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
7 changes: 3 additions & 4 deletions apps/hash-api/src/graphql/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ export const resolvers: Omit<Resolvers, "Query" | "Mutation"> & {
/** Logged in users (who may not have completed signup) */
me: loggedInMiddleware(meResolver),
getWaitlistPosition: loggedInMiddleware(getWaitlistPositionResolver),
getMyPendingInvitations: loggedInMiddleware(
getMyPendingInvitationsResolver,
),

/** Logged in and signed up users */
getBlockProtocolBlocks: loggedInAndSignedUpMiddleware(
Expand All @@ -166,10 +169,6 @@ export const resolvers: Omit<Resolvers, "Query" | "Mutation"> & {
queryEntitySubgraph: loggedInAndSignedUpMiddleware(
queryEntitySubgraphResolver,
),
getMyPendingInvitations: loggedInAndSignedUpMiddleware(
getMyPendingInvitationsResolver,
),

getLinearOrganization: loggedInAndSignedUpMiddleware(
getLinearOrganizationResolver,
),
Expand Down
7 changes: 1 addition & 6 deletions apps/hash-frontend/src/pages/_app.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,7 @@ const featureFlagHiddenPathnames: Record<FeatureFlag, string[]> = {
notes: ["/notes"],
workers: ["/goals", "/flows", "/workers", "/agents"],
ai: ["/goals"],
supplyChain: [
"/supply-chain",
"/supply-chain/product/[product-id]",
"/supply-chain/site/[site-id]",
"/supply-chain/site/[site-id]/opportunity/[opportunity-type]/[product-id]/[step-id]",
],
supplyChain: [],
Comment thread
CiaranMn marked this conversation as resolved.
Comment thread
CiaranMn marked this conversation as resolved.
};

AppWithTypeSystemContextProvider.getInitialProps = async (appContext) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ export const EntitiesVisualizer: FunctionComponent<{
currentlyDisplayedColumnsRef={currentlyDisplayedColumnsRef}
currentlyDisplayedRowsRef={currentlyDisplayedRowsRef}
handleEntityClick={handleEntityClick}
hasMoreRowsAvailable={nextCursor != null}
loading={dataLoading}
isViewingOnlyPages={isViewingOnlyPages}
maxHeight={`calc(${tableHeight} - ${toolbarHeight}px)`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const EntitiesTable: FunctionComponent<
loading: boolean;
isViewingOnlyPages: boolean;
maxHeight: string | number;
hasMoreRowsAvailable: boolean;
loadMoreRows?: () => void;
selectedRows: EntitiesTableRow[];
setActiveConversions: Dispatch<
Expand Down Expand Up @@ -136,6 +137,7 @@ export const EntitiesTable: FunctionComponent<
loading: entityDataLoading,
isViewingOnlyPages,
maxHeight,
hasMoreRowsAvailable,
loadMoreRows,
selectedRows,
setActiveConversions,
Expand Down Expand Up @@ -810,8 +812,6 @@ export const EntitiesTable: FunctionComponent<
});
}, [rows.length]);

const hasMoreRowsAvailable =
!!totalResultCount && totalResultCount > rows.length;
const loadMoreRowHeight = 60;

return (
Expand Down Expand Up @@ -906,7 +906,9 @@ export const EntitiesTable: FunctionComponent<
component="span"
sx={{ color: ({ palette }) => palette.gray[50], ml: 0.5 }}
>
- {formatNumber(totalResultCount - rows.length)} remaining
{totalResultCount != null
? `- ${formatNumber(totalResultCount - rows.length)} remaining`
: ""}
Comment thread
CiaranMn marked this conversation as resolved.
</Box>
<ArrowDownRegularIcon
sx={{
Expand Down
39 changes: 35 additions & 4 deletions apps/hash-frontend/src/pages/signup.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ import { AlertModal, ArrowUpRightRegularIcon } from "@hashintel/design-system";
import { useUpdateAuthenticatedUser } from "../components/hooks/use-update-authenticated-user";
import {
acceptOrgInvitationMutation,
getMyPendingInvitationsQuery,
getPendingInvitationByEntityIdQuery,
} from "../graphql/queries/knowledge/org.queries";
import { hasAccessToHashQuery } from "../graphql/queries/user.queries";
import { useInvites } from "../shared/invites-context";
import { getPlainLayout } from "../shared/layout";
import { Button } from "../shared/ui";
import { useAuthInfo } from "./shared/auth-info-context";
import { AuthLayout } from "./shared/auth-layout";
import { parseGraphQLError } from "./shared/auth-utils";
import { VerifyEmailStep } from "./shared/verify-email-step";
import { useActiveWorkspace } from "./shared/workspace-context";
import { AcceptOrgInvitation } from "./signup.page/accept-org-invitation";
import { AccountSetupForm } from "./signup.page/account-setup-form";
import { SignupRegistrationForm } from "./signup.page/signup-registration-form";
Expand All @@ -26,6 +29,8 @@ import { SignupSteps } from "./signup.page/signup-steps";
import type {
AcceptOrgInvitationMutation,
AcceptOrgInvitationMutationVariables,
GetMyPendingInvitationsQuery,
GetMyPendingInvitationsQueryVariables,
GetPendingInvitationByEntityIdQuery,
GetPendingInvitationByEntityIdQueryVariables,
HasAccessToHashQuery,
Expand Down Expand Up @@ -95,6 +100,8 @@ const SignupPage: NextPageWithLayout = () => {

const { authenticatedUser, refetch: refetchAuthenticatedUser } =
useAuthInfo();
const { refetch: refetchInvites } = useInvites();
const { updateActiveWorkspaceWebId } = useActiveWorkspace();

const userHasVerifiedEmail =
authenticatedUser?.emails.find(({ verified }) => verified) !== undefined;
Expand Down Expand Up @@ -139,12 +146,24 @@ const SignupPage: NextPageWithLayout = () => {
skip: !invitationId,
});

const { data: pendingInvitationsData, loading: pendingInvitationsLoading } =
useQuery<
GetMyPendingInvitationsQuery,
GetMyPendingInvitationsQueryVariables
>(getMyPendingInvitationsQuery, {
skip: !!invitationId || !authenticatedUser || !userHasVerifiedEmail,
});

const [acceptInvitation] = useMutation<
AcceptOrgInvitationMutation,
AcceptOrgInvitationMutationVariables
>(acceptOrgInvitationMutation);

const invitation = invitationData?.getPendingInvitationByEntityId;
const invitation =
invitationData?.getPendingInvitationByEntityId ??
pendingInvitationsData?.getMyPendingInvitations[0];

const loadingInvitation = invitationLoading || pendingInvitationsLoading;
Comment thread
CiaranMn marked this conversation as resolved.

const [acceptingInvitation, setAcceptingInvitation] = useState(false);
const acceptingInvitationEntityIdRef = useRef<EntityId | undefined>(
Expand Down Expand Up @@ -220,7 +239,9 @@ const SignupPage: NextPageWithLayout = () => {
})
.then(async (result) => {
if (result?.accepted || result?.alreadyAMember) {
refetchInvites();
Comment thread
CiaranMn marked this conversation as resolved.
await refetchAuthenticatedUser();
updateActiveWorkspaceWebId(invitation.org.webId);
void router.replace("/");
return;
}
Expand All @@ -245,15 +266,17 @@ const SignupPage: NextPageWithLayout = () => {
clearInvitationAcceptanceReservation,
invitation,
refetchAuthenticatedUser,
refetchInvites,
router,
updateActiveWorkspaceWebId,
]);

useEffect(() => {
if (
router.isReady &&
authenticatedUser?.accountSignupComplete &&
invitationId &&
!invitationLoading &&
!loadingInvitation &&
!invitation &&
!acceptingInvitation
) {
Expand All @@ -264,7 +287,7 @@ const SignupPage: NextPageWithLayout = () => {
authenticatedUser?.accountSignupComplete,
invitation,
invitationId,
invitationLoading,
loadingInvitation,
router,
]);

Expand Down Expand Up @@ -340,15 +363,21 @@ const SignupPage: NextPageWithLayout = () => {
}

await refetchAuthenticatedUser();
refetchInvites();
Comment thread
CiaranMn marked this conversation as resolved.
if (invitation) {
updateActiveWorkspaceWebId(invitation.org.webId);
}

void router.push("/");
},
[
acceptInvitationOnce,
clearInvitationAcceptanceReservation,
invitation,
refetchInvites,
refetchAuthenticatedUser,
updateAuthenticatedUser,
updateActiveWorkspaceWebId,
router,
],
);
Expand Down Expand Up @@ -395,7 +424,9 @@ const SignupPage: NextPageWithLayout = () => {
>
<Grid container columnSpacing={16}>
<Grid item xs={12} md={7}>
{invitationLoading ? null : invitation && showInvitationStep ? (
{loadingInvitation ? null : invitation &&
Comment thread
CiaranMn marked this conversation as resolved.
showInvitationStep &&
!authenticatedUser ? (
<AcceptOrgInvitation
invitation={invitation}
onAccept={() => setShowInvitationStep(false)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useCallback, useEffect, useState } from "react";
import { css } from "@hashintel/ds-helpers/css";

import { fetchGraph } from "../shared/data";
import { ErrorState, LoadingState } from "../shared/load-state";
import { ErrorState, SupplyChainAppSkeleton } from "../shared/load-state";
import { getSupplyChainLayout } from "../shared/supply-chain-layout";
import {
trackSupplyChainError,
Expand All @@ -16,7 +16,6 @@ import { Overview } from "../supply-chain-data-shell/product";
import type { NextPageWithLayout } from "../../../shared/layout";
import type { GraphData } from "../shared/types";

const loadingH = css({ h: "64" });
const errorPad = css({ px: "6", py: "4" });

const ProductPage: NextPageWithLayout = () => {
Expand Down Expand Up @@ -79,9 +78,7 @@ const ProductPage: NextPageWithLayout = () => {
}, [productId]);

if (loading) {
return (
<LoadingState message="Loading product data..." className={loadingH} />
);
return <SupplyChainAppSkeleton />;
}
if (error) {
return <ErrorState message={error} className={errorPad} />;
Expand Down
57 changes: 57 additions & 0 deletions apps/hash-frontend/src/pages/supply-chain/shared/load-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,43 @@ const loadingRow = css({
});
const loadingText = css({ textStyle: "sm", color: "fg.subtle" });
const errorText = css({ textStyle: "sm", color: "status.error.fg.body" });
const appSkeletonRoot = css({
display: "flex",
flexDirection: "column",
flex: "1",
minH: "0",
h: "full",
w: "full",
bg: "bgSolid.min",
});
const appSkeletonTopBar = css({
display: "flex",
alignItems: "center",
px: "6",
py: "3",
borderBottomWidth: "1px",
borderColor: "bd.subtle",
flexShrink: 0,
});
const appSkeletonSitePicker = css({
h: "10",
w: "64",
maxW: "[min(260px,45vw)]",
rounded: "md",
bg: "bg.subtle",
});
const appSkeletonContent = css({
flex: "1",
minH: "0",
p: "6",
display: "flex",
});
const appSkeletonContentBlock = css({
flex: "1",
minH: "[280px]",
rounded: "lg",
bg: "bg.subtle",
});

/** Centered, muted "loading…" message with a ds spinner. Size the area via `className` (e.g. `h-32`). */
export const LoadingState = ({
Expand All @@ -33,6 +70,26 @@ export const LoadingState = ({
);
};

/** Supply-chain route loading skeleton matching the page chrome. */
export const SupplyChainAppSkeleton = ({
className,
}: {
className?: string;
}) => (
<div
aria-label="Loading"
className={cx(appSkeletonRoot, className)}
role="status"
>
<div className={appSkeletonTopBar}>
<div className={appSkeletonSitePicker} />
</div>
<div className={appSkeletonContent}>
<div className={appSkeletonContentBlock} />
</div>
</div>
);

/** Inline error message. Pad/position via `className` (e.g. `px-6 py-4`). */
export const ErrorState = ({
message,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
import { useRef } from "react";

import { PortalContainerContext } from "@hashintel/ds-components";
import { css } from "@hashintel/ds-helpers/css";

import { getLayoutWithSidebar } from "../../../shared/layout";
import { HEADER_HEIGHT } from "../../../shared/layout/layout-with-header/page-header";
import { useActiveWorkspace } from "../../shared/workspace-context";
import { SupplyChainDataShell } from "../supply-chain-data-shell";
import { LoadingState } from "./load-state";
import { SupplyChainAppSkeleton } from "./load-state";

import type { ReactElement, ReactNode } from "react";

const emptyState = css({
h: "full",
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "fg.subtle",
textStyle: "sm",
});

/**
* Layout shared by every `/supply-chain/*` page.
*
Expand All @@ -46,7 +36,7 @@ const SupplyChainShell = ({ children }: { children: ReactNode }) => {
}}
>
{activeWorkspaceWebId === undefined ? (
<LoadingState className={emptyState} message="Loading workspace..." />
<SupplyChainAppSkeleton />
) : (
<SupplyChainDataShell
key={activeWorkspaceWebId}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useRouter } from "next/router";
import { useEffect } from "react";

import { LoadingState, ErrorState } from "../../../../../shared/load-state";
import {
ErrorState,
SupplyChainAppSkeleton,
} from "../../../../../shared/load-state";
import { useRegistry } from "../../../../../shared/registry-context";
import { getSupplyChainLayout } from "../../../../../shared/supply-chain-layout";
import {
Expand Down Expand Up @@ -55,7 +58,7 @@ const OpportunityPage: NextPageWithLayout = () => {
}, [opportunityType, productId, siteId, stepId]);

if (!router.isReady) {
return <LoadingState message="Loading opportunity brief..." />;
return <SupplyChainAppSkeleton />;
}

if (!siteId || !productId || !stepId) {
Expand Down
Loading
Loading