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

H-3609: Reduce cost of polling for notification and draft entities counts #5838

Merged
merged 7 commits into from
Dec 11, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const getEntitySubgraphQuery = gql`
) {
getEntitySubgraph(request: $request) {
closedMultiEntityTypes
count
definitions
userPermissionsOnEntities @include(if: $includePermissions)
subgraph {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useRouter } from "next/router";
import type { ReactNode } from "react";
import { useContext } from "react";

import { NotificationsWithLinksContextProvider } from "../../../../shared/notifications-with-links-context";
import { TopContextBar } from "../../../../shared/top-context-bar";
import { WorkspaceContext } from "../../../../shared/workspace-context";
import { EntityEditorTabs } from "../shared/entity-editor-tabs";
Expand Down Expand Up @@ -84,19 +83,17 @@ export const EntityPageHeader = ({
/>

{entity && entitySubgraph ? (
<NotificationsWithLinksContextProvider>
<Collapse
in={!!extractDraftIdFromEntityId(entity.metadata.recordId.entityId)}
>
<DraftEntityBanner
draftEntity={entity}
draftEntitySubgraph={entitySubgraph}
isModifyingEntity={isModifyingEntity}
onAcceptedEntity={onEntityUpdated}
owningShortname={shortname}
/>
</Collapse>
</NotificationsWithLinksContextProvider>
<Collapse
in={!!extractDraftIdFromEntityId(entity.metadata.recordId.entityId)}
>
<DraftEntityBanner
draftEntity={entity}
draftEntitySubgraph={entitySubgraph}
isModifyingEntity={isModifyingEntity}
onAcceptedEntity={onEntityUpdated}
owningShortname={shortname}
/>
</Collapse>
) : null}

{editBar}
Expand Down
12 changes: 6 additions & 6 deletions apps/hash-frontend/src/pages/_app.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ import { hasAccessToHashQuery, meQuery } from "../graphql/queries/user.queries";
import { apolloClient } from "../lib/apollo-client";
import type { MinimalUser } from "../lib/user-and-org";
import { constructMinimalUser } from "../lib/user-and-org";
import { DraftEntitiesContextProvider } from "../shared/draft-entities-context";
import { DraftEntitiesCountContextProvider } from "../shared/draft-entities-count-context";
import { EntityTypesContextProvider } from "../shared/entity-types-context/provider";
import { FileUploadsProvider } from "../shared/file-upload-context";
import { KeyboardShortcutsContextProvider } from "../shared/keyboard-shortcuts-context";
import type { NextPageWithLayout } from "../shared/layout";
import { getLayoutWithSidebar, getPlainLayout } from "../shared/layout";
import { SidebarContextProvider } from "../shared/layout/layout-with-sidebar/sidebar-context";
import { NotificationEntitiesContextProvider } from "../shared/notification-entities-context";
import { NotificationCountContextProvider } from "../shared/notification-count-context";
import { PropertyTypesContextProvider } from "../shared/property-types-context";
import { RoutePageInfoProvider } from "../shared/routing";
import { ErrorFallback } from "./_app.page/error-fallback";
Expand Down Expand Up @@ -108,8 +108,8 @@ const App: FunctionComponent<AppProps> = ({
<WorkspaceContextProvider>
<KeyboardShortcutsContextProvider>
<SnackbarProvider maxSnack={3}>
<NotificationEntitiesContextProvider>
<DraftEntitiesContextProvider>
<NotificationCountContextProvider>
<DraftEntitiesCountContextProvider>
<EntityTypesContextProvider>
<PropertyTypesContextProvider includeArchived>
<DataTypesContextProvider>
Expand All @@ -132,8 +132,8 @@ const App: FunctionComponent<AppProps> = ({
</DataTypesContextProvider>
</PropertyTypesContextProvider>
</EntityTypesContextProvider>
</DraftEntitiesContextProvider>
</NotificationEntitiesContextProvider>
</DraftEntitiesCountContextProvider>
</NotificationCountContextProvider>
</SnackbarProvider>
</KeyboardShortcutsContextProvider>
</WorkspaceContextProvider>
Expand Down
24 changes: 17 additions & 7 deletions apps/hash-frontend/src/pages/actions.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,26 @@ import type {
GetEntitySubgraphQueryVariables,
} from "../graphql/api-types.gen";
import { getEntitySubgraphQuery } from "../graphql/queries/knowledge/entity.queries";
import { useDraftEntities } from "../shared/draft-entities-context";
import { BarsSortRegularIcon } from "../shared/icons/bars-sort-regular-icon";
import type { NextPageWithLayout } from "../shared/layout";
import { getLayoutWithSidebar } from "../shared/layout";
import { MenuItem } from "../shared/ui";
import type { SortOrder } from "./actions.page/draft-entities";
import { DraftEntities } from "./actions.page/draft-entities";
import { DraftEntitiesBulkActionsDropdown } from "./actions.page/draft-entities-bulk-actions-dropdown";
import {
DraftEntitiesContextProvider,
useDraftEntities,
} from "./actions.page/draft-entities-context";
import { InlineSelect } from "./shared/inline-select";
import { NotificationsWithLinksContextProvider } from "./shared/notifications-with-links-context";
import { TopContextBar } from "./shared/top-context-bar";

const sortOrderHumanReadable: Record<SortOrder, string> = {
"created-at-asc": "creation date/time (oldest first)",
"created-at-desc": "creation date/time (newest first)",
};

const ActionsPage: NextPageWithLayout = () => {
const ActionsPage = () => {
const [selectedDraftEntityIds, setSelectedDraftEntityIds] = useState<
EntityId[]
>([]);
Expand Down Expand Up @@ -117,7 +119,7 @@ const ActionsPage: NextPageWithLayout = () => {
);

return (
<NotificationsWithLinksContextProvider>
<>
<NextSeo title="Actions" />
<TopContextBar
defaultCrumbIcon={null}
Expand Down Expand Up @@ -201,13 +203,21 @@ const ActionsPage: NextPageWithLayout = () => {
draftEntitiesWithLinkedDataSubgraph
}
/>
</NotificationsWithLinksContextProvider>
</>
);
};

const ActionsPageOuter: NextPageWithLayout = () => {
return (
<DraftEntitiesContextProvider>
<ActionsPage />
</DraftEntitiesContextProvider>
);
};

ActionsPage.getLayout = (page) =>
ActionsPageOuter.getLayout = (page) =>
getLayoutWithSidebar(page, {
fullWidth: true,
});

export default ActionsPage;
export default ActionsPageOuter;
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ import {
archiveEntitiesMutation,
updateEntitiesMutation,
} from "../../graphql/queries/knowledge/entity.queries";
import { useDraftEntities } from "../../shared/draft-entities-context";
import { LayerGroupLightIcon } from "../../shared/icons/layer-group-light-icon";
import { useNotificationEntities } from "../../shared/notification-entities-context";
import { useNotificationCount } from "../../shared/notification-count-context";
import { Button, MenuItem } from "../../shared/ui";
import { useNotificationsWithLinks } from "../shared/notifications-with-links-context";
import { useDraftEntities } from "./draft-entities-context";

export const DraftEntitiesBulkActionsDropdown: FunctionComponent<{
selectedDraftEntityIds: EntityId[];
Expand All @@ -44,9 +43,8 @@ export const DraftEntitiesBulkActionsDropdown: FunctionComponent<{
deselectAllDraftEntities,
}) => {
const { draftEntities, refetch: refetchDraftEntities } = useDraftEntities();
const { notifications } = useNotificationsWithLinks();
const { archiveNotifications, markNotificationsAsRead } =
useNotificationEntities();
const { archiveNotificationsForEntity, markNotificationsAsReadForEntity } =
useNotificationCount();

const popupState = usePopupState({
variant: "popover",
Expand Down Expand Up @@ -108,41 +106,37 @@ export const DraftEntitiesBulkActionsDropdown: FunctionComponent<{
>(archiveEntitiesMutation);

const ignoreAllSelectedDraftEntities = useCallback(async () => {
if (!notifications) {
if (!selectedDraftEntities.length) {
return;
}

const relatedNotifications = notifications.filter((notification) =>
selectedDraftEntityIds.includes(
notification.occurredInEntity.metadata.recordId.entityId,
),
);

await archiveEntities({
variables: {
entityIds: [
...selectedDraftEntities,
...(incomingOrOutgoingDraftLinksToIgnore ?? []),
].map(({ metadata }) => metadata.recordId.entityId),
...selectedDraftEntityIds,
...(incomingOrOutgoingDraftLinksToIgnore ?? []).map(
({ metadata }) => metadata.recordId.entityId,
),
],
},
});

await archiveNotifications({
notificationEntities: relatedNotifications.map(({ entity }) => entity),
});

await Promise.all(
selectedDraftEntityIds.map((entityId) =>
archiveNotificationsForEntity({ targetEntityId: entityId }),
),
);
await refetchDraftEntities();

deselectAllDraftEntities();
}, [
notifications,
archiveNotifications,
archiveEntities,
selectedDraftEntityIds,
selectedDraftEntities,
refetchDraftEntities,
incomingOrOutgoingDraftLinksToIgnore,
archiveNotificationsForEntity,
deselectAllDraftEntities,
incomingOrOutgoingDraftLinksToIgnore,
refetchDraftEntities,
selectedDraftEntities,
selectedDraftEntityIds,
]);

const [
Expand Down Expand Up @@ -222,15 +216,6 @@ export const DraftEntitiesBulkActionsDropdown: FunctionComponent<{
>(updateEntitiesMutation);

const acceptAllSelectedDraftEntities = useCallback(async () => {
const relatedGraphChangeNotifications =
notifications?.filter(
({ kind, occurredInEntity }) =>
kind === "graph-change" &&
selectedDraftEntityIds.includes(
occurredInEntity.metadata.recordId.entityId,
),
) ?? [];

await updateEntities({
variables: {
entityUpdates: [
Expand All @@ -244,24 +229,24 @@ export const DraftEntitiesBulkActionsDropdown: FunctionComponent<{
},
});

await markNotificationsAsRead({
notificationEntities: relatedGraphChangeNotifications.map(
({ entity }) => entity,
await Promise.all(
selectedDraftEntities.map((entity) =>
markNotificationsAsReadForEntity({
targetEntityId: entity.entityId,
}),
),
});
);

await refetchDraftEntities();

deselectAllDraftEntities();
}, [
notifications,
markNotificationsAsRead,
selectedDraftEntityIds,
selectedDraftEntities,
deselectAllDraftEntities,
leftOrRightDraftEntitiesToAccept,
updateEntities,
markNotificationsAsReadForEntity,
refetchDraftEntities,
deselectAllDraftEntities,
selectedDraftEntities,
updateEntities,
]);

const [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import { createContext, useContext, useMemo, useState } from "react";
import type {
GetEntitySubgraphQuery,
GetEntitySubgraphQueryVariables,
} from "../graphql/api-types.gen";
import { getEntitySubgraphQuery } from "../graphql/queries/knowledge/entity.queries";
import { useAuthInfo } from "../pages/shared/auth-info-context";
import { pollInterval } from "./poll-interval";
} from "../../graphql/api-types.gen";
import { getEntitySubgraphQuery } from "../../graphql/queries/knowledge/entity.queries";
import { useDraftEntitiesCount } from "../../shared/draft-entities-count-context";
import { pollInterval } from "../../shared/poll-interval";
import { useAuthInfo } from "../shared/auth-info-context";

export type DraftEntitiesContextValue = {
draftEntities?: Entity[];
Expand All @@ -38,6 +39,10 @@ export const useDraftEntities = () => {
return draftEntitiesContext;
};

/**
* Context to provide full information of draft entities, for use in the actions page.
* A separate app-wide context provides simply a count of draft entities.
*/
export const DraftEntitiesContextProvider: FunctionComponent<
PropsWithChildren
> = ({ children }) => {
Expand All @@ -48,9 +53,11 @@ export const DraftEntitiesContextProvider: FunctionComponent<

const { authenticatedUser } = useAuthInfo();

const { refetch: refetchDraftEntitiesCount } = useDraftEntitiesCount();

const {
data: draftEntitiesData,
refetch,
refetch: refetchFullData,
loading,
} = useQuery<GetEntitySubgraphQuery, GetEntitySubgraphQueryVariables>(
getEntitySubgraphQuery,
Expand Down Expand Up @@ -104,10 +111,17 @@ export const DraftEntitiesContextProvider: FunctionComponent<
draftEntitiesSubgraph,
loading,
refetch: async () => {
await refetch();
await refetchFullData();
await refetchDraftEntitiesCount();
},
}),
[draftEntities, draftEntitiesSubgraph, loading, refetch],
[
draftEntities,
draftEntitiesSubgraph,
loading,
refetchFullData,
refetchDraftEntitiesCount,
],
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
useState,
} from "react";

import { useDraftEntities } from "../../shared/draft-entities-context";
import { Button } from "../../shared/ui";
import type { MinimalActor } from "../../shared/use-actors";
import { useActors } from "../../shared/use-actors";
Expand All @@ -30,6 +29,7 @@ import {
getDraftEntityTypes,
isFilerStateDefaultFilterState,
} from "./draft-entities/draft-entities-filters";
import { useDraftEntities } from "./draft-entities-context";
import { DraftEntity } from "./draft-entity";

const incrementNumberOfEntitiesToDisplay = 20;
Expand Down
2 changes: 1 addition & 1 deletion apps/hash-frontend/src/pages/actions.page/draft-entity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { Box, Checkbox, Typography } from "@mui/material";
import type { FunctionComponent } from "react";
import { useMemo, useState } from "react";

import { useDraftEntities } from "../../shared/draft-entities-context";
import { ArrowUpRightRegularIcon } from "../../shared/icons/arrow-up-right-regular-icon";
import { Link } from "../../shared/ui";
import { EntityEditorSlideStack } from "../shared/entity-editor-slide-stack";
import { useEntityHref } from "../shared/use-entity-href";
import { useDraftEntities } from "./draft-entities-context";
import { DraftEntityActionButtons } from "./draft-entity/draft-entity-action-buttons";
import { DraftEntityProvenance } from "./draft-entity/draft-entity-provenance";
import { DraftEntityType } from "./draft-entity/draft-entity-type";
Expand Down
Loading
Loading