Rename portal and trust frontends
Update visitor-facing apps to Compliance Portal types, hooks, and resolvers so they match the backend GraphQL rename. Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
@@ -25,14 +25,14 @@ import { graphql, useFragment } from "react-relay";
|
||||
import { InlineErrorCard } from "#/components/errors/InlineErrorCard";
|
||||
import { HomeSection } from "#/components/HomeSection/HomeSection";
|
||||
|
||||
import type { ComplianceFrameworksSection_trustCenter$key } from "./__generated__/ComplianceFrameworksSection_trustCenter.graphql";
|
||||
import type { ComplianceFrameworksSection_compliancePortal$key } from "./__generated__/ComplianceFrameworksSection_compliancePortal.graphql";
|
||||
import { ComplianceFrameworkListItem } from "./ComplianceFrameworkListItem";
|
||||
|
||||
// @throwOnFieldError makes a field error in this fragment throw at the read
|
||||
// below, where the section's ErrorBoundary contains it. See
|
||||
// contrib/claude/error-handling.md.
|
||||
const complianceFrameworksSectionFragment = graphql`
|
||||
fragment ComplianceFrameworksSection_trustCenter on TrustCenter @throwOnFieldError {
|
||||
fragment ComplianceFrameworksSection_compliancePortal on CompliancePortal @throwOnFieldError {
|
||||
complianceFrameworks(first: 8) {
|
||||
edges {
|
||||
node {
|
||||
@@ -45,13 +45,13 @@ const complianceFrameworksSectionFragment = graphql`
|
||||
`;
|
||||
|
||||
interface ComplianceFrameworksSectionProps {
|
||||
trustCenterKey: ComplianceFrameworksSection_trustCenter$key;
|
||||
compliancePortalKey: ComplianceFrameworksSection_compliancePortal$key;
|
||||
}
|
||||
|
||||
// "Compliance" section: the grid of certification frameworks the trust center
|
||||
// "Compliance" section: the grid of certification frameworks the compliance portal
|
||||
// covers. Wraps its data-reading content in a boundary so a load failure
|
||||
// degrades to an inline error instead of taking down the page.
|
||||
export function ComplianceFrameworksSection({ trustCenterKey }: ComplianceFrameworksSectionProps) {
|
||||
export function ComplianceFrameworksSection({ compliancePortalKey }: ComplianceFrameworksSectionProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@@ -64,14 +64,14 @@ export function ComplianceFrameworksSection({ trustCenterKey }: ComplianceFramew
|
||||
</HomeSection>
|
||||
)}
|
||||
>
|
||||
<ComplianceFrameworksSectionContent trustCenterKey={trustCenterKey} />
|
||||
<ComplianceFrameworksSectionContent compliancePortalKey={compliancePortalKey} />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
function ComplianceFrameworksSectionContent({ trustCenterKey }: ComplianceFrameworksSectionProps) {
|
||||
function ComplianceFrameworksSectionContent({ compliancePortalKey }: ComplianceFrameworksSectionProps) {
|
||||
const { t } = useTranslation();
|
||||
const data = useFragment(complianceFrameworksSectionFragment, trustCenterKey);
|
||||
const data = useFragment(complianceFrameworksSectionFragment, compliancePortalKey);
|
||||
const frameworks = data.complianceFrameworks.edges.map(edge => edge.node);
|
||||
|
||||
if (frameworks.length === 0) {
|
||||
|
||||
@@ -24,29 +24,29 @@ import { graphql, useFragment } from "react-relay";
|
||||
|
||||
import { externalHref, hostnameOf } from "#/lib/url/hostname";
|
||||
|
||||
import type { TrustCenterContactInfo_trustCenter$key } from "./__generated__/TrustCenterContactInfo_trustCenter.graphql";
|
||||
import type { CompliancePortalContactInfo_compliancePortal$key } from "./__generated__/CompliancePortalContactInfo_compliancePortal.graphql";
|
||||
import { organizationContactInfo } from "./variants";
|
||||
|
||||
const trustCenterContactInfoFragment = graphql`
|
||||
fragment TrustCenterContactInfo_trustCenter on TrustCenter {
|
||||
const compliancePortalContactInfoFragment = graphql`
|
||||
fragment CompliancePortalContactInfo_compliancePortal on CompliancePortal {
|
||||
websiteUrl
|
||||
email
|
||||
headquarterAddress
|
||||
}
|
||||
`;
|
||||
|
||||
interface TrustCenterContactInfoProps {
|
||||
trustCenterKey: TrustCenterContactInfo_trustCenter$key;
|
||||
interface CompliancePortalContactInfoProps {
|
||||
compliancePortalKey: CompliancePortalContactInfo_compliancePortal$key;
|
||||
}
|
||||
|
||||
// Trust center contact details (website, email, HQ) rendered as an icon + label
|
||||
// row. Owns its fragment so it can be reused wherever the trust center is in scope.
|
||||
export function TrustCenterContactInfo({ trustCenterKey }: TrustCenterContactInfoProps) {
|
||||
const trustCenter = useFragment(trustCenterContactInfoFragment, trustCenterKey);
|
||||
// Compliance portal contact details (website, email, HQ) rendered as an icon +
|
||||
// label row. Owns its fragment so it can be reused wherever the portal is in scope.
|
||||
export function CompliancePortalContactInfo({ compliancePortalKey }: CompliancePortalContactInfoProps) {
|
||||
const compliancePortal = useFragment(compliancePortalContactInfoFragment, compliancePortalKey);
|
||||
|
||||
const hasWebsite = trustCenter.websiteUrl != null && trustCenter.websiteUrl !== "";
|
||||
const hasEmail = trustCenter.email != null && trustCenter.email !== "";
|
||||
const hasAddress = trustCenter.headquarterAddress != null && trustCenter.headquarterAddress !== "";
|
||||
const hasWebsite = compliancePortal.websiteUrl != null && compliancePortal.websiteUrl !== "";
|
||||
const hasEmail = compliancePortal.email != null && compliancePortal.email !== "";
|
||||
const hasAddress = compliancePortal.headquarterAddress != null && compliancePortal.headquarterAddress !== "";
|
||||
|
||||
// Nothing to show — render no row (and therefore no divider) at all.
|
||||
if (!hasWebsite && !hasEmail && !hasAddress) {
|
||||
@@ -60,21 +60,21 @@ export function TrustCenterContactInfo({ trustCenterKey }: TrustCenterContactInf
|
||||
{hasWebsite && (
|
||||
<a
|
||||
className={link()}
|
||||
href={externalHref(trustCenter.websiteUrl)}
|
||||
href={externalHref(compliancePortal.websiteUrl)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<GlobeSimpleIcon />
|
||||
<Text size={2} color="neutral">
|
||||
{hostnameOf(trustCenter.websiteUrl)}
|
||||
{hostnameOf(compliancePortal.websiteUrl)}
|
||||
</Text>
|
||||
</a>
|
||||
)}
|
||||
{hasEmail && (
|
||||
<a className={link()} href={`mailto:${trustCenter.email}`}>
|
||||
<a className={link()} href={`mailto:${compliancePortal.email}`}>
|
||||
<EnvelopeIcon />
|
||||
<Text size={2} color="neutral">
|
||||
{trustCenter.email}
|
||||
{compliancePortal.email}
|
||||
</Text>
|
||||
</a>
|
||||
)}
|
||||
@@ -82,7 +82,7 @@ export function TrustCenterContactInfo({ trustCenterKey }: TrustCenterContactInf
|
||||
<div className={item()}>
|
||||
<MapPinSimpleIcon />
|
||||
<Text size={2} color="neutral">
|
||||
{trustCenter.headquarterAddress}
|
||||
{compliancePortal.headquarterAddress}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
@@ -38,7 +38,7 @@ export interface PageHeaderProps {
|
||||
flushBottomSpace?: boolean;
|
||||
}
|
||||
|
||||
// Page header for the Trust Center nav pages: a size-7 title in the shared white
|
||||
// Page header for the Compliance Portal nav pages: a size-7 title in the shared white
|
||||
// band, with an optional count, inline actions, and a toolbar slot below.
|
||||
export function PageHeader({ title, count, actions, children, flushBottomSpace }: PageHeaderProps) {
|
||||
const { content, titleRow, count: countSlot } = pageHeader();
|
||||
|
||||
@@ -28,12 +28,12 @@ import { HomeSection } from "#/components/HomeSection/HomeSection";
|
||||
import { MailingListUpdateListItem } from "#/components/MailingListUpdateListItem/MailingListUpdateListItem";
|
||||
import { dotPatternStyle } from "#/components/MediaTile/variants";
|
||||
|
||||
import type { RecentUpdatesSection_trustCenter$key } from "./__generated__/RecentUpdatesSection_trustCenter.graphql";
|
||||
import type { RecentUpdatesSection_compliancePortal$key } from "./__generated__/RecentUpdatesSection_compliancePortal.graphql";
|
||||
|
||||
// @throwOnFieldError surfaces a field error at the read below so the section
|
||||
// ErrorBoundary contains it. See contrib/claude/error-handling.md.
|
||||
const recentUpdatesSectionFragment = graphql`
|
||||
fragment RecentUpdatesSection_trustCenter on TrustCenter @throwOnFieldError {
|
||||
fragment RecentUpdatesSection_compliancePortal on CompliancePortal @throwOnFieldError {
|
||||
updates(first: 5) {
|
||||
edges {
|
||||
node {
|
||||
@@ -46,12 +46,12 @@ const recentUpdatesSectionFragment = graphql`
|
||||
`;
|
||||
|
||||
interface RecentUpdatesSectionProps {
|
||||
trustCenterKey: RecentUpdatesSection_trustCenter$key;
|
||||
compliancePortalKey: RecentUpdatesSection_compliancePortal$key;
|
||||
}
|
||||
|
||||
// "Recent updates" section: the latest mailing-list updates as a list, with a
|
||||
// link to the full updates page. A load failure degrades to an inline error.
|
||||
export function RecentUpdatesSection({ trustCenterKey }: RecentUpdatesSectionProps) {
|
||||
export function RecentUpdatesSection({ compliancePortalKey }: RecentUpdatesSectionProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@@ -64,14 +64,14 @@ export function RecentUpdatesSection({ trustCenterKey }: RecentUpdatesSectionPro
|
||||
</HomeSection>
|
||||
)}
|
||||
>
|
||||
<RecentUpdatesSectionContent trustCenterKey={trustCenterKey} />
|
||||
<RecentUpdatesSectionContent compliancePortalKey={compliancePortalKey} />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
function RecentUpdatesSectionContent({ trustCenterKey }: RecentUpdatesSectionProps) {
|
||||
function RecentUpdatesSectionContent({ compliancePortalKey }: RecentUpdatesSectionProps) {
|
||||
const { t } = useTranslation();
|
||||
const data = useFragment(recentUpdatesSectionFragment, trustCenterKey);
|
||||
const data = useFragment(recentUpdatesSectionFragment, compliancePortalKey);
|
||||
const updates = data.updates.edges.map(edge => edge.node);
|
||||
|
||||
if (updates.length === 0) {
|
||||
|
||||
@@ -23,7 +23,7 @@ import { graphql, useFragment } from "react-relay";
|
||||
|
||||
import { InlineErrorCard } from "#/components/errors/InlineErrorCard";
|
||||
|
||||
import type { SecurityCommitmentsSection_trustCenter$key } from "./__generated__/SecurityCommitmentsSection_trustCenter.graphql";
|
||||
import type { SecurityCommitmentsSection_compliancePortal$key } from "./__generated__/SecurityCommitmentsSection_compliancePortal.graphql";
|
||||
import { SecurityCommitmentGroupListItem } from "./SecurityCommitmentGroupListItem";
|
||||
import { securityCommitments } from "./variants";
|
||||
|
||||
@@ -31,7 +31,7 @@ import { securityCommitments } from "./variants";
|
||||
// below, where the section's ErrorBoundary contains it. See
|
||||
// contrib/claude/error-handling.md.
|
||||
const securityCommitmentsSectionFragment = graphql`
|
||||
fragment SecurityCommitmentsSection_trustCenter on TrustCenter @throwOnFieldError {
|
||||
fragment SecurityCommitmentsSection_compliancePortal on CompliancePortal @throwOnFieldError {
|
||||
commitmentGroups(first: 100) {
|
||||
edges {
|
||||
node {
|
||||
@@ -53,13 +53,13 @@ const securityCommitmentsSectionFragment = graphql`
|
||||
`;
|
||||
|
||||
interface SecurityCommitmentsSectionProps {
|
||||
trustCenterKey: SecurityCommitmentsSection_trustCenter$key;
|
||||
compliancePortalKey: SecurityCommitmentsSection_compliancePortal$key;
|
||||
}
|
||||
|
||||
// "Security Commitments" section: stacked groups, each a header above a grid of
|
||||
// commitment cards. Wraps its data-reading content in a boundary so a load
|
||||
// failure degrades to an inline error instead of taking down the page.
|
||||
export function SecurityCommitmentsSection({ trustCenterKey }: SecurityCommitmentsSectionProps) {
|
||||
export function SecurityCommitmentsSection({ compliancePortalKey }: SecurityCommitmentsSectionProps) {
|
||||
return (
|
||||
<ErrorBoundary
|
||||
fallback={(
|
||||
@@ -68,13 +68,13 @@ export function SecurityCommitmentsSection({ trustCenterKey }: SecurityCommitmen
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<SecurityCommitmentsSectionContent trustCenterKey={trustCenterKey} />
|
||||
<SecurityCommitmentsSectionContent compliancePortalKey={compliancePortalKey} />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
function SecurityCommitmentsSectionContent({ trustCenterKey }: SecurityCommitmentsSectionProps) {
|
||||
const data = useFragment(securityCommitmentsSectionFragment, trustCenterKey);
|
||||
function SecurityCommitmentsSectionContent({ compliancePortalKey }: SecurityCommitmentsSectionProps) {
|
||||
const data = useFragment(securityCommitmentsSectionFragment, compliancePortalKey);
|
||||
const slots = securityCommitments();
|
||||
|
||||
// Groups with no cards render nothing, so filter them out here to keep the
|
||||
|
||||
@@ -41,7 +41,7 @@ const topBarFragment = graphql`
|
||||
...TopBarUserMenu_identity
|
||||
...TopBarMobileNav_identity
|
||||
}
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
currentCompliancePortal @required(action: THROW) {
|
||||
themedLogoUrl
|
||||
title
|
||||
}
|
||||
@@ -62,9 +62,9 @@ export function TopBar({ queryKey }: TopBarProps) {
|
||||
const location = useLocation();
|
||||
const { pathname } = location;
|
||||
|
||||
const { currentTrustCenter } = data;
|
||||
const title = currentTrustCenter.title;
|
||||
const logoUrl = currentTrustCenter.themedLogoUrl ?? undefined;
|
||||
const { currentCompliancePortal } = data;
|
||||
const title = currentCompliancePortal.title;
|
||||
const logoUrl = currentCompliancePortal.themedLogoUrl ?? undefined;
|
||||
|
||||
const slots = topBar();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
import { tv } from "tailwind-variants/lite";
|
||||
|
||||
// Trust Center top navigation bar. Slots are shared by the live TopBar and its
|
||||
// Compliance Portal top navigation bar. Slots are shared by the live TopBar and its
|
||||
// skeleton so the loading placeholder is structurally identical. Desktop-first:
|
||||
// unprefixed classes are the desktop layout; max-md: collapses into the burger.
|
||||
export const topBar = tv({
|
||||
|
||||
@@ -24,10 +24,10 @@ import { graphql, useFragment } from "react-relay";
|
||||
import { MediaTile } from "#/components/MediaTile/MediaTile";
|
||||
import { externalHref } from "#/lib/url/hostname";
|
||||
|
||||
import type { TrustCenterReferenceListItem_reference$key } from "./__generated__/TrustCenterReferenceListItem_reference.graphql";
|
||||
import type { CompliancePortalReferenceListItem_reference$key } from "./__generated__/CompliancePortalReferenceListItem_reference.graphql";
|
||||
|
||||
const trustCenterReferenceListItemFragment = graphql`
|
||||
fragment TrustCenterReferenceListItem_reference on TrustCenterReference @throwOnFieldError {
|
||||
const compliancePortalReferenceListItemFragment = graphql`
|
||||
fragment CompliancePortalReferenceListItem_reference on CompliancePortalReference @throwOnFieldError {
|
||||
name
|
||||
websiteUrl
|
||||
logo {
|
||||
@@ -36,13 +36,13 @@ const trustCenterReferenceListItemFragment = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
interface TrustCenterReferenceListItemProps {
|
||||
referenceKey: TrustCenterReferenceListItem_reference$key;
|
||||
interface CompliancePortalReferenceListItemProps {
|
||||
referenceKey: CompliancePortalReferenceListItem_reference$key;
|
||||
}
|
||||
|
||||
// A single "Trusted by" logo tile, linking to the reference's website.
|
||||
export function TrustCenterReferenceListItem({ referenceKey }: TrustCenterReferenceListItemProps) {
|
||||
const reference = useFragment(trustCenterReferenceListItemFragment, referenceKey);
|
||||
export function CompliancePortalReferenceListItem({ referenceKey }: CompliancePortalReferenceListItemProps) {
|
||||
const reference = useFragment(compliancePortalReferenceListItemFragment, referenceKey);
|
||||
|
||||
return (
|
||||
<a
|
||||
@@ -25,18 +25,18 @@ import { graphql, useFragment } from "react-relay";
|
||||
import { InlineErrorCard } from "#/components/errors/InlineErrorCard";
|
||||
import { HomeSection } from "#/components/HomeSection/HomeSection";
|
||||
|
||||
import type { TrustedBySection_trustCenter$key } from "./__generated__/TrustedBySection_trustCenter.graphql";
|
||||
import { TrustCenterReferenceListItem } from "./TrustCenterReferenceListItem";
|
||||
import type { TrustedBySection_compliancePortal$key } from "./__generated__/TrustedBySection_compliancePortal.graphql";
|
||||
import { CompliancePortalReferenceListItem } from "./CompliancePortalReferenceListItem";
|
||||
|
||||
// @throwOnFieldError surfaces a field error at the read below so the section
|
||||
// ErrorBoundary contains it. See contrib/claude/error-handling.md.
|
||||
const trustedBySectionFragment = graphql`
|
||||
fragment TrustedBySection_trustCenter on TrustCenter @throwOnFieldError {
|
||||
fragment TrustedBySection_compliancePortal on CompliancePortal @throwOnFieldError {
|
||||
references(first: 12) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...TrustCenterReferenceListItem_reference
|
||||
...CompliancePortalReferenceListItem_reference
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,12 +44,12 @@ const trustedBySectionFragment = graphql`
|
||||
`;
|
||||
|
||||
interface TrustedBySectionProps {
|
||||
trustCenterKey: TrustedBySection_trustCenter$key;
|
||||
compliancePortalKey: TrustedBySection_compliancePortal$key;
|
||||
}
|
||||
|
||||
// "Trusted by" section: a grid of customer / reference logos. A load failure
|
||||
// degrades to an inline error instead of taking down the page.
|
||||
export function TrustedBySection({ trustCenterKey }: TrustedBySectionProps) {
|
||||
export function TrustedBySection({ compliancePortalKey }: TrustedBySectionProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@@ -62,14 +62,14 @@ export function TrustedBySection({ trustCenterKey }: TrustedBySectionProps) {
|
||||
</HomeSection>
|
||||
)}
|
||||
>
|
||||
<TrustedBySectionContent trustCenterKey={trustCenterKey} />
|
||||
<TrustedBySectionContent compliancePortalKey={compliancePortalKey} />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
function TrustedBySectionContent({ trustCenterKey }: TrustedBySectionProps) {
|
||||
function TrustedBySectionContent({ compliancePortalKey }: TrustedBySectionProps) {
|
||||
const { t } = useTranslation();
|
||||
const data = useFragment(trustedBySectionFragment, trustCenterKey);
|
||||
const data = useFragment(trustedBySectionFragment, compliancePortalKey);
|
||||
const references = data.references.edges.map(edge => edge.node);
|
||||
|
||||
if (references.length === 0) {
|
||||
@@ -80,7 +80,7 @@ function TrustedBySectionContent({ trustCenterKey }: TrustedBySectionProps) {
|
||||
<HomeSection title={t("home.sections.trustedBy")}>
|
||||
<div className="grid grid-cols-6 gap-4 max-lg:grid-cols-3 max-sm:grid-cols-2">
|
||||
{references.map(reference => (
|
||||
<TrustCenterReferenceListItem key={reference.id} referenceKey={reference} />
|
||||
<CompliancePortalReferenceListItem key={reference.id} referenceKey={reference} />
|
||||
))}
|
||||
</div>
|
||||
</HomeSection>
|
||||
|
||||
@@ -44,7 +44,7 @@ import type { useResumeAccessRequestMutation } from "./__generated__/useResumeAc
|
||||
const requestAllAccessesMutation = graphql`
|
||||
mutation useResumeAccessRequestMutation {
|
||||
requestAllAccesses {
|
||||
trustCenterAccess {
|
||||
compliancePortalAccess {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -83,8 +83,8 @@ const requestReportMutation = graphql`
|
||||
`;
|
||||
|
||||
const requestFileMutation = graphql`
|
||||
mutation useResumeAccessRequest_fileMutation($input: RequestTrustCenterFileAccessInput!) {
|
||||
requestTrustCenterFileAccess(input: $input) {
|
||||
mutation useResumeAccessRequest_fileMutation($input: RequestCompliancePortalFileAccessInput!) {
|
||||
requestCompliancePortalFileAccess(input: $input) {
|
||||
file {
|
||||
id
|
||||
access {
|
||||
@@ -194,7 +194,7 @@ export function useResumeAccessRequest(isAuthenticated: boolean) {
|
||||
const continueUrl = buildRequestAccessContinueUrl(REQUEST_FILE_PARAM, fileId);
|
||||
clear(REQUEST_FILE_PARAM);
|
||||
void requestFileAccess({
|
||||
variables: { input: { trustCenterFileId: fileId } },
|
||||
variables: { input: { compliancePortalFileId: fileId } },
|
||||
...makeHandlers(continueUrl),
|
||||
}).catch(() => {});
|
||||
return;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
import { graphql } from "react-relay";
|
||||
import { type LiveState, readFragment } from "relay-runtime";
|
||||
|
||||
import type { TrustCenterLogoResolverFragment$key } from "./__generated__/TrustCenterLogoResolverFragment.graphql";
|
||||
import type { CompliancePortalLogoResolverFragment$key } from "./__generated__/CompliancePortalLogoResolverFragment.graphql";
|
||||
|
||||
function prefersDark(): boolean {
|
||||
return typeof window !== "undefined"
|
||||
@@ -30,21 +30,21 @@ function prefersDark(): boolean {
|
||||
}
|
||||
|
||||
/**
|
||||
* @relayField TrustCenter.themedLogoUrl: String
|
||||
* @rootFragment TrustCenterLogoResolverFragment
|
||||
* @relayField CompliancePortal.themedLogoUrl: String
|
||||
* @rootFragment CompliancePortalLogoResolverFragment
|
||||
* @live
|
||||
*
|
||||
* Resolves the trust center logo download URL for the current system color
|
||||
* Resolves the compliance portal logo download URL for the current system color
|
||||
* scheme: the dark logo (falling back to the light one) when the OS prefers
|
||||
* dark, otherwise the light logo. Lives in the graph so consumers select a
|
||||
* single field instead of threading `useSystemTheme` through URL selection.
|
||||
*/
|
||||
export function themedLogoUrl(
|
||||
key: TrustCenterLogoResolverFragment$key,
|
||||
key: CompliancePortalLogoResolverFragment$key,
|
||||
): LiveState<string | null> {
|
||||
const data = readFragment(
|
||||
graphql`
|
||||
fragment TrustCenterLogoResolverFragment on TrustCenter {
|
||||
fragment CompliancePortalLogoResolverFragment on CompliancePortal {
|
||||
logo {
|
||||
downloadUrl
|
||||
}
|
||||
@@ -24,7 +24,7 @@ import { graphql, usePreloadedQuery } from "react-relay";
|
||||
|
||||
import { ComplianceFrameworksSection } from "#/components/ComplianceFrameworks/ComplianceFrameworksSection";
|
||||
import { Hero } from "#/components/Hero/Hero";
|
||||
import { TrustCenterContactInfo } from "#/components/Hero/TrustCenterContactInfo";
|
||||
import { CompliancePortalContactInfo } from "#/components/Hero/CompliancePortalContactInfo";
|
||||
import { RecentUpdatesSection } from "#/components/RecentUpdates/RecentUpdatesSection";
|
||||
import { SecurityCommitmentsSection } from "#/components/SecurityCommitments/SecurityCommitmentsSection";
|
||||
import { TrustedBySection } from "#/components/TrustedBy/TrustedBySection";
|
||||
@@ -33,13 +33,13 @@ import type { HomePageQuery } from "./__generated__/HomePageQuery.graphql";
|
||||
|
||||
export const homePageQuery = graphql`
|
||||
query HomePageQuery @throwOnFieldError {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
currentCompliancePortal @required(action: THROW) {
|
||||
title
|
||||
...TrustCenterContactInfo_trustCenter
|
||||
...ComplianceFrameworksSection_trustCenter
|
||||
...SecurityCommitmentsSection_trustCenter
|
||||
...TrustedBySection_trustCenter
|
||||
...RecentUpdatesSection_trustCenter
|
||||
...CompliancePortalContactInfo_compliancePortal
|
||||
...ComplianceFrameworksSection_compliancePortal
|
||||
...SecurityCommitmentsSection_compliancePortal
|
||||
...TrustedBySection_compliancePortal
|
||||
...RecentUpdatesSection_compliancePortal
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -51,8 +51,8 @@ interface HomePageProps {
|
||||
export function HomePage({ queryRef }: HomePageProps) {
|
||||
const { t } = useTranslation();
|
||||
const data = usePreloadedQuery<HomePageQuery>(homePageQuery, queryRef);
|
||||
const { currentTrustCenter } = data;
|
||||
const { title } = currentTrustCenter;
|
||||
const { currentCompliancePortal } = data;
|
||||
const { title } = currentCompliancePortal;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -60,14 +60,14 @@ export function HomePage({ queryRef }: HomePageProps) {
|
||||
title={t("home.heroTitle", { name: title })}
|
||||
description={t("home.heroDescription")}
|
||||
>
|
||||
<TrustCenterContactInfo trustCenterKey={currentTrustCenter} />
|
||||
<CompliancePortalContactInfo compliancePortalKey={currentCompliancePortal} />
|
||||
</Hero>
|
||||
<div className="flex w-full flex-col items-center px-8 max-md:px-4">
|
||||
<div className="flex w-full max-w-5xl flex-col">
|
||||
<ComplianceFrameworksSection trustCenterKey={currentTrustCenter} />
|
||||
<SecurityCommitmentsSection trustCenterKey={currentTrustCenter} />
|
||||
<TrustedBySection trustCenterKey={currentTrustCenter} />
|
||||
<RecentUpdatesSection trustCenterKey={currentTrustCenter} />
|
||||
<ComplianceFrameworksSection compliancePortalKey={currentCompliancePortal} />
|
||||
<SecurityCommitmentsSection compliancePortalKey={currentCompliancePortal} />
|
||||
<TrustedBySection compliancePortalKey={currentCompliancePortal} />
|
||||
<RecentUpdatesSection compliancePortalKey={currentCompliancePortal} />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -37,7 +37,7 @@ export const documentViewerPageQuery = graphql`
|
||||
title
|
||||
isUserAuthorized
|
||||
}
|
||||
... on TrustCenterFile {
|
||||
... on CompliancePortalFile {
|
||||
id
|
||||
name
|
||||
isUserAuthorized
|
||||
@@ -66,8 +66,8 @@ function resolveNode(node: DocumentViewerPageQuery["response"]["aliasedNode"]):
|
||||
switch (node.__typename) {
|
||||
case "Document":
|
||||
return { kind: "Document", id: node.id, title: node.title, isAuthorized: node.isUserAuthorized };
|
||||
case "TrustCenterFile":
|
||||
return { kind: "TrustCenterFile", id: node.id, title: node.name, isAuthorized: node.isUserAuthorized };
|
||||
case "CompliancePortalFile":
|
||||
return { kind: "CompliancePortalFile", id: node.id, title: node.name, isAuthorized: node.isUserAuthorized };
|
||||
case "AuditReport":
|
||||
return { kind: "AuditReport", id: node.id, title: node.fileName, isAuthorized: node.isUserAuthorized };
|
||||
default:
|
||||
|
||||
@@ -35,13 +35,13 @@ import { DocumentListItem } from "./_components/DocumentListItem";
|
||||
import { DocumentSection } from "./_components/DocumentSection";
|
||||
import { DocumentsEmpty } from "./_components/DocumentsEmpty";
|
||||
import { DocumentsToolbar } from "./_components/DocumentsToolbar";
|
||||
import { TrustCenterFileListItem } from "./_components/TrustCenterFileListItem";
|
||||
import { CompliancePortalFileListItem } from "./_components/CompliancePortalFileListItem";
|
||||
import { toQueryVariables } from "./_lib/toQueryVariables";
|
||||
import { useDocumentTab } from "./_lib/useDocumentTab";
|
||||
import { documentsLayout } from "./variants";
|
||||
|
||||
export const documentsPageQuery = graphql`
|
||||
query DocumentsPageQuery($visibility: TrustCenterVisibility) {
|
||||
query DocumentsPageQuery($visibility: CompliancePortalVisibility) {
|
||||
...DocumentsPage_query @arguments(visibility: $visibility)
|
||||
}
|
||||
`;
|
||||
@@ -49,8 +49,8 @@ export const documentsPageQuery = graphql`
|
||||
const documentsPageFragment = graphql`
|
||||
fragment DocumentsPage_query on Query
|
||||
@refetchable(queryName: "DocumentsPageRefetchQuery")
|
||||
@argumentDefinitions(visibility: { type: "TrustCenterVisibility" }) {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
@argumentDefinitions(visibility: { type: "CompliancePortalVisibility" }) {
|
||||
currentCompliancePortal @required(action: THROW) {
|
||||
documents(first: 250, filter: { visibility: $visibility }) {
|
||||
edges {
|
||||
node {
|
||||
@@ -71,12 +71,12 @@ const documentsPageFragment = graphql`
|
||||
}
|
||||
}
|
||||
}
|
||||
trustCenterFiles(first: 250, filter: { visibility: $visibility }) {
|
||||
compliancePortalFiles(first: 250, filter: { visibility: $visibility }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
category
|
||||
...TrustCenterFileListItem_file
|
||||
...CompliancePortalFileListItem_file
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ interface DocumentsPageProps {
|
||||
queryRef: PreloadedQuery<DocumentsPageQuery>;
|
||||
}
|
||||
|
||||
// Trust Center documents page: a unified list of published documents, uploaded
|
||||
// Compliance Portal documents page: a unified list of published documents, uploaded
|
||||
// files, and audit reports, grouped into category sections. The All/Public/
|
||||
// Private tabs are backed by a server-side visibility filter.
|
||||
export function DocumentsPage({ queryRef }: DocumentsPageProps) {
|
||||
@@ -140,10 +140,10 @@ export function DocumentsPage({ queryRef }: DocumentsPageProps) {
|
||||
});
|
||||
}, [refetch, tab]);
|
||||
|
||||
const { currentTrustCenter } = data;
|
||||
const documentNodes = currentTrustCenter.documents.edges.map(edge => edge.node);
|
||||
const fileNodes = currentTrustCenter.trustCenterFiles.edges.map(edge => edge.node);
|
||||
const auditNodes = currentTrustCenter.audits.edges
|
||||
const { currentCompliancePortal } = data;
|
||||
const documentNodes = currentCompliancePortal.documents.edges.map(edge => edge.node);
|
||||
const fileNodes = currentCompliancePortal.compliancePortalFiles.edges.map(edge => edge.node);
|
||||
const auditNodes = currentCompliancePortal.audits.edges
|
||||
.map(edge => edge.node)
|
||||
.filter(node => node.reportFile != null);
|
||||
|
||||
@@ -191,7 +191,7 @@ export function DocumentsPage({ queryRef }: DocumentsPageProps) {
|
||||
{fileGroups.map(group => (
|
||||
<DocumentSection key={`category:${group.key}`} title={group.key}>
|
||||
{group.nodes.map(node => (
|
||||
<TrustCenterFileListItem key={node.id} fileKey={node} />
|
||||
<CompliancePortalFileListItem key={node.id} fileKey={node} />
|
||||
))}
|
||||
</DocumentSection>
|
||||
))}
|
||||
|
||||
@@ -22,11 +22,11 @@ import { graphql, useFragment } from "react-relay";
|
||||
|
||||
import { useRequestFileAccess } from "../_lib/useAccessRequest";
|
||||
|
||||
import type { TrustCenterFileListItem_file$key } from "./__generated__/TrustCenterFileListItem_file.graphql";
|
||||
import type { CompliancePortalFileListItem_file$key } from "./__generated__/CompliancePortalFileListItem_file.graphql";
|
||||
import { DocumentEntry } from "./DocumentEntry";
|
||||
|
||||
const trustCenterFileListItemFragment = graphql`
|
||||
fragment TrustCenterFileListItem_file on TrustCenterFile @throwOnFieldError {
|
||||
const compliancePortalFileListItemFragment = graphql`
|
||||
fragment CompliancePortalFileListItem_file on CompliancePortalFile @throwOnFieldError {
|
||||
id
|
||||
alias
|
||||
name
|
||||
@@ -38,14 +38,14 @@ const trustCenterFileListItemFragment = graphql`
|
||||
}
|
||||
`;
|
||||
|
||||
interface TrustCenterFileListItemProps {
|
||||
fileKey: TrustCenterFileListItem_file$key;
|
||||
interface CompliancePortalFileListItemProps {
|
||||
fileKey: CompliancePortalFileListItem_file$key;
|
||||
}
|
||||
|
||||
// A single uploaded trust-center file entry: name, its category, and an access
|
||||
// action linking to the viewer when authorized.
|
||||
export function TrustCenterFileListItem({ fileKey }: TrustCenterFileListItemProps) {
|
||||
const file = useFragment(trustCenterFileListItemFragment, fileKey);
|
||||
export function CompliancePortalFileListItem({ fileKey }: CompliancePortalFileListItemProps) {
|
||||
const file = useFragment(compliancePortalFileListItemFragment, fileKey);
|
||||
const { requestAccess, isRequesting } = useRequestFileAccess(file.id);
|
||||
|
||||
return (
|
||||
@@ -26,7 +26,7 @@ import { EmptyState } from "#/components/EmptyState/EmptyState";
|
||||
import { useDocumentTab } from "../_lib/useDocumentTab";
|
||||
|
||||
// Empty state for the documents list. When a Public/Private tab is active it
|
||||
// notes the filter; otherwise it states the trust center publishes no documents.
|
||||
// notes the filter; otherwise it states the compliance portal publishes no documents.
|
||||
export function DocumentsEmpty() {
|
||||
const { t } = useTranslation("documents");
|
||||
const { tab } = useDocumentTab();
|
||||
|
||||
@@ -80,8 +80,8 @@ const reportMutation = graphql`
|
||||
`;
|
||||
|
||||
const fileMutation = graphql`
|
||||
mutation useAccessRequestFileMutation($input: RequestTrustCenterFileAccessInput!) {
|
||||
requestTrustCenterFileAccess(input: $input) {
|
||||
mutation useAccessRequestFileMutation($input: RequestCompliancePortalFileAccessInput!) {
|
||||
requestCompliancePortalFileAccess(input: $input) {
|
||||
file {
|
||||
id
|
||||
access {
|
||||
@@ -171,7 +171,7 @@ export function useRequestFileAccess(id: string): AccessRequest {
|
||||
);
|
||||
|
||||
const requestAccess = useCallback(() => {
|
||||
void mutate({ variables: { input: { trustCenterFileId: id } }, ...handlers }).catch(() => {});
|
||||
void mutate({ variables: { input: { compliancePortalFileId: id } }, ...handlers }).catch(() => {});
|
||||
}, [mutate, id, handlers]);
|
||||
|
||||
return { requestAccess, isRequesting };
|
||||
@@ -189,7 +189,7 @@ export function useAccessRequest(kind: DocumentKind, id: string): AccessRequest
|
||||
return document;
|
||||
case "AuditReport":
|
||||
return report;
|
||||
case "TrustCenterFile":
|
||||
case "CompliancePortalFile":
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import type { useDocumentExportDocumentMutation } from "./__generated__/useDocum
|
||||
import type { useDocumentExportFileMutation } from "./__generated__/useDocumentExportFileMutation.graphql";
|
||||
import type { useDocumentExportReportMutation } from "./__generated__/useDocumentExportReportMutation.graphql";
|
||||
|
||||
export type DocumentKind = "Document" | "TrustCenterFile" | "AuditReport";
|
||||
export type DocumentKind = "Document" | "CompliancePortalFile" | "AuditReport";
|
||||
|
||||
const exportDocumentMutation = graphql`
|
||||
mutation useDocumentExportDocumentMutation($input: ExportDocumentPDFInput!) {
|
||||
@@ -38,8 +38,8 @@ const exportDocumentMutation = graphql`
|
||||
`;
|
||||
|
||||
const exportFileMutation = graphql`
|
||||
mutation useDocumentExportFileMutation($input: ExportTrustCenterFileInput!) {
|
||||
exportTrustCenterFile(input: $input) {
|
||||
mutation useDocumentExportFileMutation($input: ExportCompliancePortalFileInput!) {
|
||||
exportCompliancePortalFile(input: $input) {
|
||||
data
|
||||
}
|
||||
}
|
||||
@@ -102,10 +102,10 @@ export function useDocumentExport(kind: DocumentKind, id: string, enabled: boole
|
||||
onCompleted: response => apply(id, response.exportDocumentPDF.data),
|
||||
}).catch(() => {});
|
||||
break;
|
||||
case "TrustCenterFile":
|
||||
case "CompliancePortalFile":
|
||||
exportFile({
|
||||
variables: { input: { trustCenterFileId: id } },
|
||||
onCompleted: response => apply(id, response.exportTrustCenterFile.data),
|
||||
variables: { input: { compliancePortalFileId: id } },
|
||||
onCompleted: response => apply(id, response.exportCompliancePortalFile.data),
|
||||
}).catch(() => {});
|
||||
break;
|
||||
case "AuditReport":
|
||||
|
||||
@@ -61,7 +61,7 @@ export const ndaPageQuery = graphql`
|
||||
viewer {
|
||||
id
|
||||
}
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
currentCompliancePortal @required(action: THROW) {
|
||||
title
|
||||
nonDisclosureAgreement {
|
||||
fileUrl
|
||||
@@ -72,7 +72,7 @@ export const ndaPageQuery = graphql`
|
||||
`;
|
||||
|
||||
const ndaPageFragment = graphql`
|
||||
fragment NDAPageFragment on TrustCenter
|
||||
fragment NDAPageFragment on CompliancePortal
|
||||
@refetchable(queryName: "NDAPageRefetchQuery") {
|
||||
nonDisclosureAgreement @required(action: THROW) {
|
||||
viewerSignature {
|
||||
@@ -122,13 +122,13 @@ export function NDAPage({ queryRef }: NDAPageProps) {
|
||||
const [scale, setScale] = useState(1);
|
||||
|
||||
const data = usePreloadedQuery<NDAPageQueryType>(ndaPageQuery, queryRef);
|
||||
const trustCenter = data.currentTrustCenter;
|
||||
const compliancePortal = data.currentCompliancePortal;
|
||||
const [fragment, refetch] = useRefetchableFragment<NDAPageRefetchQuery, NDAPageFragment$key>(
|
||||
ndaPageFragment,
|
||||
trustCenter,
|
||||
compliancePortal,
|
||||
);
|
||||
|
||||
const nda = trustCenter.nonDisclosureAgreement;
|
||||
const nda = compliancePortal.nonDisclosureAgreement;
|
||||
const signature = fragment.nonDisclosureAgreement.viewerSignature;
|
||||
|
||||
const safeContinueUrl = getSafeContinueUrl(searchParams.get("continue"));
|
||||
@@ -236,7 +236,7 @@ export function NDAPage({ queryRef }: NDAPageProps) {
|
||||
{t("title")}
|
||||
</Heading>
|
||||
<Text size={2} color="neutral">
|
||||
{t("subtitle", { name: trustCenter.title })}
|
||||
{t("subtitle", { name: compliancePortal.title })}
|
||||
</Text>
|
||||
{signature.consentText != null && (
|
||||
<Text size={1} color="faint" className={slots.consent()}>
|
||||
|
||||
@@ -52,7 +52,7 @@ const subprocessorsPageFragment = graphql`
|
||||
category: { type: "SubprocessorCategory" }
|
||||
country: { type: "CountryCode" }
|
||||
) {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
currentCompliancePortal @required(action: THROW) {
|
||||
subprocessors(first: 250, filter: { query: $query, category: $category, country: $country }) {
|
||||
totalCount
|
||||
edges {
|
||||
@@ -98,7 +98,7 @@ export function SubprocessorsPage({ queryRef }: SubprocessorsPageProps) {
|
||||
});
|
||||
}, [refetch, query, category, country]);
|
||||
|
||||
const { subprocessors } = data.currentTrustCenter;
|
||||
const { subprocessors } = data.currentCompliancePortal;
|
||||
const nodes: SubprocessorNode[] = subprocessors.edges.map(edge => edge.node);
|
||||
const groups = groupByCategory(nodes, value => t(`categories.${value}.label`));
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import { EmptyState } from "#/components/EmptyState/EmptyState";
|
||||
import { useSubprocessorFilters } from "../_lib/useSubprocessorFilters";
|
||||
|
||||
// Empty state for the subprocessor list. When filters are active it offers to
|
||||
// clear them; otherwise it states the trust center lists no subprocessors.
|
||||
// clear them; otherwise it states the compliance portal lists no subprocessors.
|
||||
export function SubprocessorsEmpty() {
|
||||
const { t } = useTranslation("subprocessors");
|
||||
const { hasActiveFilters, clear } = useSubprocessorFilters();
|
||||
|
||||
@@ -34,11 +34,11 @@ import { useSubprocessorSearch } from "../_lib/useSubprocessorSearch";
|
||||
import type { SubprocessorsToolbar_query$key } from "./__generated__/SubprocessorsToolbar_query.graphql";
|
||||
|
||||
// Facet data: the distinct categories and countries actually present across the
|
||||
// trust center's published subprocessors, used to populate the filter dropdowns
|
||||
// compliance portal's published subprocessors, used to populate the filter dropdowns
|
||||
// (server-computed so the options never dead-end on an empty result).
|
||||
const subprocessorsToolbarFragment = graphql`
|
||||
fragment SubprocessorsToolbar_query on Query {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
currentCompliancePortal @required(action: THROW) {
|
||||
subprocessorCategories
|
||||
subprocessorCountries
|
||||
}
|
||||
@@ -58,7 +58,7 @@ export function SubprocessorsToolbar({ queryKey }: SubprocessorsToolbarProps) {
|
||||
const { category, country, setCategory, setCountry } = useSubprocessorFilters();
|
||||
const [queryInput, setQueryInput] = useSubprocessorSearch();
|
||||
|
||||
const { subprocessorCategories, subprocessorCountries } = data.currentTrustCenter;
|
||||
const { subprocessorCategories, subprocessorCountries } = data.currentCompliancePortal;
|
||||
|
||||
const categoryOptions = useMemo(() => {
|
||||
return [...subprocessorCategories].sort((a, b) => t(`categories.${a}.label`).localeCompare(t(`categories.${b}.label`)));
|
||||
|
||||
@@ -53,7 +53,7 @@ const updatesPageFragment = graphql`
|
||||
last: { type: "Int" }
|
||||
before: { type: "CursorKey" }
|
||||
) {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
currentCompliancePortal @required(action: THROW) {
|
||||
updates(first: $first, after: $after, last: $last, before: $before) {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
@@ -96,7 +96,7 @@ export function UpdatesPage({ queryRef }: UpdatesPageProps) {
|
||||
});
|
||||
}, [refetch]);
|
||||
|
||||
const { updates } = data.currentTrustCenter;
|
||||
const { updates } = data.currentCompliancePortal;
|
||||
const { pageInfo } = updates;
|
||||
const { isPending, goPrevious, goNext } = useCursorPagination(refetchUpdates, pageInfo, UPDATES_PAGE_SIZE);
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import { EmptyState } from "#/components/EmptyState/EmptyState";
|
||||
|
||||
import { UpdatesSubscribeButton } from "./UpdatesSubscribeButton";
|
||||
|
||||
// Empty state for the updates list: shown when the trust center has published no
|
||||
// Empty state for the updates list: shown when the compliance portal has published no
|
||||
// updates yet, inviting the visitor to subscribe.
|
||||
export function UpdatesEmpty() {
|
||||
const { t } = useTranslation("updates");
|
||||
|
||||
Reference in New Issue
Block a user