Add trust center configuration

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2025-07-24 21:11:46 +02:00
parent e85a7b4955
commit 32c47a1988
49 changed files with 4755 additions and 126 deletions

View File

@@ -0,0 +1,175 @@
import { graphql } from "relay-runtime";
import {
Card,
Button,
Tr,
Td,
Table,
Thead,
Tbody,
Th,
IconChevronDown,
IconCheckmark1,
IconCrossLargeX,
Badge,
} from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import { useFragment } from "react-relay";
import { useMemo, useState } from "react";
import { sprintf, getAuditStateVariant, getAuditStateLabel } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId";
import clsx from "clsx";
import type { TrustCenterAuditsCardFragment$key } from "./__generated__/TrustCenterAuditsCardFragment.graphql";
const trustCenterAuditFragment = graphql`
fragment TrustCenterAuditsCardFragment on Audit {
id
framework {
name
}
validFrom
validUntil
state
showOnTrustCenter
createdAt
}
`;
type Mutation<Params> = (p: {
variables: {
input: {
id: string;
showOnTrustCenter: boolean;
} & Params;
};
}) => void;
type Props<Params> = {
audits: TrustCenterAuditsCardFragment$key[];
params: Params;
disabled?: boolean;
onToggleVisibility: Mutation<Params>;
variant?: "card" | "table";
};
export function TrustCenterAuditsCard<Params>(props: Props<Params>) {
const { __ } = useTranslate();
const [limit, setLimit] = useState<number | null>(4);
const audits = useMemo(() => {
return limit ? props.audits.slice(0, limit) : props.audits;
}, [props.audits, limit]);
const showMoreButton = limit !== null && props.audits.length > limit;
const variant = props.variant ?? "table";
const onToggleVisibility = (auditId: string, showOnTrustCenter: boolean) => {
props.onToggleVisibility({
variables: {
input: {
id: auditId,
showOnTrustCenter,
...props.params,
},
},
});
};
const Wrapper = variant === "card" ? Card : "div";
return (
<Wrapper {...(variant === "card" ? { padded: true } : {})} className="space-y-[10px]">
<Table className={clsx(variant === "card" && "bg-invert")}>
<Thead>
<Tr>
<Th>{__("Framework")}</Th>
<Th>{__("Valid Until")}</Th>
<Th>{__("State")}</Th>
<Th>{__("Visibility")}</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody>
{audits.length === 0 && (
<Tr>
<Td colSpan={5} className="text-center text-txt-secondary">
{__("No audits available")}
</Td>
</Tr>
)}
{audits.map((audit, index) => (
<AuditRow
key={index}
audit={audit}
onToggleVisibility={onToggleVisibility}
disabled={props.disabled}
/>
))}
</Tbody>
</Table>
{showMoreButton && (
<Button
variant="tertiary"
onClick={() => setLimit(null)}
className="mt-3 mx-auto"
icon={IconChevronDown}
>
{sprintf(__("Show %s more"), props.audits.length - limit)}
</Button>
)}
</Wrapper>
);
}
function AuditRow(props: {
audit: TrustCenterAuditsCardFragment$key;
onToggleVisibility: (auditId: string, showOnTrustCenter: boolean) => void;
disabled?: boolean;
}) {
const audit = useFragment(trustCenterAuditFragment, props.audit);
const organizationId = useOrganizationId();
const { __ } = useTranslate();
const validUntilFormatted = audit.validUntil
? new Date(audit.validUntil).toLocaleDateString()
: __("No expiry");
return (
<Tr to={`/organizations/${organizationId}/audits/${audit.id}`}>
<Td>
<div className="flex gap-4 items-center">
{audit.framework.name}
</div>
</Td>
<Td>{validUntilFormatted}</Td>
<Td>
<Badge variant={getAuditStateVariant(audit.state)}>
{getAuditStateLabel(__, audit.state)}
</Badge>
</Td>
<Td>
<div className="flex items-center gap-2">
{audit.showOnTrustCenter ? (
<>
<IconCheckmark1 className="w-4 h-4 text-txt-primary" />
<span className="text-txt-primary">{__("Visible")}</span>
</>
) : (
<>
<IconCrossLargeX className="w-4 h-4 text-txt-tertiary" />
<span className="text-txt-tertiary">{__("Hidden")}</span>
</>
)}
</div>
</Td>
<Td noLink width={100} className="text-end">
<Button
variant="secondary"
onClick={() => props.onToggleVisibility(audit.id, !audit.showOnTrustCenter)}
icon={audit.showOnTrustCenter ? IconCrossLargeX : IconCheckmark1}
disabled={props.disabled}
>
{audit.showOnTrustCenter ? __("Hide") : __("Show")}
</Button>
</Td>
</Tr>
);
}

View File

@@ -0,0 +1,99 @@
import { useTranslate } from "@probo/i18n";
import {
Dialog,
DialogContent,
DialogFooter,
Button,
useDialogRef,
} from "@probo/ui";
import { type ReactNode } from "react";
import { useFragment, graphql } from "react-relay";
import type { TrustCenterDocumentsCardFragment$key } from "./__generated__/TrustCenterDocumentsCardFragment.graphql";
const trustCenterDocumentDialogFragment = graphql`
fragment TrustCenterDocumentDialogFragment on Document {
id
title
showOnTrustCenter
}
`;
type Props = {
children: ReactNode;
documents: (TrustCenterDocumentsCardFragment$key & { id: string })[];
onToggleVisibility: (documentId: string, showOnTrustCenter: boolean) => void;
disabled?: boolean;
};
export default function TrustCenterDocumentDialog({
children,
documents,
onToggleVisibility,
disabled,
}: Props) {
const { __ } = useTranslate();
const dialogRef = useDialogRef();
return (
<>
<span onClick={() => !disabled && dialogRef.current?.open()}>
{children}
</span>
<Dialog ref={dialogRef}>
<DialogContent>
<div className="text-lg font-semibold mb-4">
{__("Manage Document Visibility on Trust Center")}
</div>
<div className="py-4">
<p className="text-txt-secondary mb-4">
{__("Control which documents are visible on your public trust center.")}
</p>
<div className="space-y-2 max-h-96 overflow-y-auto">
{documents.map((documentKey) => (
<DocumentDialogRow
key={documentKey.id}
document={documentKey}
onToggleVisibility={onToggleVisibility}
disabled={disabled}
/>
))}
</div>
</div>
<DialogFooter>
<Button onClick={() => dialogRef.current?.close()}>
{__("Close")}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
}
function DocumentDialogRow({
document: documentKey,
onToggleVisibility,
disabled,
}: {
document: TrustCenterDocumentsCardFragment$key & { id: string };
onToggleVisibility: (documentId: string, showOnTrustCenter: boolean) => void;
disabled?: boolean;
}) {
const document = useFragment(trustCenterDocumentDialogFragment, documentKey);
const { __ } = useTranslate();
return (
<div className="flex items-center justify-between p-3 border border-border-solid rounded">
<div className="flex-1">
<div className="font-medium">{document.title}</div>
</div>
<Button
variant="secondary"
onClick={() => onToggleVisibility(document.id, !document.showOnTrustCenter)}
disabled={disabled}
>
{document.showOnTrustCenter ? __("Hide") : __("Show")}
</Button>
</div>
);
}

View File

@@ -0,0 +1,177 @@
import { graphql } from "relay-runtime";
import {
Card,
Button,
Tr,
Td,
Table,
Thead,
Tbody,
Th,
IconChevronDown,
IconCheckmark1,
IconCrossLargeX,
DocumentVersionBadge,
DocumentTypeBadge,
} from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import type { TrustCenterDocumentsCardFragment$key } from "./__generated__/TrustCenterDocumentsCardFragment.graphql";
import { useFragment } from "react-relay";
import { useMemo, useState } from "react";
import { sprintf } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId";
import clsx from "clsx";
const trustCenterDocumentFragment = graphql`
fragment TrustCenterDocumentsCardFragment on Document {
id
title
createdAt
documentType
showOnTrustCenter
versions(first: 1) {
edges {
node {
id
status
}
}
}
}
`;
type Mutation<Params> = (p: {
variables: {
input: {
id: string;
showOnTrustCenter: boolean;
} & Params;
};
}) => void;
type Props<Params> = {
documents: TrustCenterDocumentsCardFragment$key[];
params: Params;
disabled?: boolean;
onToggleVisibility: Mutation<Params>;
variant?: "card" | "table";
};
export function TrustCenterDocumentsCard<Params>(props: Props<Params>) {
const { __ } = useTranslate();
const [limit, setLimit] = useState<number | null>(4);
const documents = useMemo(() => {
return limit ? props.documents.slice(0, limit) : props.documents;
}, [props.documents, limit]);
const showMoreButton = limit !== null && props.documents.length > limit;
const variant = props.variant ?? "table";
const onToggleVisibility = (documentId: string, showOnTrustCenter: boolean) => {
props.onToggleVisibility({
variables: {
input: {
id: documentId,
showOnTrustCenter,
...props.params,
},
},
});
};
const Wrapper = variant === "card" ? Card : "div";
return (
<Wrapper padded className="space-y-[10px]">
<Table className={clsx(variant === "card" && "bg-invert")}>
<Thead>
<Tr>
<Th>{__("Name")}</Th>
<Th>{__("Type")}</Th>
<Th>{__("State")}</Th>
<Th>{__("Visibility")}</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody>
{documents.length === 0 && (
<Tr>
<Td colSpan={5} className="text-center text-txt-secondary">
{__("No documents available")}
</Td>
</Tr>
)}
{documents.map((document, index) => (
<DocumentRow
key={index}
document={document}
onToggleVisibility={onToggleVisibility}
disabled={props.disabled}
/>
))}
</Tbody>
</Table>
{showMoreButton && (
<Button
variant="tertiary"
onClick={() => setLimit(null)}
className="mt-3 mx-auto"
icon={IconChevronDown}
>
{sprintf(__("Show %s more"), props.documents.length - limit)}
</Button>
)}
</Wrapper>
);
}
function DocumentRow(props: {
document: TrustCenterDocumentsCardFragment$key;
onToggleVisibility: (documentId: string, showOnTrustCenter: boolean) => void;
disabled?: boolean;
}) {
const document = useFragment(trustCenterDocumentFragment, props.document);
const organizationId = useOrganizationId();
const { __ } = useTranslate();
return (
<Tr to={`/organizations/${organizationId}/documents/${document.id}`}>
<Td>
<div className="flex gap-4 items-center">
{document.title}
</div>
</Td>
<Td>
<DocumentTypeBadge type={document.documentType} />
</Td>
<Td>
<DocumentVersionBadge state={document.versions?.edges?.[0]?.node?.status} />
</Td>
<Td>
<div className="flex items-center gap-2">
{document.showOnTrustCenter ? (
<>
<IconCheckmark1 className="w-4 h-4 text-txt-primary" />
<span className="text-txt-primary">{__("Visible")}</span>
</>
) : (
<>
<IconCrossLargeX className="w-4 h-4 text-txt-tertiary" />
<span className="text-txt-tertiary">{__("Hidden")}</span>
</>
)}
</div>
</Td>
<Td noLink width={100} className="text-end">
<Button
variant="secondary"
onClick={() => props.onToggleVisibility(document.id, !document.showOnTrustCenter)}
icon={document.showOnTrustCenter ? IconCrossLargeX : IconCheckmark1}
disabled={props.disabled}
>
{document.showOnTrustCenter ? __("Hide") : __("Show")}
</Button>
</Td>
</Tr>
);
}

View File

@@ -0,0 +1,166 @@
import { graphql } from "relay-runtime";
import {
Card,
Button,
Tr,
Td,
Table,
Thead,
Tbody,
Th,
IconChevronDown,
IconCheckmark1,
IconCrossLargeX,
Badge,
} from "@probo/ui";
import { useTranslate } from "@probo/i18n";
import { useFragment } from "react-relay";
import { useMemo, useState } from "react";
import { sprintf } from "@probo/helpers";
import { useOrganizationId } from "/hooks/useOrganizationId";
import clsx from "clsx";
import type { TrustCenterVendorsCardFragment$key } from "./__generated__/TrustCenterVendorsCardFragment.graphql";
const trustCenterVendorFragment = graphql`
fragment TrustCenterVendorsCardFragment on Vendor {
id
name
category
description
showOnTrustCenter
createdAt
}
`;
type Mutation<Params> = (p: {
variables: {
input: {
id: string;
showOnTrustCenter: boolean;
} & Params;
};
}) => void;
type Props<Params> = {
vendors: TrustCenterVendorsCardFragment$key[];
params: Params;
disabled?: boolean;
onToggleVisibility: Mutation<Params>;
variant?: "card" | "table";
};
export function TrustCenterVendorsCard<Params>(props: Props<Params>) {
const { __ } = useTranslate();
const [limit, setLimit] = useState<number | null>(4);
const vendors = useMemo(() => {
return limit ? props.vendors.slice(0, limit) : props.vendors;
}, [props.vendors, limit]);
const showMoreButton = limit !== null && props.vendors.length > limit;
const variant = props.variant ?? "table";
const onToggleVisibility = (vendorId: string, showOnTrustCenter: boolean) => {
props.onToggleVisibility({
variables: {
input: {
id: vendorId,
showOnTrustCenter,
...props.params,
},
},
});
};
const Wrapper = variant === "card" ? Card : "div";
return (
<Wrapper padded className="space-y-[10px]">
<Table className={clsx(variant === "card" && "bg-invert")}>
<Thead>
<Tr>
<Th>{__("Name")}</Th>
<Th>{__("Category")}</Th>
<Th>{__("Visibility")}</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody>
{vendors.length === 0 && (
<Tr>
<Td colSpan={4} className="text-center text-txt-secondary">
{__("No vendors available")}
</Td>
</Tr>
)}
{vendors.map((vendor, index) => (
<VendorRow
key={index}
vendor={vendor}
onToggleVisibility={onToggleVisibility}
disabled={props.disabled}
/>
))}
</Tbody>
</Table>
{showMoreButton && (
<Button
variant="tertiary"
onClick={() => setLimit(null)}
className="mt-3 mx-auto"
icon={IconChevronDown}
>
{sprintf(__("Show %s more"), props.vendors.length - limit)}
</Button>
)}
</Wrapper>
);
}
function VendorRow(props: {
vendor: TrustCenterVendorsCardFragment$key;
onToggleVisibility: (vendorId: string, showOnTrustCenter: boolean) => void;
disabled?: boolean;
}) {
const vendor = useFragment(trustCenterVendorFragment, props.vendor);
const organizationId = useOrganizationId();
const { __ } = useTranslate();
return (
<Tr to={`/organizations/${organizationId}/vendors/${vendor.id}`}>
<Td>
<div className="flex gap-4 items-center">
{vendor.name}
</div>
</Td>
<Td>
<Badge variant="neutral">
{vendor.category}
</Badge>
</Td>
<Td>
<div className="flex items-center gap-2">
{vendor.showOnTrustCenter ? (
<>
<IconCheckmark1 className="w-4 h-4 text-txt-primary" />
<span className="text-txt-primary">{__("Visible")}</span>
</>
) : (
<>
<IconCrossLargeX className="w-4 h-4 text-txt-tertiary" />
<span className="text-txt-tertiary">{__("Hidden")}</span>
</>
)}
</div>
</Td>
<Td noLink width={100} className="text-end">
<Button
variant="secondary"
onClick={() => props.onToggleVisibility(vendor.id, !vendor.showOnTrustCenter)}
icon={vendor.showOnTrustCenter ? IconCrossLargeX : IconCheckmark1}
disabled={props.disabled}
>
{vendor.showOnTrustCenter ? __("Hide") : __("Show")}
</Button>
</Td>
</Tr>
);
}

View File

@@ -0,0 +1,104 @@
/**
* @generated SignedSource<<794277d17daabd92807ccfaa5a1c2dbb>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type AuditState = "COMPLETED" | "IN_PROGRESS" | "NOT_STARTED" | "OUTDATED" | "REJECTED";
import { FragmentRefs } from "relay-runtime";
export type TrustCenterAuditsCardFragment$data = {
readonly createdAt: any;
readonly framework: {
readonly name: string;
};
readonly id: string;
readonly showOnTrustCenter: boolean;
readonly state: AuditState;
readonly validFrom: any | null | undefined;
readonly validUntil: any | null | undefined;
readonly " $fragmentType": "TrustCenterAuditsCardFragment";
};
export type TrustCenterAuditsCardFragment$key = {
readonly " $data"?: TrustCenterAuditsCardFragment$data;
readonly " $fragmentSpreads": FragmentRefs<"TrustCenterAuditsCardFragment">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "TrustCenterAuditsCardFragment",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"concreteType": "Framework",
"kind": "LinkedField",
"name": "framework",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
}
],
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "validFrom",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "validUntil",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "state",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "showOnTrustCenter",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
}
],
"type": "Audit",
"abstractKey": null
};
(node as any).hash = "9c9291dffd5c057c0e70e2567a897362";
export default node;

View File

@@ -0,0 +1,58 @@
/**
* @generated SignedSource<<3ff483dcc660e6b45d676db7fc05a30e>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type TrustCenterDocumentDialogFragment$data = {
readonly id: string;
readonly showOnTrustCenter: boolean;
readonly title: string;
readonly " $fragmentType": "TrustCenterDocumentDialogFragment";
};
export type TrustCenterDocumentDialogFragment$key = {
readonly " $data"?: TrustCenterDocumentDialogFragment$data;
readonly " $fragmentSpreads": FragmentRefs<"TrustCenterDocumentDialogFragment">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "TrustCenterDocumentDialogFragment",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "title",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "showOnTrustCenter",
"storageKey": null
}
],
"type": "Document",
"abstractKey": null
};
(node as any).hash = "d886df25fdf197161a91bbc693c9fac8";
export default node;

View File

@@ -0,0 +1,134 @@
/**
* @generated SignedSource<<711a0b67f3e93814ae3297a2578373c6>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type DocumentStatus = "DRAFT" | "PUBLISHED";
export type DocumentType = "ISMS" | "OTHER" | "POLICY";
import { FragmentRefs } from "relay-runtime";
export type TrustCenterDocumentsCardFragment$data = {
readonly createdAt: any;
readonly documentType: DocumentType;
readonly id: string;
readonly showOnTrustCenter: boolean;
readonly title: string;
readonly versions: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly id: string;
readonly status: DocumentStatus;
};
}>;
};
readonly " $fragmentType": "TrustCenterDocumentsCardFragment";
};
export type TrustCenterDocumentsCardFragment$key = {
readonly " $data"?: TrustCenterDocumentsCardFragment$data;
readonly " $fragmentSpreads": FragmentRefs<"TrustCenterDocumentsCardFragment">;
};
const node: ReaderFragment = (function(){
var v0 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
};
return {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "TrustCenterDocumentsCardFragment",
"selections": [
(v0/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "title",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "documentType",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "showOnTrustCenter",
"storageKey": null
},
{
"alias": null,
"args": [
{
"kind": "Literal",
"name": "first",
"value": 1
}
],
"concreteType": "DocumentVersionConnection",
"kind": "LinkedField",
"name": "versions",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "DocumentVersionEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "DocumentVersion",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v0/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "status",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": "versions(first:1)"
}
],
"type": "Document",
"abstractKey": null
};
})();
(node as any).hash = "88d5e5e3a2d9f4b730428efcea644f25";
export default node;

View File

@@ -0,0 +1,83 @@
/**
* @generated SignedSource<<b3d65d827fc901aa002b24df72f79ee2>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ReaderFragment } from 'relay-runtime';
export type VendorCategory = "ANALYTICS" | "CLOUD_MONITORING" | "CLOUD_PROVIDER" | "COLLABORATION" | "CUSTOMER_SUPPORT" | "DATA_STORAGE_AND_PROCESSING" | "DOCUMENT_MANAGEMENT" | "EMPLOYEE_MANAGEMENT" | "ENGINEERING" | "FINANCE" | "IDENTITY_PROVIDER" | "IT" | "MARKETING" | "OFFICE_OPERATIONS" | "OTHER" | "PASSWORD_MANAGEMENT" | "PRODUCT_AND_DESIGN" | "PROFESSIONAL_SERVICES" | "RECRUITING" | "SALES" | "SECURITY" | "VERSION_CONTROL";
import { FragmentRefs } from "relay-runtime";
export type TrustCenterVendorsCardFragment$data = {
readonly category: VendorCategory;
readonly createdAt: any;
readonly description: string | null | undefined;
readonly id: string;
readonly name: string;
readonly showOnTrustCenter: boolean;
readonly " $fragmentType": "TrustCenterVendorsCardFragment";
};
export type TrustCenterVendorsCardFragment$key = {
readonly " $data"?: TrustCenterVendorsCardFragment$data;
readonly " $fragmentSpreads": FragmentRefs<"TrustCenterVendorsCardFragment">;
};
const node: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "TrustCenterVendorsCardFragment",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "name",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "category",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "description",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "showOnTrustCenter",
"storageKey": null
},
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "createdAt",
"storageKey": null
}
],
"type": "Vendor",
"abstractKey": null
};
(node as any).hash = "72b637589fd9299b5e982450fccbfd12";
export default node;