Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable server-side pagination for deployments, containers, and releases #781

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 32 additions & 23 deletions frontend/src/components/ContainersTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Edgehog.

Copyright 2024 SECO Mind Srl
Copyright 2024-2025 SECO Mind Srl

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,8 +19,9 @@
*/

import { FormattedMessage } from "react-intl";
import { graphql, useFragment } from "react-relay/hooks";
import { graphql, usePaginationFragment } from "react-relay/hooks";

import type { ContainersTable_PaginationQuery } from "api/__generated__/ContainersTable_PaginationQuery.graphql";
import type {
ContainersTable_ContainerFragment$data,
ContainersTable_ContainerFragment$key,
Expand All @@ -31,24 +32,28 @@ import Table, { createColumnHelper } from "components/Table";
// We use graphql fields below in columns configuration
/* eslint-disable relay/unused-fields */
const CONTAINERS_TABLE_FRAGMENT = graphql`
fragment ContainersTable_ContainerFragment on ContainerConnection {
edges {
node {
id
portBindings
image {
reference
credentials {
label
username
fragment ContainersTable_ContainerFragment on Release
@refetchable(queryName: "ContainersTable_PaginationQuery") {
containers(first: $first, after: $after)
@connection(key: "ContainersTable_containers") {
edges {
node {
id
portBindings
image {
reference
credentials {
label
username
}
}
}
networks {
edges {
node {
id
driver
internal
networks {
edges {
node {
id
driver
internal
}
}
}
}
Expand All @@ -58,7 +63,7 @@ const CONTAINERS_TABLE_FRAGMENT = graphql`
`;

type TableRecord = NonNullable<
ContainersTable_ContainerFragment$data["edges"]
ContainersTable_ContainerFragment$data["containers"]["edges"]
>[number]["node"];

const columnHelper = createColumnHelper<TableRecord>();
Expand Down Expand Up @@ -171,14 +176,18 @@ const ContainersTable = ({
containersRef,
hideSearch = false,
}: ContainersTableProps) => {
const containers = useFragment(CONTAINERS_TABLE_FRAGMENT, containersRef);
const data = containers.edges?.map((edge) => edge.node) || [];
const { data } = usePaginationFragment<
ContainersTable_PaginationQuery,
ContainersTable_ContainerFragment$key
>(CONTAINERS_TABLE_FRAGMENT, containersRef);

const tableData = data.containers.edges?.map((edge) => edge.node) ?? [];

return (
<Table
className={className}
columns={columns}
data={data}
data={tableData}
hideSearch={hideSearch}
/>
);
Expand Down
17 changes: 12 additions & 5 deletions frontend/src/components/DeployedApplicationsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Edgehog.

Copyright 2024 SECO Mind Srl
Copyright 2024-2025 SECO Mind Srl

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,10 +19,11 @@
*/

import { defineMessages, FormattedMessage, useIntl } from "react-intl";
import { graphql, useFragment, useMutation } from "react-relay/hooks";
import { graphql, useMutation, usePaginationFragment } from "react-relay/hooks";
import { useCallback, useState } from "react";
import semver from "semver";

import type { DeployedApplicationsTable_PaginationQuery } from "api/__generated__/DeployedApplicationsTable_PaginationQuery.graphql";
import type {
ApplicationDeploymentStatus,
DeployedApplicationsTable_deployedApplications$key,
Expand All @@ -44,8 +45,10 @@ import Form from "components/Form";
// We use graphql fields below in columns configuration
/* eslint-disable relay/unused-fields */
const DEPLOYED_APPLICATIONS_TABLE_FRAGMENT = graphql`
fragment DeployedApplicationsTable_deployedApplications on Device {
applicationDeployments {
fragment DeployedApplicationsTable_deployedApplications on Device
@refetchable(queryName: "DeployedApplicationsTable_PaginationQuery") {
applicationDeployments(first: $first, after: $after)
@connection(key: "DeployedApplicationsTable_applicationDeployments") {
edges {
node {
id
Expand Down Expand Up @@ -276,7 +279,11 @@ const DeployedApplicationsTable = ({
setErrorFeedback,
onDeploymentChange,
}: DeploymentTableProps) => {
const data = useFragment(DEPLOYED_APPLICATIONS_TABLE_FRAGMENT, deviceRef);
const { data } = usePaginationFragment<
DeployedApplicationsTable_PaginationQuery,
DeployedApplicationsTable_deployedApplications$key
>(DEPLOYED_APPLICATIONS_TABLE_FRAGMENT, deviceRef);

const intl = useIntl();

const [upgradeTargetRelease, setUpgradeTargetRelease] =
Expand Down
33 changes: 21 additions & 12 deletions frontend/src/components/ReleasesTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Edgehog.

Copyright 2024 SECO Mind Srl
Copyright 2024-2025 SECO Mind Srl

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,8 +19,9 @@
*/

import { FormattedMessage } from "react-intl";
import { graphql, useFragment } from "react-relay/hooks";
import { graphql, usePaginationFragment } from "react-relay/hooks";

import type { ReleasesTable_PaginationQuery } from "api/__generated__/ReleasesTable_PaginationQuery.graphql";
import type {
ReleasesTable_ReleaseFragment$data,
ReleasesTable_ReleaseFragment$key,
Expand All @@ -32,21 +33,25 @@ import Table, { createColumnHelper } from "components/Table";
// We use graphql fields below in columns configuration
/* eslint-disable relay/unused-fields */
const RELEASES_TABLE_FRAGMENT = graphql`
fragment ReleasesTable_ReleaseFragment on ReleaseConnection {
edges {
node {
id
version
application {
fragment ReleasesTable_ReleaseFragment on Application
@refetchable(queryName: "ReleasesTable_PaginationQuery") {
releases(first: $first, after: $after)
@connection(key: "ReleasesTable_releases") {
edges {
node {
id
version
application {
id
}
}
}
}
}
`;

type TableRecord = NonNullable<
ReleasesTable_ReleaseFragment$data["edges"]
ReleasesTable_ReleaseFragment$data["releases"]["edges"]
>[number]["node"];

const columnHelper = createColumnHelper<TableRecord>();
Expand Down Expand Up @@ -84,14 +89,18 @@ const ReleasesTable = ({
releasesRef,
hideSearch = false,
}: ReleaseTableProps) => {
const release = useFragment(RELEASES_TABLE_FRAGMENT, releasesRef);
const data = release.edges ? release.edges.map((edge) => edge.node) : [];
const { data } = usePaginationFragment<
ReleasesTable_PaginationQuery,
ReleasesTable_ReleaseFragment$key
>(RELEASES_TABLE_FRAGMENT, releasesRef);

const tableData = data.releases.edges?.map((edge) => edge.node) ?? [];

return (
<Table
className={className}
columns={columns}
data={data}
data={tableData}
hideSearch={hideSearch}
/>
);
Expand Down
20 changes: 13 additions & 7 deletions frontend/src/pages/Application.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Edgehog.

Copyright 2024 SECO Mind Srl
Copyright 2024-2025 SECO Mind Srl

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,13 +41,15 @@ import ReleasesTable from "components/ReleasesTable";
import Button from "components/Button";

const GET_APPLICATION_QUERY = graphql`
query Application_getApplication_Query($applicationId: ID!) {
query Application_getApplication_Query(
$applicationId: ID!
$first: Int
$after: String
) {
application(id: $applicationId) {
name
description
releases(first: 10000) {
...ReleasesTable_ReleaseFragment
}
...ReleasesTable_ReleaseFragment
}
}
`;
Expand Down Expand Up @@ -102,7 +104,7 @@ const ApplicationContent = ({ application }: ApplicationContentProps) => {
/>
</Col>
</Form.Group>
<ReleasesTable releasesRef={application.releases} hideSearch />
<ReleasesTable releasesRef={application} hideSearch />
</Page.Main>
</Page>
);
Expand Down Expand Up @@ -150,7 +152,11 @@ const ApplicationPage = () => {
useQueryLoader<Application_getApplication_Query>(GET_APPLICATION_QUERY);

const fetchApplication = useCallback(
() => getApplication({ applicationId }, { fetchPolicy: "network-only" }),
() =>
getApplication(
{ applicationId, first: 10_000 },
{ fetchPolicy: "network-only" },
),
[getApplication, applicationId],
);

Expand Down
11 changes: 7 additions & 4 deletions frontend/src/pages/Device.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Edgehog.

Copyright 2021-2024 SECO Mind Srl
Copyright 2021-2025 SECO Mind Srl

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -226,7 +226,7 @@ const DEVICE_CONNECTION_STATUS_FRAGMENT = graphql`
`;

const GET_DEVICE_QUERY = graphql`
query Device_getDevice_Query($id: ID!) {
query Device_getDevice_Query($id: ID!, $first: Int, $after: String) {
forwarderConfig {
__typename
}
Expand Down Expand Up @@ -562,7 +562,10 @@ const ApplicationsTab = ({ deviceRef }: ApplicationsTabProps) => {
const isOnline = useMemo(() => device?.online ?? false, [device]);

const handleRefetch = useCallback(() => {
refetch({ id: device?.id }, { fetchPolicy: "store-and-network" });
refetch(
{ id: device?.id, first: 10_000 },
{ fetchPolicy: "store-and-network" },
);
}, [refetch, device?.id]);

useEffect(() => {
Expand Down Expand Up @@ -2010,7 +2013,7 @@ const DevicePage = () => {
);

useEffect(() => {
getDevice({ id: deviceId });
getDevice({ id: deviceId, first: 10_000 });
refreshTags();
}, [getDevice, deviceId, refreshTags]);

Expand Down
13 changes: 6 additions & 7 deletions frontend/src/pages/Release.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
This file is part of Edgehog.

Copyright 2024 SECO Mind Srl
Copyright 2024-2025 SECO Mind Srl

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,15 +39,13 @@ import Spinner from "components/Spinner";
import ContainersTable from "components/ContainersTable";

const GET_RELEASE_QUERY = graphql`
query Release_getRelease_Query($releaseId: ID!) {
query Release_getRelease_Query($releaseId: ID!, $first: Int, $after: String) {
release(id: $releaseId) {
version
application {
name
}
containers {
...ContainersTable_ContainerFragment
}
...ContainersTable_ContainerFragment
}
}
`;
Expand All @@ -73,7 +71,7 @@ const ReleaseContent = ({ release }: ReleaseContentProps) => {
>
{errorFeedback}
</Alert>
<ContainersTable containersRef={release.containers} />
<ContainersTable containersRef={release} />
</Page.Main>
</Page>
);
Expand Down Expand Up @@ -116,7 +114,8 @@ const ReleasePage = () => {
useQueryLoader<Release_getRelease_Query>(GET_RELEASE_QUERY);

const fetchRelease = useCallback(
() => getRelease({ releaseId }, { fetchPolicy: "network-only" }),
() =>
getRelease({ releaseId, first: 10_000 }, { fetchPolicy: "network-only" }),
[getRelease, releaseId],
);

Expand Down
Loading