Move trust center profile onto the page
Store website, email, and headquarters on the trust center so public and admin surfaces read branding from one place. Drop the trust API organization type and wire console, MCP, CLI, and apps through the updated schema. Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
@@ -44,9 +44,7 @@ const topBarFragment = graphql`
|
||||
}
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
themedLogoUrl
|
||||
organization {
|
||||
name
|
||||
}
|
||||
title
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -66,7 +64,7 @@ export function TopBar({ queryKey }: TopBarProps) {
|
||||
const { openSignIn } = useSignInDialog();
|
||||
|
||||
const { currentTrustCenter } = data;
|
||||
const organizationName = currentTrustCenter.organization.name;
|
||||
const title = currentTrustCenter.title;
|
||||
const logoUrl = currentTrustCenter.themedLogoUrl ?? undefined;
|
||||
|
||||
const slots = topBar();
|
||||
@@ -81,11 +79,11 @@ export function TopBar({ queryKey }: TopBarProps) {
|
||||
color="neutral"
|
||||
radius="small"
|
||||
src={logoUrl}
|
||||
fallback={organizationName.charAt(0) || "?"}
|
||||
fallback={title.charAt(0) || "?"}
|
||||
className={slots.logo()}
|
||||
/>
|
||||
<Text size={2} weight="medium" color="neutral" highContrast className={slots.brandName()}>
|
||||
{organizationName}
|
||||
{title}
|
||||
</Text>
|
||||
<Text size={2} color="neutral" className={slots.tagline()}>
|
||||
{t("topBar.tagline")}
|
||||
|
||||
@@ -34,9 +34,7 @@ import type { HomePageQuery } from "./__generated__/HomePageQuery.graphql";
|
||||
export const homePageQuery = graphql`
|
||||
query HomePageQuery @throwOnFieldError {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
organization {
|
||||
name
|
||||
}
|
||||
title
|
||||
...TrustCenterContactInfo_trustCenter
|
||||
...ComplianceFrameworksSection_trustCenter
|
||||
...SecurityCommitmentsSection_trustCenter
|
||||
@@ -54,12 +52,12 @@ export function HomePage({ queryRef }: HomePageProps) {
|
||||
const { t } = useTranslation();
|
||||
const data = usePreloadedQuery<HomePageQuery>(homePageQuery, queryRef);
|
||||
const { currentTrustCenter } = data;
|
||||
const { organization } = currentTrustCenter;
|
||||
const { title } = currentTrustCenter;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Hero
|
||||
title={t("home.heroTitle", { name: organization.name })}
|
||||
title={t("home.heroTitle", { name: title })}
|
||||
description={t("home.heroDescription")}
|
||||
>
|
||||
<TrustCenterContactInfo trustCenterKey={currentTrustCenter} />
|
||||
|
||||
@@ -32,6 +32,7 @@ const updateCompliancePageMutation = graphql`
|
||||
id
|
||||
active
|
||||
searchEngineIndexing
|
||||
title
|
||||
description
|
||||
websiteUrl
|
||||
email
|
||||
|
||||
@@ -25,6 +25,7 @@ import { useFormWithSchema } from "#/hooks/useFormWithSchema";
|
||||
const compliancePageFragment = graphql`
|
||||
fragment CompliancePageProfileSection_compliancePageFragment on TrustCenter {
|
||||
id
|
||||
title
|
||||
description
|
||||
websiteUrl
|
||||
email
|
||||
@@ -34,6 +35,7 @@ const compliancePageFragment = graphql`
|
||||
`;
|
||||
|
||||
const profileSchema = z.object({
|
||||
title: z.string().min(1),
|
||||
description: z.string().optional(),
|
||||
websiteUrl: z.string().optional(),
|
||||
email: z.string().optional(),
|
||||
@@ -56,6 +58,7 @@ export function CompliancePageProfileSection(props: {
|
||||
|
||||
const { formState, handleSubmit, register } = useFormWithSchema(profileSchema, {
|
||||
defaultValues: {
|
||||
title: compliancePage.title,
|
||||
description: compliancePage.description || "",
|
||||
websiteUrl: compliancePage.websiteUrl || "",
|
||||
email: compliancePage.email || "",
|
||||
@@ -70,6 +73,7 @@ export function CompliancePageProfileSection(props: {
|
||||
variables: {
|
||||
input: {
|
||||
trustCenterId: compliancePage.id,
|
||||
title: data.title,
|
||||
description: data.description || null,
|
||||
websiteUrl: data.websiteUrl || null,
|
||||
email: data.email || null,
|
||||
@@ -91,6 +95,13 @@ export function CompliancePageProfileSection(props: {
|
||||
{formState.isSubmitting && <Spinner />}
|
||||
</div>
|
||||
<Card padded className="space-y-4">
|
||||
<Field
|
||||
{...register("title")}
|
||||
readOnly={readOnly}
|
||||
name="title"
|
||||
label={__("Title")}
|
||||
placeholder={__("Your company or product name")}
|
||||
/>
|
||||
<div>
|
||||
<Label>{__("Description")}</Label>
|
||||
<Textarea
|
||||
|
||||
@@ -185,7 +185,7 @@ export function CompliancePageVisualIdentitySection(props: CompliancePageVisualI
|
||||
<div>
|
||||
<h2 className="text-base font-medium">{__("Visual identity")}</h2>
|
||||
<p className="text-sm text-txt-tertiary">
|
||||
{__("Logos displayed on your public compliance page.")}
|
||||
{__("Square logos displayed on your public compliance page.")}
|
||||
</p>
|
||||
</div>
|
||||
{isUpdating && <Spinner />}
|
||||
@@ -196,7 +196,7 @@ export function CompliancePageVisualIdentitySection(props: CompliancePageVisualI
|
||||
<div className="flex-1">
|
||||
<Label>{__("Logo")}</Label>
|
||||
<p className="text-sm text-txt-tertiary mb-3">
|
||||
{__("This logo will be displayed on your public compliance page.")}
|
||||
{__("Upload a square logo for your public compliance page.")}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
@@ -211,7 +211,7 @@ export function CompliancePageVisualIdentitySection(props: CompliancePageVisualI
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div className="flex h-16 w-28 shrink-0 items-center justify-center rounded-md border border-dashed border-border-solid bg-surface-secondary text-xs text-txt-tertiary">
|
||||
<div className="flex size-16 shrink-0 items-center justify-center rounded-md border border-dashed border-border-solid bg-surface-secondary text-xs text-txt-tertiary">
|
||||
{__("No logo")}
|
||||
</div>
|
||||
)}
|
||||
@@ -230,7 +230,7 @@ export function CompliancePageVisualIdentitySection(props: CompliancePageVisualI
|
||||
</FileButton>
|
||||
{!currentLogoUrl && (
|
||||
<p className="text-xs text-txt-tertiary">
|
||||
{__("PNG, JPG, SVG, or WEBP up to 5MB")}
|
||||
{__("Square format. PNG, JPG, SVG, or WEBP up to 5MB")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -250,7 +250,7 @@ export function CompliancePageVisualIdentitySection(props: CompliancePageVisualI
|
||||
<div className="flex-1">
|
||||
<Label>{__("Dark mode logo")}</Label>
|
||||
<p className="text-sm text-txt-tertiary mb-3">
|
||||
{__("This logo will be used when dark mode is enabled.")}
|
||||
{__("Upload a square logo for use when dark mode is enabled.")}
|
||||
</p>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
@@ -265,7 +265,7 @@ export function CompliancePageVisualIdentitySection(props: CompliancePageVisualI
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<div className="flex h-16 w-28 shrink-0 items-center justify-center rounded-md border border-dashed border-border-solid bg-gray-900 text-xs text-txt-tertiary">
|
||||
<div className="flex size-16 shrink-0 items-center justify-center rounded-md border border-dashed border-border-solid bg-gray-900 text-xs text-txt-tertiary">
|
||||
{__("No logo")}
|
||||
</div>
|
||||
)}
|
||||
@@ -284,7 +284,7 @@ export function CompliancePageVisualIdentitySection(props: CompliancePageVisualI
|
||||
</FileButton>
|
||||
{!currentDarkLogoUrl && (
|
||||
<p className="text-xs text-txt-tertiary">
|
||||
{__("PNG, JPG, SVG, or WEBP up to 5MB")}
|
||||
{__("Square format. PNG, JPG, SVG, or WEBP up to 5MB")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -42,6 +42,9 @@ const compliancePageFragment = graphql`
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
framework {
|
||||
id
|
||||
}
|
||||
...CompliancePageFrameworkListItem_complianceFramework
|
||||
}
|
||||
}
|
||||
@@ -82,7 +85,7 @@ export function CompliancePageFrameworkList(props: CompliancePageFrameworkListPr
|
||||
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4">
|
||||
{edges.map(edge => (
|
||||
<CompliancePageFrameworkListItem
|
||||
key={edge.node.id}
|
||||
key={edge.node.framework.id}
|
||||
complianceFrameworkKey={edge.node}
|
||||
compliancePageKey={compliancePage}
|
||||
onRefetch={handleRefetch}
|
||||
|
||||
@@ -233,7 +233,7 @@ export function OrganizationSidebar({
|
||||
: (
|
||||
<div className="size-24 rounded-2xl border border-border-mid shadow-mid bg-level-1" />
|
||||
)}
|
||||
<h1 className="text-2xl mt-6">{trustCenter.organization.name}</h1>
|
||||
<h1 className="text-2xl mt-6">{trustCenter.title}</h1>
|
||||
<p className="text-sm text-txt-secondary mt-1">
|
||||
{trustCenter.description}
|
||||
</p>
|
||||
|
||||
@@ -24,7 +24,7 @@ import { TrustCenterContext } from "#/providers/TrustCenterProvider";
|
||||
|
||||
export function useTrustCenter(): {
|
||||
id: string;
|
||||
organization: { name: string };
|
||||
title: string;
|
||||
} {
|
||||
const context = useContext(TrustCenterContext);
|
||||
if (!context) {
|
||||
|
||||
@@ -47,9 +47,7 @@ export const ndaPageQuery = graphql`
|
||||
id
|
||||
}
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
organization {
|
||||
name
|
||||
}
|
||||
title
|
||||
nonDisclosureAgreement {
|
||||
fileName
|
||||
fileUrl
|
||||
@@ -246,7 +244,7 @@ export function NDAPage(props: {
|
||||
__(
|
||||
"%s requires you to sign an NDA before accessing compliance documents.",
|
||||
),
|
||||
trustCenter.organization.name,
|
||||
trustCenter.title,
|
||||
)}
|
||||
</p>
|
||||
{isMobile && nda?.fileUrl && (
|
||||
|
||||
@@ -107,7 +107,7 @@ export function OverviewPage() {
|
||||
url={getTrustCenterUrl("documents")}
|
||||
/>
|
||||
<Subprocessors
|
||||
organizationName={trustCenter.organization.name}
|
||||
title={trustCenter.title}
|
||||
subprocessors={fragment.subprocessors.edges}
|
||||
url={getTrustCenterUrl("subprocessors")}
|
||||
/>
|
||||
@@ -187,11 +187,11 @@ function Documents({
|
||||
function Subprocessors({
|
||||
subprocessors,
|
||||
url,
|
||||
organizationName,
|
||||
title,
|
||||
}: {
|
||||
subprocessors: OverviewPageFragment$data["subprocessors"]["edges"];
|
||||
url: string;
|
||||
organizationName: string;
|
||||
title: string;
|
||||
}) {
|
||||
const { __ } = useTranslate();
|
||||
if (subprocessors.length === 0) {
|
||||
@@ -209,7 +209,7 @@ function Subprocessors({
|
||||
<p className="text-sm text-txt-secondary mb-4">
|
||||
{sprintf(
|
||||
__("Third-party subprocessors %s work with:"),
|
||||
organizationName,
|
||||
title,
|
||||
)}
|
||||
</p>
|
||||
<Rows className="mb-8 *:py-5">
|
||||
|
||||
@@ -45,7 +45,7 @@ export function SubprocessorsPage({ queryRef }: Props) {
|
||||
<p className="text-sm text-txt-secondary mb-4">
|
||||
{sprintf(
|
||||
__("Third-party subprocessors %s work with:"),
|
||||
data.currentTrustCenter?.organization.name ?? "",
|
||||
data.currentTrustCenter?.title ?? "",
|
||||
)}
|
||||
</p>
|
||||
<Rows>
|
||||
|
||||
@@ -38,9 +38,7 @@ import { OIDCButton } from "./_components/OIDCButton";
|
||||
export const connectPageQuery = graphql`
|
||||
query ConnectPageQuery {
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
organization @required(action: THROW) {
|
||||
name
|
||||
}
|
||||
title
|
||||
}
|
||||
oidcProviders {
|
||||
...OIDCButtonFragment
|
||||
@@ -77,7 +75,7 @@ export function ConnectPage(props: {
|
||||
const safeContinueUrl = useSafeContinueUrl();
|
||||
|
||||
const {
|
||||
currentTrustCenter: { organization },
|
||||
currentTrustCenter: { title },
|
||||
oidcProviders,
|
||||
} = usePreloadedQuery<ConnectPageQuery>(connectPageQuery, queryRef);
|
||||
|
||||
@@ -98,7 +96,7 @@ export function ConnectPage(props: {
|
||||
};
|
||||
}, [magicLinkSent]);
|
||||
|
||||
usePageTitle(__(`Connect to ${organization.name}'s Compliance Page`));
|
||||
usePageTitle(__(`Connect to ${title}'s Compliance Page`));
|
||||
|
||||
const {
|
||||
handleSubmit: handleSubmitWrapper,
|
||||
@@ -164,7 +162,7 @@ export function ConnectPage(props: {
|
||||
<div className="space-y-6 w-full max-w-md mx-auto pt-8">
|
||||
<div className="space-y-2 text-center">
|
||||
<h1 className="text-3xl font-bold">
|
||||
{__(`Connect to ${organization.name}'s Compliance Page`)}
|
||||
{__(`Connect to ${title}'s Compliance Page`)}
|
||||
</h1>
|
||||
<p className="text-txt-tertiary">
|
||||
{__(
|
||||
|
||||
@@ -31,6 +31,7 @@ export const currentTrustGraphQuery = graphql`
|
||||
currentTrustCenter @required(action: THROW) {
|
||||
id
|
||||
slug
|
||||
title
|
||||
description
|
||||
websiteUrl
|
||||
email
|
||||
@@ -54,9 +55,6 @@ export const currentTrustGraphQuery = graphql`
|
||||
status
|
||||
}
|
||||
}
|
||||
organization {
|
||||
name
|
||||
}
|
||||
customLinks(first: 20) {
|
||||
edges {
|
||||
node {
|
||||
@@ -96,9 +94,7 @@ export const currentTrustDocumentsQuery = graphql`
|
||||
query TrustGraphCurrentDocumentsQuery {
|
||||
currentTrustCenter {
|
||||
id
|
||||
organization {
|
||||
name
|
||||
}
|
||||
title
|
||||
documents(first: 50) {
|
||||
edges {
|
||||
node {
|
||||
@@ -125,9 +121,7 @@ export const currentTrustSubprocessorsQuery = graphql`
|
||||
query TrustGraphCurrentSubprocessorsQuery {
|
||||
currentTrustCenter {
|
||||
id
|
||||
organization {
|
||||
name
|
||||
}
|
||||
title
|
||||
subprocessors(first: 50) {
|
||||
edges {
|
||||
node {
|
||||
|
||||
Reference in New Issue
Block a user