Replace portal title with entity name
Store a short entity name instead of the full home heading so orgs can brand portals for sub-entities. Restore hero i18n composition and keep the English document title composed from the entity name. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "Vertrauen bei {{name}}.",
|
||||||
"heroDescription": "Willkommen auf unserem Compliance-Portal. Hier finden Sie unsere Sicherheitsdokumentation und Zertifizierungen.",
|
"heroDescription": "Willkommen auf unserem Compliance-Portal. Hier finden Sie unsere Sicherheitsdokumentation und Zertifizierungen.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Compliance",
|
"compliance": "Compliance",
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "Compliance at {{name}}.",
|
||||||
"heroDescription": "Welcome to our Compliance Portal. Find our security documentation and certifications here.",
|
"heroDescription": "Welcome to our Compliance Portal. Find our security documentation and certifications here.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Compliance",
|
"compliance": "Compliance",
|
||||||
@@ -104,4 +105,4 @@
|
|||||||
"previous": "Previous page",
|
"previous": "Previous page",
|
||||||
"next": "Next page"
|
"next": "Next page"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "Confianza en {{name}}.",
|
||||||
"heroDescription": "Bienvenido a nuestro Portal de cumplimiento. Aquí encontrará nuestra documentación de seguridad y nuestras certificaciones.",
|
"heroDescription": "Bienvenido a nuestro Portal de cumplimiento. Aquí encontrará nuestra documentación de seguridad y nuestras certificaciones.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Cumplimiento",
|
"compliance": "Cumplimiento",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "La confiance chez {{name}}.",
|
||||||
"heroDescription": "Bienvenue dans notre Portail de conformité. Retrouvez ici notre documentation et nos certifications de sécurité.",
|
"heroDescription": "Bienvenue dans notre Portail de conformité. Retrouvez ici notre documentation et nos certifications de sécurité.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Conformité",
|
"compliance": "Conformité",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "Kepercayaan di {{name}}.",
|
||||||
"heroDescription": "Selamat datang di Portal Kepatuhan kami. Temukan dokumentasi keamanan dan sertifikasi kami di sini.",
|
"heroDescription": "Selamat datang di Portal Kepatuhan kami. Temukan dokumentasi keamanan dan sertifikasi kami di sini.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Kepatuhan",
|
"compliance": "Kepatuhan",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "La fiducia in {{name}}.",
|
||||||
"heroDescription": "Benvenuti nel nostro Portale di conformità. Qui potete trovare la nostra documentazione di sicurezza e le nostre certificazioni.",
|
"heroDescription": "Benvenuti nel nostro Portale di conformità. Qui potete trovare la nostra documentazione di sicurezza e le nostre certificazioni.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Conformità",
|
"compliance": "Conformità",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "{{name}}における信頼。",
|
||||||
"heroDescription": "コンプライアンスポータルへようこそ。セキュリティに関する文書や認証はこちらからご確認いただけます。",
|
"heroDescription": "コンプライアンスポータルへようこそ。セキュリティに関する文書や認証はこちらからご確認いただけます。",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "コンプライアンス",
|
"compliance": "コンプライアンス",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "{{name}}의 신뢰.",
|
||||||
"heroDescription": "컴플라이언스 포털에 오신 것을 환영합니다. 이곳에서 보안 문서와 인증 정보를 확인하실 수 있습니다.",
|
"heroDescription": "컴플라이언스 포털에 오신 것을 환영합니다. 이곳에서 보안 문서와 인증 정보를 확인하실 수 있습니다.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "컴플라이언스",
|
"compliance": "컴플라이언스",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "Zaufanie w {{name}}.",
|
||||||
"heroDescription": "Witamy w naszym Portalu Zgodności. Znajdziesz tu naszą dokumentację bezpieczeństwa i certyfikaty.",
|
"heroDescription": "Witamy w naszym Portalu Zgodności. Znajdziesz tu naszą dokumentację bezpieczeństwa i certyfikaty.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Zgodność",
|
"compliance": "Zgodność",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "A confiança na {{name}}.",
|
||||||
"heroDescription": "Bem-vindo ao nosso Portal de Conformidade. Encontre aqui a nossa documentação de segurança e certificações.",
|
"heroDescription": "Bem-vindo ao nosso Portal de Conformidade. Encontre aqui a nossa documentação de segurança e certificações.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Conformidade",
|
"compliance": "Conformidade",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "{{name}}'de Güven.",
|
||||||
"heroDescription": "Uyumluluk Portalımıza hoş geldiniz. Güvenlik belgelerimizi ve sertifikalarımızı burada bulabilirsiniz.",
|
"heroDescription": "Uyumluluk Portalımıza hoş geldiniz. Güvenlik belgelerimizi ve sertifikalarımızı burada bulabilirsiniz.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Uyumluluk",
|
"compliance": "Uyumluluk",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "Довіра в {{name}}.",
|
||||||
"heroDescription": "Вітаємо у нашому Порталі відповідності. Тут ви знайдете нашу документацію з безпеки та сертифікати.",
|
"heroDescription": "Вітаємо у нашому Порталі відповідності. Тут ви знайдете нашу документацію з безпеки та сертифікати.",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "Відповідність",
|
"compliance": "Відповідність",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
|
"heroTitle": "信赖 {{name}}。",
|
||||||
"heroDescription": "欢迎访问我们的合规门户。您可以在此查看我们的安全文档和认证。",
|
"heroDescription": "欢迎访问我们的合规门户。您可以在此查看我们的安全文档和认证。",
|
||||||
"sections": {
|
"sections": {
|
||||||
"compliance": "合规",
|
"compliance": "合规",
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const topBarFragment = graphql`
|
|||||||
}
|
}
|
||||||
currentCompliancePortal @required(action: THROW) {
|
currentCompliancePortal @required(action: THROW) {
|
||||||
themedLogoUrl
|
themedLogoUrl
|
||||||
title
|
entityName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -66,7 +66,7 @@ export function TopBar({ queryKey }: TopBarProps) {
|
|||||||
const localizedPath = useLocalizedPath();
|
const localizedPath = useLocalizedPath();
|
||||||
|
|
||||||
const { currentCompliancePortal } = data;
|
const { currentCompliancePortal } = data;
|
||||||
const title = currentCompliancePortal.title;
|
const entityName = currentCompliancePortal.entityName;
|
||||||
const logoUrl = currentCompliancePortal.themedLogoUrl ?? undefined;
|
const logoUrl = currentCompliancePortal.themedLogoUrl ?? undefined;
|
||||||
|
|
||||||
const slots = topBar();
|
const slots = topBar();
|
||||||
@@ -82,11 +82,11 @@ export function TopBar({ queryKey }: TopBarProps) {
|
|||||||
color="neutral"
|
color="neutral"
|
||||||
radius="small"
|
radius="small"
|
||||||
src={logoUrl}
|
src={logoUrl}
|
||||||
fallback={title.charAt(0) || "?"}
|
fallback={entityName.charAt(0) || "?"}
|
||||||
className={slots.logo()}
|
className={slots.logo()}
|
||||||
/>
|
/>
|
||||||
<Text size={2} weight="medium" color="neutral" highContrast className={slots.brandName()}>
|
<Text size={2} weight="medium" color="neutral" highContrast className={slots.brandName()}>
|
||||||
{title}
|
{entityName}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size={2} color="neutral" className={slots.tagline()}>
|
<Text size={2} color="neutral" className={slots.tagline()}>
|
||||||
{t("topBar.tagline")}
|
{t("topBar.tagline")}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export const subscribeDialogProviderFragment = graphql`
|
|||||||
}
|
}
|
||||||
currentCompliancePortal @required(action: THROW) {
|
currentCompliancePortal @required(action: THROW) {
|
||||||
id
|
id
|
||||||
title
|
entityName
|
||||||
viewerSubscription {
|
viewerSubscription {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ export function SubscribeDialogProvider({
|
|||||||
const [unsubscribeFromMailingList, isUnsubscribing] = useUnsubscribeFromMailingList();
|
const [unsubscribeFromMailingList, isUnsubscribing] = useUnsubscribeFromMailingList();
|
||||||
|
|
||||||
const viewer = data.viewer;
|
const viewer = data.viewer;
|
||||||
const { id: trustCenterId, title, viewerSubscription } = data.currentCompliancePortal;
|
const { id: trustCenterId, entityName, viewerSubscription } = data.currentCompliancePortal;
|
||||||
const isSubscribed = viewerSubscription != null;
|
const isSubscribed = viewerSubscription != null;
|
||||||
|
|
||||||
const openSubscribe = useCallback(() => {
|
const openSubscribe = useCallback(() => {
|
||||||
@@ -127,7 +127,7 @@ export function SubscribeDialogProvider({
|
|||||||
onOpenChange={setDialogOpen}
|
onOpenChange={setDialogOpen}
|
||||||
trustCenterId={trustCenterId}
|
trustCenterId={trustCenterId}
|
||||||
viewerEmail={viewer.email}
|
viewerEmail={viewer.email}
|
||||||
organizationName={title}
|
organizationName={entityName}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SubscribeDialogContextProvider>
|
</SubscribeDialogContextProvider>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import type { HomePageQuery } from "./__generated__/HomePageQuery.graphql";
|
|||||||
export const homePageQuery = graphql`
|
export const homePageQuery = graphql`
|
||||||
query HomePageQuery @throwOnFieldError {
|
query HomePageQuery @throwOnFieldError {
|
||||||
currentCompliancePortal @required(action: THROW) {
|
currentCompliancePortal @required(action: THROW) {
|
||||||
title
|
entityName
|
||||||
...CompliancePortalContactInfo_compliancePortal
|
...CompliancePortalContactInfo_compliancePortal
|
||||||
...ComplianceFrameworksSection_compliancePortal
|
...ComplianceFrameworksSection_compliancePortal
|
||||||
...SecurityCommitmentsSection_compliancePortal
|
...SecurityCommitmentsSection_compliancePortal
|
||||||
@@ -52,12 +52,12 @@ export function HomePage({ queryRef }: HomePageProps) {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const data = usePreloadedQuery<HomePageQuery>(homePageQuery, queryRef);
|
const data = usePreloadedQuery<HomePageQuery>(homePageQuery, queryRef);
|
||||||
const { currentCompliancePortal } = data;
|
const { currentCompliancePortal } = data;
|
||||||
const { title } = currentCompliancePortal;
|
const { entityName } = currentCompliancePortal;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero
|
<Hero
|
||||||
title={title}
|
title={t("home.heroTitle", { name: entityName })}
|
||||||
description={t("home.heroDescription")}
|
description={t("home.heroDescription")}
|
||||||
>
|
>
|
||||||
<CompliancePortalContactInfo compliancePortalKey={currentCompliancePortal} />
|
<CompliancePortalContactInfo compliancePortalKey={currentCompliancePortal} />
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export const ndaPageQuery = graphql`
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
currentCompliancePortal @required(action: THROW) {
|
currentCompliancePortal @required(action: THROW) {
|
||||||
title
|
entityName
|
||||||
nonDisclosureAgreement {
|
nonDisclosureAgreement {
|
||||||
fileUrl
|
fileUrl
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ export function NDAPage({ queryRef }: NDAPageProps) {
|
|||||||
{t("title")}
|
{t("title")}
|
||||||
</Heading>
|
</Heading>
|
||||||
<Text size={2} color="neutral">
|
<Text size={2} color="neutral">
|
||||||
{t("subtitle", { name: compliancePortal.title })}
|
{t("subtitle", { name: compliancePortal.entityName })}
|
||||||
</Text>
|
</Text>
|
||||||
{signature.consentText != null && (
|
{signature.consentText != null && (
|
||||||
<Text size={1} color="faint" className={slots.consent()}>
|
<Text size={1} color="faint" className={slots.consent()}>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const updateCompliancePageMutation = graphql`
|
|||||||
id
|
id
|
||||||
active
|
active
|
||||||
searchEngineIndexing
|
searchEngineIndexing
|
||||||
title
|
entityName
|
||||||
description
|
description
|
||||||
websiteUrl
|
websiteUrl
|
||||||
email
|
email
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { useFormWithSchema } from "#/hooks/useFormWithSchema";
|
|||||||
const compliancePageFragment = graphql`
|
const compliancePageFragment = graphql`
|
||||||
fragment CompliancePageProfileSection_compliancePageFragment on CompliancePortal {
|
fragment CompliancePageProfileSection_compliancePageFragment on CompliancePortal {
|
||||||
id
|
id
|
||||||
title
|
entityName
|
||||||
description
|
description
|
||||||
websiteUrl
|
websiteUrl
|
||||||
email
|
email
|
||||||
@@ -35,7 +35,7 @@ const compliancePageFragment = graphql`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const profileSchema = z.object({
|
const profileSchema = z.object({
|
||||||
title: z.string().min(1),
|
entityName: z.string().min(1),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
websiteUrl: z.string().optional(),
|
websiteUrl: z.string().optional(),
|
||||||
email: z.string().optional(),
|
email: z.string().optional(),
|
||||||
@@ -58,7 +58,7 @@ export function CompliancePageProfileSection(props: {
|
|||||||
|
|
||||||
const { formState, handleSubmit, register } = useFormWithSchema(profileSchema, {
|
const { formState, handleSubmit, register } = useFormWithSchema(profileSchema, {
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
title: compliancePage.title,
|
entityName: compliancePage.entityName,
|
||||||
description: compliancePage.description || "",
|
description: compliancePage.description || "",
|
||||||
websiteUrl: compliancePage.websiteUrl || "",
|
websiteUrl: compliancePage.websiteUrl || "",
|
||||||
email: compliancePage.email || "",
|
email: compliancePage.email || "",
|
||||||
@@ -73,7 +73,7 @@ export function CompliancePageProfileSection(props: {
|
|||||||
variables: {
|
variables: {
|
||||||
input: {
|
input: {
|
||||||
compliancePortalId: compliancePage.id,
|
compliancePortalId: compliancePage.id,
|
||||||
title: data.title,
|
entityName: data.entityName,
|
||||||
description: data.description || null,
|
description: data.description || null,
|
||||||
websiteUrl: data.websiteUrl || null,
|
websiteUrl: data.websiteUrl || null,
|
||||||
email: data.email || null,
|
email: data.email || null,
|
||||||
@@ -96,11 +96,11 @@ export function CompliancePageProfileSection(props: {
|
|||||||
</div>
|
</div>
|
||||||
<Card padded className="space-y-4">
|
<Card padded className="space-y-4">
|
||||||
<Field
|
<Field
|
||||||
{...register("title")}
|
{...register("entityName")}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
name="title"
|
name="entityName"
|
||||||
label={__("Title")}
|
label={__("Entity name")}
|
||||||
placeholder={__("Compliance at Acme.")}
|
placeholder={__("Acme")}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<Label>{__("Description")}</Label>
|
<Label>{__("Description")}</Label>
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ export function OrganizationSidebar({
|
|||||||
: (
|
: (
|
||||||
<div className="size-24 rounded-2xl border border-border-mid shadow-mid bg-level-1" />
|
<div className="size-24 rounded-2xl border border-border-mid shadow-mid bg-level-1" />
|
||||||
)}
|
)}
|
||||||
<h1 className="text-2xl mt-6">{compliancePortal.title}</h1>
|
<h1 className="text-2xl mt-6">{compliancePortal.entityName}</h1>
|
||||||
<p className="text-sm text-txt-secondary mt-1">
|
<p className="text-sm text-txt-secondary mt-1">
|
||||||
{compliancePortal.description}
|
{compliancePortal.description}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { CompliancePortalContext } from "#/providers/CompliancePortalProvider";
|
|||||||
|
|
||||||
export function useCompliancePortal(): {
|
export function useCompliancePortal(): {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
entityName: string;
|
||||||
} {
|
} {
|
||||||
const context = useContext(CompliancePortalContext);
|
const context = useContext(CompliancePortalContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export const ndaPageQuery = graphql`
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
currentCompliancePortal @required(action: THROW) {
|
currentCompliancePortal @required(action: THROW) {
|
||||||
title
|
entityName
|
||||||
nonDisclosureAgreement {
|
nonDisclosureAgreement {
|
||||||
fileName
|
fileName
|
||||||
fileUrl
|
fileUrl
|
||||||
@@ -244,7 +244,7 @@ export function NDAPage(props: {
|
|||||||
__(
|
__(
|
||||||
"%s requires you to sign an NDA before accessing compliance documents.",
|
"%s requires you to sign an NDA before accessing compliance documents.",
|
||||||
),
|
),
|
||||||
compliancePortal.title,
|
compliancePortal.entityName,
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
{isMobile && nda?.fileUrl && (
|
{isMobile && nda?.fileUrl && (
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ export function OverviewPage() {
|
|||||||
url={getCompliancePortalUrl("documents")}
|
url={getCompliancePortalUrl("documents")}
|
||||||
/>
|
/>
|
||||||
<Subprocessors
|
<Subprocessors
|
||||||
title={compliancePortal.title}
|
title={compliancePortal.entityName}
|
||||||
subprocessors={fragment.subprocessors.edges}
|
subprocessors={fragment.subprocessors.edges}
|
||||||
url={getCompliancePortalUrl("subprocessors")}
|
url={getCompliancePortalUrl("subprocessors")}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function SubprocessorsPage({ queryRef }: Props) {
|
|||||||
<p className="text-sm text-txt-secondary mb-4">
|
<p className="text-sm text-txt-secondary mb-4">
|
||||||
{sprintf(
|
{sprintf(
|
||||||
__("Third-party subprocessors %s work with:"),
|
__("Third-party subprocessors %s work with:"),
|
||||||
data.currentCompliancePortal?.title ?? "",
|
data.currentCompliancePortal?.entityName ?? "",
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<Rows>
|
<Rows>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import type { ConnectPageQuery } from "./__generated__/ConnectPageQuery.graphql"
|
|||||||
export const connectPageQuery = graphql`
|
export const connectPageQuery = graphql`
|
||||||
query ConnectPageQuery {
|
query ConnectPageQuery {
|
||||||
currentCompliancePortal @required(action: THROW) {
|
currentCompliancePortal @required(action: THROW) {
|
||||||
title
|
entityName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -45,10 +45,10 @@ export function ConnectPage(props: {
|
|||||||
const safeContinueUrl = useSafeContinueUrl();
|
const safeContinueUrl = useSafeContinueUrl();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
currentCompliancePortal: { title },
|
currentCompliancePortal: { entityName },
|
||||||
} = usePreloadedQuery<ConnectPageQuery>(connectPageQuery, queryRef);
|
} = usePreloadedQuery<ConnectPageQuery>(connectPageQuery, queryRef);
|
||||||
|
|
||||||
usePageTitle(__(`Connect to ${title}'s Compliance Page`));
|
usePageTitle(__(`Connect to ${entityName}'s Compliance Page`));
|
||||||
|
|
||||||
const initiateURL = new URL("/initiate", window.location.origin);
|
const initiateURL = new URL("/initiate", window.location.origin);
|
||||||
initiateURL.searchParams.set("continue", safeContinueUrl.toString());
|
initiateURL.searchParams.set("continue", safeContinueUrl.toString());
|
||||||
@@ -57,7 +57,7 @@ export function ConnectPage(props: {
|
|||||||
<div className="space-y-6 w-full max-w-md mx-auto pt-8">
|
<div className="space-y-6 w-full max-w-md mx-auto pt-8">
|
||||||
<div className="space-y-2 text-center">
|
<div className="space-y-2 text-center">
|
||||||
<h1 className="text-3xl font-bold">
|
<h1 className="text-3xl font-bold">
|
||||||
{__(`Connect to ${title}'s Compliance Page`)}
|
{__(`Connect to ${entityName}'s Compliance Page`)}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-txt-tertiary">
|
<p className="text-txt-tertiary">
|
||||||
{__(
|
{__(
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const currentCompliancePortalGraphQuery = graphql`
|
|||||||
currentCompliancePortal @required(action: THROW) {
|
currentCompliancePortal @required(action: THROW) {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
title
|
entityName
|
||||||
description
|
description
|
||||||
websiteUrl
|
websiteUrl
|
||||||
email
|
email
|
||||||
@@ -120,6 +120,7 @@ export const currentTrustSubprocessorsQuery = graphql`
|
|||||||
query CompliancePortalGraphCurrentSubprocessorsQuery {
|
query CompliancePortalGraphCurrentSubprocessorsQuery {
|
||||||
currentCompliancePortal {
|
currentCompliancePortal {
|
||||||
id
|
id
|
||||||
|
entityName
|
||||||
subprocessors(first: 50) {
|
subprocessors(first: 50) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ func TestCompliancePortal_UpdateProfile(t *testing.T) {
|
|||||||
updateCompliancePortal(input: $input) {
|
updateCompliancePortal(input: $input) {
|
||||||
compliancePortal {
|
compliancePortal {
|
||||||
id
|
id
|
||||||
title
|
entityName
|
||||||
description
|
description
|
||||||
websiteUrl
|
websiteUrl
|
||||||
email
|
email
|
||||||
@@ -75,7 +75,7 @@ func TestCompliancePortal_UpdateProfile(t *testing.T) {
|
|||||||
UpdateCompliancePortal struct {
|
UpdateCompliancePortal struct {
|
||||||
CompliancePortal struct {
|
CompliancePortal struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
EntityName string `json:"entityName"`
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
WebsiteURL *string `json:"websiteUrl"`
|
WebsiteURL *string `json:"websiteUrl"`
|
||||||
Email *string `json:"email"`
|
Email *string `json:"email"`
|
||||||
@@ -87,7 +87,7 @@ func TestCompliancePortal_UpdateProfile(t *testing.T) {
|
|||||||
err = owner.Execute(updateMutation, map[string]any{
|
err = owner.Execute(updateMutation, map[string]any{
|
||||||
"input": map[string]any{
|
"input": map[string]any{
|
||||||
"compliancePortalId": compliancePortalID,
|
"compliancePortalId": compliancePortalID,
|
||||||
"title": "Acme Security",
|
"entityName": "Acme Security",
|
||||||
"description": "We keep your data safe.",
|
"description": "We keep your data safe.",
|
||||||
"websiteUrl": "https://example.com",
|
"websiteUrl": "https://example.com",
|
||||||
"email": "security@example.com",
|
"email": "security@example.com",
|
||||||
@@ -98,7 +98,7 @@ func TestCompliancePortal_UpdateProfile(t *testing.T) {
|
|||||||
|
|
||||||
tc := result.UpdateCompliancePortal.CompliancePortal
|
tc := result.UpdateCompliancePortal.CompliancePortal
|
||||||
assert.Equal(t, compliancePortalID, tc.ID)
|
assert.Equal(t, compliancePortalID, tc.ID)
|
||||||
assert.Equal(t, "Acme Security", tc.Title)
|
assert.Equal(t, "Acme Security", tc.EntityName)
|
||||||
require.NotNil(t, tc.Description)
|
require.NotNil(t, tc.Description)
|
||||||
assert.Equal(t, "We keep your data safe.", *tc.Description)
|
assert.Equal(t, "We keep your data safe.", *tc.Description)
|
||||||
require.NotNil(t, tc.WebsiteURL)
|
require.NotNil(t, tc.WebsiteURL)
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ type mcpFile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type compliancePortal struct {
|
type compliancePortal struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
EntityName string `json:"entity_name"`
|
||||||
Active bool `json:"active"`
|
Active bool `json:"active"`
|
||||||
Logo *mcpFile `json:"logo,omitempty"`
|
Logo *mcpFile `json:"logo,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type compliancePortalReference struct {
|
type compliancePortalReference struct {
|
||||||
@@ -175,7 +175,7 @@ func TestMCP_UpdateCompliancePortal(t *testing.T) {
|
|||||||
var updateResult struct {
|
var updateResult struct {
|
||||||
CompliancePortal struct {
|
CompliancePortal struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
EntityName string `json:"entity_name"`
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
WebsiteURL *string `json:"website_url"`
|
WebsiteURL *string `json:"website_url"`
|
||||||
Email *string `json:"email"`
|
Email *string `json:"email"`
|
||||||
@@ -184,7 +184,7 @@ func TestMCP_UpdateCompliancePortal(t *testing.T) {
|
|||||||
}
|
}
|
||||||
mc.CallToolInto("updateCompliancePortal", map[string]any{
|
mc.CallToolInto("updateCompliancePortal", map[string]any{
|
||||||
"compliance_portal_id": getResult.CompliancePortal.ID,
|
"compliance_portal_id": getResult.CompliancePortal.ID,
|
||||||
"title": "Acme Security",
|
"entity_name": "Acme Security",
|
||||||
"description": "We keep your data safe.",
|
"description": "We keep your data safe.",
|
||||||
"website_url": "https://example.com",
|
"website_url": "https://example.com",
|
||||||
"email": "security@example.com",
|
"email": "security@example.com",
|
||||||
@@ -192,7 +192,7 @@ func TestMCP_UpdateCompliancePortal(t *testing.T) {
|
|||||||
}, &updateResult)
|
}, &updateResult)
|
||||||
|
|
||||||
assert.Equal(t, getResult.CompliancePortal.ID, updateResult.CompliancePortal.ID)
|
assert.Equal(t, getResult.CompliancePortal.ID, updateResult.CompliancePortal.ID)
|
||||||
assert.Equal(t, "Acme Security", updateResult.CompliancePortal.Title)
|
assert.Equal(t, "Acme Security", updateResult.CompliancePortal.EntityName)
|
||||||
require.NotNil(t, updateResult.CompliancePortal.Description)
|
require.NotNil(t, updateResult.CompliancePortal.Description)
|
||||||
assert.Equal(t, "We keep your data safe.", *updateResult.CompliancePortal.Description)
|
assert.Equal(t, "We keep your data safe.", *updateResult.CompliancePortal.Description)
|
||||||
require.NotNil(t, updateResult.CompliancePortal.WebsiteURL)
|
require.NotNil(t, updateResult.CompliancePortal.WebsiteURL)
|
||||||
|
|||||||
@@ -83,20 +83,20 @@ func TestCompliancePortal_VisitorConnectViaCIMD(t *testing.T) {
|
|||||||
const query = `
|
const query = `
|
||||||
query {
|
query {
|
||||||
currentCompliancePortal {
|
currentCompliancePortal {
|
||||||
title
|
entityName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
var result struct {
|
var result struct {
|
||||||
CurrentCompliancePortal struct {
|
CurrentCompliancePortal struct {
|
||||||
Title string `json:"title"`
|
EntityName string `json:"entityName"`
|
||||||
} `json:"currentCompliancePortal"`
|
} `json:"currentCompliancePortal"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := visitor.ExecuteTrust(trustHost, query, nil, &result)
|
err := visitor.ExecuteTrust(trustHost, query, nil, &result)
|
||||||
require.NoError(t, err, "visitor session must authenticate trust GraphQL after CIMD connect")
|
require.NoError(t, err, "visitor session must authenticate trust GraphQL after CIMD connect")
|
||||||
assert.NotEmpty(t, result.CurrentCompliancePortal.Title)
|
assert.NotEmpty(t, result.CurrentCompliancePortal.EntityName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompliancePortal_UnknownCIMDClientRejected(t *testing.T) {
|
func TestCompliancePortal_UnknownCIMDClientRejected(t *testing.T) {
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ export const description: INodeProperties[] = [
|
|||||||
description: 'Whether search engines should index the compliance portal',
|
description: 'Whether search engines should index the compliance portal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Title',
|
displayName: 'Entity Name',
|
||||||
name: 'title',
|
name: 'entityName',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
@@ -87,7 +87,7 @@ export const description: INodeProperties[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
default: '',
|
default: '',
|
||||||
description: 'The title shown on the public compliance page',
|
description: 'The entity name shown on the public compliance page',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
displayName: 'Description',
|
displayName: 'Description',
|
||||||
@@ -155,7 +155,7 @@ export async function execute(
|
|||||||
const websiteUrl = this.getNodeParameter('websiteUrl', itemIndex, '') as string;
|
const websiteUrl = this.getNodeParameter('websiteUrl', itemIndex, '') as string;
|
||||||
const email = this.getNodeParameter('email', itemIndex, '') as string;
|
const email = this.getNodeParameter('email', itemIndex, '') as string;
|
||||||
const headquarterAddress = this.getNodeParameter('headquarterAddress', itemIndex, '') as string;
|
const headquarterAddress = this.getNodeParameter('headquarterAddress', itemIndex, '') as string;
|
||||||
const title = this.getNodeParameter('title', itemIndex, '') as string;
|
const entityName = this.getNodeParameter('entityName', itemIndex, '') as string;
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
mutation UpdateCompliancePortal($input: UpdateCompliancePortalInput!) {
|
mutation UpdateCompliancePortal($input: UpdateCompliancePortalInput!) {
|
||||||
@@ -164,7 +164,7 @@ export async function execute(
|
|||||||
id
|
id
|
||||||
active
|
active
|
||||||
searchEngineIndexing
|
searchEngineIndexing
|
||||||
title
|
entityName
|
||||||
description
|
description
|
||||||
websiteUrl
|
websiteUrl
|
||||||
email
|
email
|
||||||
@@ -178,7 +178,7 @@ export async function execute(
|
|||||||
|
|
||||||
const input: Record<string, unknown> = {
|
const input: Record<string, unknown> = {
|
||||||
compliancePortalId,
|
compliancePortalId,
|
||||||
title,
|
entityName,
|
||||||
description,
|
description,
|
||||||
websiteUrl,
|
websiteUrl,
|
||||||
email,
|
email,
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ mutation($input: UpdateCompliancePortalInput!) {
|
|||||||
id
|
id
|
||||||
active
|
active
|
||||||
searchEngineIndexing
|
searchEngineIndexing
|
||||||
title
|
entityName
|
||||||
description
|
description
|
||||||
websiteUrl
|
websiteUrl
|
||||||
email
|
email
|
||||||
@@ -74,7 +74,7 @@ type updateResponse struct {
|
|||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Active bool `json:"active"`
|
Active bool `json:"active"`
|
||||||
SearchEngineIndexing string `json:"searchEngineIndexing"`
|
SearchEngineIndexing string `json:"searchEngineIndexing"`
|
||||||
Title string `json:"title"`
|
EntityName string `json:"entityName"`
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
WebsiteURL *string `json:"websiteUrl"`
|
WebsiteURL *string `json:"websiteUrl"`
|
||||||
Email *string `json:"email"`
|
Email *string `json:"email"`
|
||||||
@@ -92,7 +92,7 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
|||||||
flagWebsiteURL string
|
flagWebsiteURL string
|
||||||
flagEmail string
|
flagEmail string
|
||||||
flagHeadquarterAddress string
|
flagHeadquarterAddress string
|
||||||
flagTitle string
|
flagEntityName string
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@@ -193,8 +193,8 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
|||||||
input["headquarterAddress"] = flagHeadquarterAddress
|
input["headquarterAddress"] = flagHeadquarterAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmd.Flags().Changed("title") {
|
if cmd.Flags().Changed("entity-name") {
|
||||||
input["title"] = flagTitle
|
input["entityName"] = flagEntityName
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(input) == 1 {
|
if len(input) == 1 {
|
||||||
@@ -232,7 +232,7 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
|
|||||||
cmd.Flags().StringVar(&flagWebsiteURL, "website-url", "", "Compliance page website URL")
|
cmd.Flags().StringVar(&flagWebsiteURL, "website-url", "", "Compliance page website URL")
|
||||||
cmd.Flags().StringVar(&flagEmail, "email", "", "Compliance page contact email")
|
cmd.Flags().StringVar(&flagEmail, "email", "", "Compliance page contact email")
|
||||||
cmd.Flags().StringVar(&flagHeadquarterAddress, "headquarter-address", "", "Compliance page headquarter address")
|
cmd.Flags().StringVar(&flagHeadquarterAddress, "headquarter-address", "", "Compliance page headquarter address")
|
||||||
cmd.Flags().StringVar(&flagTitle, "title", "", "Public compliance page title")
|
cmd.Flags().StringVar(&flagEntityName, "entity-name", "", "Entity name shown on the public compliance page")
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ type (
|
|||||||
Slug *string
|
Slug *string
|
||||||
SearchEngineIndexing *coredata.SearchEngineIndexing
|
SearchEngineIndexing *coredata.SearchEngineIndexing
|
||||||
NonDisclosureAgreementFileID *gid.GID
|
NonDisclosureAgreementFileID *gid.GID
|
||||||
Title *string
|
EntityName *string
|
||||||
Description **string
|
Description **string
|
||||||
WebsiteURL **string
|
WebsiteURL **string
|
||||||
Email **string
|
Email **string
|
||||||
@@ -75,8 +75,8 @@ func (utcr *UpdateRequest) Validate() error {
|
|||||||
v.Check(utcr.Slug, "slug", validator.SafeText(NameMaxLength))
|
v.Check(utcr.Slug, "slug", validator.SafeText(NameMaxLength))
|
||||||
v.Check(utcr.NonDisclosureAgreementFileID, "non_disclosure_agreement_file_id", validator.GID(coredata.FileEntityType))
|
v.Check(utcr.NonDisclosureAgreementFileID, "non_disclosure_agreement_file_id", validator.GID(coredata.FileEntityType))
|
||||||
|
|
||||||
if utcr.Title != nil {
|
if utcr.EntityName != nil {
|
||||||
v.Check(*utcr.Title, "title", validator.Required(), validator.SafeTextNoNewLine(TitleMaxLength))
|
v.Check(*utcr.EntityName, "entity_name", validator.Required(), validator.SafeTextNoNewLine(TitleMaxLength))
|
||||||
}
|
}
|
||||||
|
|
||||||
if utcr.Description != nil {
|
if utcr.Description != nil {
|
||||||
@@ -214,8 +214,8 @@ func (s *Service) Update(
|
|||||||
portal.SearchEngineIndexing = *req.SearchEngineIndexing
|
portal.SearchEngineIndexing = *req.SearchEngineIndexing
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Title != nil {
|
if req.EntityName != nil {
|
||||||
portal.Title = *req.Title
|
portal.EntityName = *req.EntityName
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Description != nil {
|
if req.Description != nil {
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func BuildClientMetadataDocument(
|
|||||||
|
|
||||||
doc := oauth2.ClientMetadataDocument{
|
doc := oauth2.ClientMetadataDocument{
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
ClientName: portal.Title,
|
ClientName: "Compliance at " + portal.EntityName + ".",
|
||||||
ClientURI: portalRootURL,
|
ClientURI: portalRootURL,
|
||||||
RedirectURIs: []string{redirectURI},
|
RedirectURIs: []string{redirectURI},
|
||||||
TokenEndpointAuthMethod: "none",
|
TokenEndpointAuthMethod: "none",
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ func TestBuildClientMetadataDocument(t *testing.T) {
|
|||||||
|
|
||||||
websiteURL := "https://www.acme.com"
|
websiteURL := "https://www.acme.com"
|
||||||
portal := &coredata.CompliancePortal{
|
portal := &coredata.CompliancePortal{
|
||||||
Title: "Acme Compliance Page",
|
EntityName: "Acme",
|
||||||
WebsiteURL: &websiteURL,
|
WebsiteURL: &websiteURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ func TestBuildClientMetadataDocument(t *testing.T) {
|
|||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "https://acme.example.com/.well-known/oauth-client-metadata", doc.ClientID)
|
assert.Equal(t, "https://acme.example.com/.well-known/oauth-client-metadata", doc.ClientID)
|
||||||
assert.Equal(t, "Acme Compliance Page", doc.ClientName)
|
assert.Equal(t, "Compliance at Acme.", doc.ClientName)
|
||||||
assert.Equal(t, []string{"https://acme.example.com/callback"}, doc.RedirectURIs)
|
assert.Equal(t, []string{"https://acme.example.com/callback"}, doc.RedirectURIs)
|
||||||
assert.Equal(t, "https://acme.example.com", doc.ClientURI)
|
assert.Equal(t, "https://acme.example.com", doc.ClientURI)
|
||||||
assert.Equal(t, VisitorOAuthScope, doc.Scope)
|
assert.Equal(t, VisitorOAuthScope, doc.Scope)
|
||||||
@@ -88,7 +88,7 @@ func TestBuildClientMetadataDocument_LogoURIUsesBrandLogoEndpoint(t *testing.T)
|
|||||||
|
|
||||||
logoFileID := gid.MustParseGID("WR-qMrB5AAEAGQAAAZ9mIO8B8vDFQ-i3")
|
logoFileID := gid.MustParseGID("WR-qMrB5AAEAGQAAAZ9mIO8B8vDFQ-i3")
|
||||||
portal := &coredata.CompliancePortal{
|
portal := &coredata.CompliancePortal{
|
||||||
Title: "Acme Compliance Page",
|
EntityName: "Acme",
|
||||||
LogoFileID: &logoFileID,
|
LogoFileID: &logoFileID,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ type (
|
|||||||
NonDisclosureAgreementFileID *gid.GID `db:"non_disclosure_agreement_file_id"`
|
NonDisclosureAgreementFileID *gid.GID `db:"non_disclosure_agreement_file_id"`
|
||||||
DefaultDomainID *gid.GID `db:"default_domain_id"`
|
DefaultDomainID *gid.GID `db:"default_domain_id"`
|
||||||
CustomDomainID *gid.GID `db:"custom_domain_id"`
|
CustomDomainID *gid.GID `db:"custom_domain_id"`
|
||||||
Title string `db:"title"`
|
EntityName string `db:"entity_name"`
|
||||||
Description *string `db:"description"`
|
Description *string `db:"description"`
|
||||||
WebsiteURL *string `db:"website_url"`
|
WebsiteURL *string `db:"website_url"`
|
||||||
Email *string `db:"email"`
|
Email *string `db:"email"`
|
||||||
@@ -129,7 +129,7 @@ SELECT
|
|||||||
non_disclosure_agreement_file_id,
|
non_disclosure_agreement_file_id,
|
||||||
default_domain_id,
|
default_domain_id,
|
||||||
custom_domain_id,
|
custom_domain_id,
|
||||||
title,
|
entity_name,
|
||||||
description,
|
description,
|
||||||
website_url,
|
website_url,
|
||||||
email,
|
email,
|
||||||
@@ -188,7 +188,7 @@ SELECT
|
|||||||
non_disclosure_agreement_file_id,
|
non_disclosure_agreement_file_id,
|
||||||
default_domain_id,
|
default_domain_id,
|
||||||
custom_domain_id,
|
custom_domain_id,
|
||||||
title,
|
entity_name,
|
||||||
description,
|
description,
|
||||||
website_url,
|
website_url,
|
||||||
email,
|
email,
|
||||||
@@ -247,7 +247,7 @@ SELECT
|
|||||||
non_disclosure_agreement_file_id,
|
non_disclosure_agreement_file_id,
|
||||||
default_domain_id,
|
default_domain_id,
|
||||||
custom_domain_id,
|
custom_domain_id,
|
||||||
title,
|
entity_name,
|
||||||
description,
|
description,
|
||||||
website_url,
|
website_url,
|
||||||
email,
|
email,
|
||||||
@@ -306,7 +306,7 @@ SELECT
|
|||||||
non_disclosure_agreement_file_id,
|
non_disclosure_agreement_file_id,
|
||||||
default_domain_id,
|
default_domain_id,
|
||||||
custom_domain_id,
|
custom_domain_id,
|
||||||
title,
|
entity_name,
|
||||||
description,
|
description,
|
||||||
website_url,
|
website_url,
|
||||||
email,
|
email,
|
||||||
@@ -365,7 +365,7 @@ SELECT
|
|||||||
non_disclosure_agreement_file_id,
|
non_disclosure_agreement_file_id,
|
||||||
default_domain_id,
|
default_domain_id,
|
||||||
custom_domain_id,
|
custom_domain_id,
|
||||||
title,
|
entity_name,
|
||||||
description,
|
description,
|
||||||
website_url,
|
website_url,
|
||||||
email,
|
email,
|
||||||
@@ -420,7 +420,7 @@ INSERT INTO trust_centers (
|
|||||||
non_disclosure_agreement_file_id,
|
non_disclosure_agreement_file_id,
|
||||||
default_domain_id,
|
default_domain_id,
|
||||||
custom_domain_id,
|
custom_domain_id,
|
||||||
title,
|
entity_name,
|
||||||
description,
|
description,
|
||||||
website_url,
|
website_url,
|
||||||
email,
|
email,
|
||||||
@@ -440,7 +440,7 @@ INSERT INTO trust_centers (
|
|||||||
@non_disclosure_agreement_file_id,
|
@non_disclosure_agreement_file_id,
|
||||||
@default_domain_id,
|
@default_domain_id,
|
||||||
@custom_domain_id,
|
@custom_domain_id,
|
||||||
@title,
|
@entity_name,
|
||||||
@description,
|
@description,
|
||||||
@website_url,
|
@website_url,
|
||||||
@email,
|
@email,
|
||||||
@@ -463,7 +463,7 @@ INSERT INTO trust_centers (
|
|||||||
"non_disclosure_agreement_file_id": tc.NonDisclosureAgreementFileID,
|
"non_disclosure_agreement_file_id": tc.NonDisclosureAgreementFileID,
|
||||||
"default_domain_id": tc.DefaultDomainID,
|
"default_domain_id": tc.DefaultDomainID,
|
||||||
"custom_domain_id": tc.CustomDomainID,
|
"custom_domain_id": tc.CustomDomainID,
|
||||||
"title": tc.Title,
|
"entity_name": tc.EntityName,
|
||||||
"description": tc.Description,
|
"description": tc.Description,
|
||||||
"website_url": tc.WebsiteURL,
|
"website_url": tc.WebsiteURL,
|
||||||
"email": tc.Email,
|
"email": tc.Email,
|
||||||
@@ -502,7 +502,7 @@ SET
|
|||||||
non_disclosure_agreement_file_id = @non_disclosure_agreement_file_id,
|
non_disclosure_agreement_file_id = @non_disclosure_agreement_file_id,
|
||||||
default_domain_id = @default_domain_id,
|
default_domain_id = @default_domain_id,
|
||||||
custom_domain_id = @custom_domain_id,
|
custom_domain_id = @custom_domain_id,
|
||||||
title = @title,
|
entity_name = @entity_name,
|
||||||
description = @description,
|
description = @description,
|
||||||
website_url = @website_url,
|
website_url = @website_url,
|
||||||
email = @email,
|
email = @email,
|
||||||
@@ -525,7 +525,7 @@ WHERE
|
|||||||
"non_disclosure_agreement_file_id": tc.NonDisclosureAgreementFileID,
|
"non_disclosure_agreement_file_id": tc.NonDisclosureAgreementFileID,
|
||||||
"default_domain_id": tc.DefaultDomainID,
|
"default_domain_id": tc.DefaultDomainID,
|
||||||
"custom_domain_id": tc.CustomDomainID,
|
"custom_domain_id": tc.CustomDomainID,
|
||||||
"title": tc.Title,
|
"entity_name": tc.EntityName,
|
||||||
"description": tc.Description,
|
"description": tc.Description,
|
||||||
"website_url": tc.WebsiteURL,
|
"website_url": tc.WebsiteURL,
|
||||||
"email": tc.Email,
|
"email": tc.Email,
|
||||||
|
|||||||
36
pkg/coredata/migrations/20260721T165706Z.sql
Normal file
36
pkg/coredata/migrations/20260721T165706Z.sql
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
-- Copyright (c) 2026 Probo Inc <hello@probo.com>.
|
||||||
|
--
|
||||||
|
-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
-- of this software and associated documentation files (the "Software"), to deal
|
||||||
|
-- in the Software without restriction, including without limitation the rights
|
||||||
|
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
-- copies of the Software, and to permit persons to whom the Software is
|
||||||
|
-- furnished to do so, subject to the following conditions:
|
||||||
|
--
|
||||||
|
-- The above copyright notice and this permission notice shall be included in
|
||||||
|
-- all copies or substantial portions of the Software.
|
||||||
|
--
|
||||||
|
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
-- SOFTWARE.
|
||||||
|
|
||||||
|
-- entity_name is the short name shown in the hero ("Compliance at {{name}}.")
|
||||||
|
-- and TopBar brand. Prefill from the organization so existing portals keep a
|
||||||
|
-- sensible default; customized full titles in the old title column are dropped.
|
||||||
|
ALTER TABLE trust_centers
|
||||||
|
ADD COLUMN entity_name TEXT NOT NULL DEFAULT '';
|
||||||
|
|
||||||
|
UPDATE trust_centers tc
|
||||||
|
SET entity_name = o.name
|
||||||
|
FROM organizations o
|
||||||
|
WHERE tc.organization_id = o.id;
|
||||||
|
|
||||||
|
ALTER TABLE trust_centers
|
||||||
|
ALTER COLUMN entity_name DROP DEFAULT;
|
||||||
|
|
||||||
|
ALTER TABLE trust_centers
|
||||||
|
DROP COLUMN title;
|
||||||
@@ -614,7 +614,7 @@ func (s *OrganizationService) CreateOrganization(
|
|||||||
TenantID: organization.TenantID,
|
TenantID: organization.TenantID,
|
||||||
Active: false,
|
Active: false,
|
||||||
Slug: slug.MakeWithEntropy(organization.Name),
|
Slug: slug.MakeWithEntropy(organization.Name),
|
||||||
Title: "Compliance at " + organization.Name + ".",
|
EntityName: organization.Name,
|
||||||
SearchEngineIndexing: coredata.SearchEngineIndexingNotIndexable,
|
SearchEngineIndexing: coredata.SearchEngineIndexingNotIndexable,
|
||||||
MailingListID: &mailingList.ID,
|
MailingListID: &mailingList.ID,
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ type CompliancePortal implements Node {
|
|||||||
websiteUrl: String
|
websiteUrl: String
|
||||||
email: String
|
email: String
|
||||||
headquarterAddress: String
|
headquarterAddress: String
|
||||||
title: String!
|
entityName: String!
|
||||||
|
|
||||||
nonDisclosureAgreement: NonDisclosureAgreement @goField(forceResolver: true)
|
nonDisclosureAgreement: NonDisclosureAgreement @goField(forceResolver: true)
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,8 @@ func compliancePageHeadData() HeadDataFunc {
|
|||||||
|
|
||||||
compliancePageBaseURL := complianceportal.CompliancePortalBaseURLFromContext(r.Context())
|
compliancePageBaseURL := complianceportal.CompliancePortalBaseURLFromContext(r.Context())
|
||||||
|
|
||||||
description := tc.Title
|
pageTitle := "Compliance at " + tc.EntityName + "."
|
||||||
|
description := pageTitle
|
||||||
if tc.Description != nil && *tc.Description != "" {
|
if tc.Description != nil && *tc.Description != "" {
|
||||||
description = *tc.Description
|
description = *tc.Description
|
||||||
}
|
}
|
||||||
@@ -142,7 +143,7 @@ func compliancePageHeadData() HeadDataFunc {
|
|||||||
htmlLang, canonical, hreflang := SEOFromRequest(r)
|
htmlLang, canonical, hreflang := SEOFromRequest(r)
|
||||||
|
|
||||||
headData := HeadData{
|
headData := HeadData{
|
||||||
Title: tc.Title,
|
Title: pageTitle,
|
||||||
Description: description,
|
Description: description,
|
||||||
HTMLLang: htmlLang,
|
HTMLLang: htmlLang,
|
||||||
OGURL: canonical,
|
OGURL: canonical,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func NewCompliancePortal(cp *coredata.CompliancePortal) *CompliancePortal {
|
|||||||
ID: cp.ID,
|
ID: cp.ID,
|
||||||
Active: cp.Active,
|
Active: cp.Active,
|
||||||
Slug: cp.Slug,
|
Slug: cp.Slug,
|
||||||
Title: cp.Title,
|
EntityName: cp.EntityName,
|
||||||
Description: cp.Description,
|
Description: cp.Description,
|
||||||
WebsiteURL: cp.WebsiteURL,
|
WebsiteURL: cp.WebsiteURL,
|
||||||
Email: cp.Email,
|
Email: cp.Email,
|
||||||
|
|||||||
@@ -804,7 +804,7 @@ func (r *mutationResolver) UpdateCompliancePortal(ctx context.Context, input typ
|
|||||||
WebsiteURL: gqlutils.UnwrapOmittable(input.WebsiteURL),
|
WebsiteURL: gqlutils.UnwrapOmittable(input.WebsiteURL),
|
||||||
Email: gqlutils.UnwrapOmittable(input.Email),
|
Email: gqlutils.UnwrapOmittable(input.Email),
|
||||||
HeadquarterAddress: gqlutils.UnwrapOmittable(input.HeadquarterAddress),
|
HeadquarterAddress: gqlutils.UnwrapOmittable(input.HeadquarterAddress),
|
||||||
Title: input.Title,
|
EntityName: input.EntityName,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ type CompliancePortal implements Node
|
|||||||
websiteUrl: String
|
websiteUrl: String
|
||||||
email: String
|
email: String
|
||||||
headquarterAddress: String
|
headquarterAddress: String
|
||||||
title: String!
|
entityName: String!
|
||||||
createdAt: Datetime!
|
createdAt: Datetime!
|
||||||
updatedAt: Datetime!
|
updatedAt: Datetime!
|
||||||
organization: Organization! @goField(forceResolver: true)
|
organization: Organization! @goField(forceResolver: true)
|
||||||
@@ -747,7 +747,7 @@ input UpdateCompliancePortalInput {
|
|||||||
compliancePortalId: ID!
|
compliancePortalId: ID!
|
||||||
active: Boolean
|
active: Boolean
|
||||||
searchEngineIndexing: SearchEngineIndexing
|
searchEngineIndexing: SearchEngineIndexing
|
||||||
title: String
|
entityName: String
|
||||||
description: String @goField(omittable: true)
|
description: String @goField(omittable: true)
|
||||||
websiteUrl: String @goField(omittable: true)
|
websiteUrl: String @goField(omittable: true)
|
||||||
email: String @goField(omittable: true)
|
email: String @goField(omittable: true)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ type CompliancePortal struct {
|
|||||||
WebsiteURL *string `json:"websiteUrl,omitempty"`
|
WebsiteURL *string `json:"websiteUrl,omitempty"`
|
||||||
Email *string `json:"email,omitempty"`
|
Email *string `json:"email,omitempty"`
|
||||||
HeadquarterAddress *string `json:"headquarterAddress,omitempty"`
|
HeadquarterAddress *string `json:"headquarterAddress,omitempty"`
|
||||||
Title string `json:"title"`
|
EntityName string `json:"entityName"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
Organization *Organization `json:"organization"`
|
Organization *Organization `json:"organization"`
|
||||||
@@ -67,7 +67,7 @@ func NewCompliancePortal(tc *coredata.CompliancePortal) *CompliancePortal {
|
|||||||
WebsiteURL: tc.WebsiteURL,
|
WebsiteURL: tc.WebsiteURL,
|
||||||
Email: tc.Email,
|
Email: tc.Email,
|
||||||
HeadquarterAddress: tc.HeadquarterAddress,
|
HeadquarterAddress: tc.HeadquarterAddress,
|
||||||
Title: tc.Title,
|
EntityName: tc.EntityName,
|
||||||
CreatedAt: tc.CreatedAt,
|
CreatedAt: tc.CreatedAt,
|
||||||
UpdatedAt: tc.UpdatedAt,
|
UpdatedAt: tc.UpdatedAt,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4954,8 +4954,8 @@ func (r *Resolver) UpdateCompliancePortalTool(ctx context.Context, req *mcp.Call
|
|||||||
updateReq.Email = UnwrapOmittable(input.Email)
|
updateReq.Email = UnwrapOmittable(input.Email)
|
||||||
updateReq.HeadquarterAddress = UnwrapOmittable(input.HeadquarterAddress)
|
updateReq.HeadquarterAddress = UnwrapOmittable(input.HeadquarterAddress)
|
||||||
|
|
||||||
if title := UnwrapOmittable(input.Title); title != nil {
|
if entityName := UnwrapOmittable(input.EntityName); entityName != nil {
|
||||||
updateReq.Title = *title
|
updateReq.EntityName = *entityName
|
||||||
}
|
}
|
||||||
|
|
||||||
compliancePortal, _, err := prb.Update(ctx, scope, updateReq)
|
compliancePortal, _, err := prb.Update(ctx, scope, updateReq)
|
||||||
|
|||||||
@@ -8832,7 +8832,7 @@ components:
|
|||||||
- organization_id
|
- organization_id
|
||||||
- active
|
- active
|
||||||
- search_engine_indexing
|
- search_engine_indexing
|
||||||
- title
|
- entity_name
|
||||||
- created_at
|
- created_at
|
||||||
- updated_at
|
- updated_at
|
||||||
properties:
|
properties:
|
||||||
@@ -8870,9 +8870,9 @@ components:
|
|||||||
- string
|
- string
|
||||||
- "null"
|
- "null"
|
||||||
description: Compliance page headquarter address
|
description: Compliance page headquarter address
|
||||||
title:
|
entity_name:
|
||||||
type: string
|
type: string
|
||||||
description: Public compliance page title
|
description: Entity name shown on the public compliance page
|
||||||
created_at:
|
created_at:
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
@@ -9079,11 +9079,11 @@ components:
|
|||||||
- "null"
|
- "null"
|
||||||
description: Compliance page headquarter address
|
description: Compliance page headquarter address
|
||||||
go.probo.inc/mcpgen/omittable: true
|
go.probo.inc/mcpgen/omittable: true
|
||||||
title:
|
entity_name:
|
||||||
type:
|
type:
|
||||||
- string
|
- string
|
||||||
- "null"
|
- "null"
|
||||||
description: Public compliance page title
|
description: Entity name shown on the public compliance page
|
||||||
go.probo.inc/mcpgen/omittable: true
|
go.probo.inc/mcpgen/omittable: true
|
||||||
|
|
||||||
UpdateCompliancePortalOutput:
|
UpdateCompliancePortalOutput:
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func NewCompliancePortal(tc *coredata.CompliancePortal) *CompliancePortal {
|
|||||||
OrganizationID: tc.OrganizationID,
|
OrganizationID: tc.OrganizationID,
|
||||||
Active: tc.Active,
|
Active: tc.Active,
|
||||||
SearchEngineIndexing: tc.SearchEngineIndexing,
|
SearchEngineIndexing: tc.SearchEngineIndexing,
|
||||||
Title: tc.Title,
|
EntityName: tc.EntityName,
|
||||||
Description: tc.Description,
|
Description: tc.Description,
|
||||||
WebsiteURL: tc.WebsiteURL,
|
WebsiteURL: tc.WebsiteURL,
|
||||||
Email: tc.Email,
|
Email: tc.Email,
|
||||||
|
|||||||
Reference in New Issue
Block a user