Skip to content
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
2 changes: 1 addition & 1 deletion apps/hash-api/src/ai/infer-entities-websocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const inferEntitiesMessageHandler = async ({
temporalClient,
});

for (const flowRun of openFlowRuns) {
for (const flowRun of openFlowRuns.flowRuns) {
for (const inputRequest of flowRun.inputRequests) {
if (!inputRequest.resolvedAt) {
const requestMessage: ExternalInputWebsocketRequestMessage = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const handleInferEntitiesRequest = async ({
temporalClient,
});

for (const flowRun of openFlowRuns) {
for (const flowRun of openFlowRuns.flowRuns) {
const flowIsAlreadyRunningOnPage = (
flowRun.inputs[0].flowTrigger.outputs as StepOutput<
AutomaticInferenceTriggerInputs[AutomaticInferenceTriggerInputName]
Expand Down
6 changes: 4 additions & 2 deletions apps/hash-api/src/graphql/resolvers/flows/get-flow-runs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { GraphQLContext } from "../../context";
import { wereDetailedFieldsRequested } from "./shared/were-detailed-fields-requested";

export const getFlowRunsResolver: ResolverFn<
FlowRun[] | SparseFlowRun[],
{ flowRuns: FlowRun[] | SparseFlowRun[]; totalCount: number },
Record<string, never>,
Pick<GraphQLContext, "authentication" | "dataSources" | "temporal">,
QueryGetFlowRunsArgs
Expand All @@ -19,13 +19,15 @@ export const getFlowRunsResolver: ResolverFn<

const { authentication, dataSources, temporal } = context;

const { flowDefinitionIds, executionStatus } = args;
const { flowDefinitionIds, executionStatus, offset, limit } = args;

return await getFlowRuns({
authentication,
filters: {
flowDefinitionIds,
executionStatus,
offset,
limit,
},
graphApiClient: dataSources.graphApi,
includeDetails,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import type { DetailedFlowField } from "@local/hash-isomorphic-utils/flows/types";
import { detailedFlowFields } from "@local/hash-isomorphic-utils/flows/types";
import type { GraphQLResolveInfo } from "graphql";
import type { ResolveTree } from "graphql-parse-resolve-info";
import { parseResolveInfo } from "graphql-parse-resolve-info";

/**
* Works for both `getFlowRuns` (returns `PaginatedFlowRuns` wrapping `FlowRun`)
* and `getFlowRunById` (returns `FlowRun` directly).
*/
export const wereDetailedFieldsRequested = (
info: GraphQLResolveInfo,
): boolean => {
const parsedResolveInfoFragment = parseResolveInfo(info);

const requestedFieldsTree =
parsedResolveInfoFragment?.fieldsByTypeName.FlowRun;
let requestedFieldsTree = parsedResolveInfoFragment?.fieldsByTypeName.FlowRun;

if (!requestedFieldsTree) {
const paginatedFields = parsedResolveInfoFragment?.fieldsByTypeName
.PaginatedFlowRuns as Record<string, ResolveTree> | undefined;

requestedFieldsTree = paginatedFields?.flowRuns?.fieldsByTypeName.FlowRun;
}

if (!requestedFieldsTree) {
throw new Error("Expected FlowRun to be requested in query");
Expand Down
33 changes: 30 additions & 3 deletions apps/hash-frontend/src/pages/shared/flow-runs-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@ import type {
} from "../../graphql/api-types.gen";
import { FlowRunStatus, FlowStepStatus } from "../../graphql/api-types.gen";

export type FlowRunsPaginationState = {
page: number;
rowsPerPage: number;
onPageChange: (newPage: number) => void;
onRowsPerPageChange: (newRowsPerPage: number) => void;
};

export type FlowRunsContextType = {
flowRuns: GetFlowRunsQuery["getFlowRuns"];
flowRuns: GetFlowRunsQuery["getFlowRuns"]["flowRuns"];
totalCount: number;
loading: boolean;
pagination: FlowRunsPaginationState | null;
selectedFlowRun: FlowRun | null;
selectedFlowRunId: string | null;
};
Expand All @@ -28,13 +37,25 @@ export const FlowRunsContext = createContext<FlowRunsContextType | null>(null);

export const FlowRunsContextProvider = ({
children,
pagination,
selectedFlowRunId,
}: PropsWithChildren<{ selectedFlowRunId: string | null }>) => {
}: PropsWithChildren<{
pagination?: FlowRunsPaginationState;
selectedFlowRunId: string | null;
}>) => {
const variables: GetFlowRunsQueryVariables = pagination
? {
offset: pagination.page * pagination.rowsPerPage,
limit: pagination.rowsPerPage,
}
: { offset: 0, limit: 50 };

const { data: flowRunsData, loading: flowRunsLoading } = useQuery<
GetFlowRunsQuery,
GetFlowRunsQueryVariables
>(getFlowRunsQuery, {
pollInterval: 3_000,
variables,
});

const { data: selectedFlowRunData, loading: selectedFlowRunLoading } =
Expand All @@ -51,11 +72,13 @@ export const FlowRunsContextProvider = ({

const flowRuns = useMemo(() => {
if (flowRunsData) {
return flowRunsData.getFlowRuns;
return flowRunsData.getFlowRuns.flowRuns;
}
return [];
}, [flowRunsData]);

const totalCount = flowRunsData?.getFlowRuns.totalCount ?? 0;

const selectedFlowRun = useMemo(() => {
if (selectedFlowRunData) {
return selectedFlowRunData.getFlowRunById;
Expand All @@ -66,13 +89,17 @@ export const FlowRunsContextProvider = ({
const context = useMemo<FlowRunsContextType>(
() => ({
flowRuns,
totalCount,
loading: selectedFlowRunLoading || flowRunsLoading,
pagination: pagination ?? null,
selectedFlowRun,
selectedFlowRunId,
}),
[
flowRuns,
totalCount,
flowRunsLoading,
pagination,
selectedFlowRunLoading,
selectedFlowRun,
selectedFlowRunId,
Expand Down
28 changes: 26 additions & 2 deletions apps/hash-frontend/src/pages/workers.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { TerminalLightIcon } from "@hashintel/design-system";
import { workerFlowFilterParam } from "@local/hash-isomorphic-utils/flows/frontend-paths";
import { Box, Container, Stack, Typography } from "@mui/material";
import { useRouter } from "next/router";
import { useMemo } from "react";
import { useCallback, useMemo, useState } from "react";

import type { NextPageWithLayout } from "../shared/layout";
import { getLayoutWithSidebar } from "../shared/layout";
Expand All @@ -12,6 +12,8 @@ import { FlowRunsContextProvider } from "./shared/flow-runs-context";
import { FlowRunTable } from "./workers.page/flow-run-table";
import { FlowSchedulesTable } from "./workers.page/flow-schedules-table";

const defaultRowsPerPage = 20;

const WorkersPageContent = () => {
const {
query: { [workerFlowFilterParam]: definitionFilterQueryParam },
Expand Down Expand Up @@ -61,9 +63,31 @@ const WorkersPageContent = () => {
};

const WorkersPage: NextPageWithLayout = () => {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(defaultRowsPerPage);

const handlePageChange = useCallback((newPage: number) => {
setPage(newPage);
}, []);

const handleRowsPerPageChange = useCallback((newRowsPerPage: number) => {
setRowsPerPage(newRowsPerPage);
setPage(0);
}, []);

const pagination = useMemo(
() => ({
page,
rowsPerPage,
onPageChange: handlePageChange,
onRowsPerPageChange: handleRowsPerPageChange,
}),
[page, rowsPerPage, handlePageChange, handleRowsPerPageChange],
);

return (
<FlowDefinitionsContextProvider selectedFlowDefinitionId={null}>
<FlowRunsContextProvider selectedFlowRunId={null}>
<FlowRunsContextProvider pagination={pagination} selectedFlowRunId={null}>
<WorkersPageContent />
</FlowRunsContextProvider>
</FlowDefinitionsContextProvider>
Expand Down
91 changes: 81 additions & 10 deletions apps/hash-frontend/src/pages/workers.page/flow-run-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,12 @@ export const FlowRunTable = ({ flowDefinitionIdFilter }: FlowRunTableProps) => {

const { flowDefinitions } = useFlowDefinitionsContext();

const { flowRuns: unfilteredFlowRuns, loading } = useFlowRunsContext();
const {
flowRuns: unfilteredFlowRuns,
totalCount,
loading,
pagination,
} = useFlowRunsContext();

const { authenticatedUser } = useAuthenticatedUser();

Expand Down Expand Up @@ -431,15 +436,81 @@ export const FlowRunTable = ({ flowDefinitionIdFilter }: FlowRunTableProps) => {
);

return (
<Box sx={{ height: tableHeight }}>
<VirtualizedTable
columns={columns}
createRowContent={createRowContent}
EmptyPlaceholder={loading ? LoadingPlaceholder : EmptyPlaceholder}
rows={flowRunRows}
sort={sort}
setSort={setSort}
/>
<Box>
<Box sx={{ height: tableHeight }}>
<VirtualizedTable
columns={columns}
createRowContent={createRowContent}
EmptyPlaceholder={loading ? LoadingPlaceholder : EmptyPlaceholder}
rows={flowRunRows}
sort={sort}
setSort={setSort}
/>
</Box>
{pagination && totalCount > 0 && (
<Stack
direction="row"
alignItems="center"
justifyContent="space-between"
sx={{ px: 1, py: 1.5 }}
>
<Typography
sx={{ fontSize: 13, color: ({ palette }) => palette.gray[70] }}
>
Showing{" "}
<strong>{pagination.page * pagination.rowsPerPage + 1}</strong> to{" "}
<strong>
{Math.min(
(pagination.page + 1) * pagination.rowsPerPage,
totalCount,
)}
</strong>{" "}
of <strong>{totalCount}</strong>
</Typography>
<Stack direction="row" gap={2}>
{pagination.page > 0 && (
<Typography
component="button"
onClick={() => pagination.onPageChange(pagination.page - 1)}
sx={{
fontSize: 13,
fontWeight: 600,
color: ({ palette }) => palette.blue[70],
cursor: "pointer",
background: "none",
border: "none",
padding: 0,
"&:hover": {
textDecoration: "underline",
},
}}
>
Previous page
</Typography>
)}
{(pagination.page + 1) * pagination.rowsPerPage < totalCount && (
<Typography
component="button"
onClick={() => pagination.onPageChange(pagination.page + 1)}
sx={{
fontSize: 13,
fontWeight: 600,
color: ({ palette }) => palette.blue[70],
cursor: "pointer",
background: "none",
border: "none",
padding: 0,
"&:hover": {
textDecoration: "underline",
},
}}
>
Next page
</Typography>
)}
</Stack>
</Stack>
)}
</Box>
);
};
23 changes: 13 additions & 10 deletions apps/plugin-browser/src/graphql/queries/flow.queries.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
export const getMinimalFlowRunsQuery = /* GraphQL */ `
query getMinimalFlowRuns {
getFlowRuns {
name
flowDefinitionId
flowRunId
webId
status
executedAt
closedAt
inputs
inputRequests
outputs
totalCount
flowRuns {
name
flowDefinitionId
flowRunId
webId
status
executedAt
closedAt
inputs
inputRequests
outputs
}
}
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { useStorageSync } from "../../../../shared/use-storage-sync";
import { useUserContext } from "../../shared/user-context";

const mapFlowRunToMinimalFlowRun = (
flowRun: GetMinimalFlowRunsQuery["getFlowRuns"][number],
flowRun: GetMinimalFlowRunsQuery["getFlowRuns"]["flowRuns"][number],
): MinimalFlowRun => {
const persistedEntities = (flowRun.outputs ?? []).flatMap((output) =>
(output.contents[0]?.outputs ?? []).flatMap(({ outputName, payload }) => {
Expand Down Expand Up @@ -75,7 +75,7 @@ const getFlowRuns = async ({
getMinimalFlowRunsQuery,
)
.then(({ data }) =>
data.getFlowRuns.sort((a, b) => {
data.getFlowRuns.flowRuns.sort((a, b) => {
if (!a.executedAt) {
return b.executedAt ? 1 : 0;
}
Expand Down
Loading
Loading