Add granular permissions on document and report

Signed-off-by: Jonathan <contact@grafikart.fr>
This commit is contained in:
Jonathan
2025-10-03 15:56:15 +02:00
committed by Sacha Al Himdani
parent 3543de0bf8
commit 2ee30efed0
11 changed files with 603 additions and 156 deletions

View File

@@ -1,6 +1,9 @@
import { useFragment } from "react-relay";
import { graphql } from "relay-runtime";
import type { OverviewPageFragment$key } from "./__generated__/OverviewPageFragment.graphql";
import type {
OverviewPageFragment$data,
OverviewPageFragment$key,
} from "./__generated__/OverviewPageFragment.graphql";
import { Link, useOutletContext } from "react-router";
import { groupBy, objectEntries, sprintf } from "@probo/helpers";
import type { TrustGraphQuery$data } from "/queries/__generated__/TrustGraphQuery.graphql";
@@ -51,26 +54,64 @@ export function OverviewPage() {
trustCenter: OverviewPageFragment$key &
TrustGraphQuery$data["trustCenterBySlug"];
}>();
const { __ } = useTranslate();
const fragment = useFragment(overviewFragment, trustCenter);
const documentsPerType = groupBy(
fragment.documents.edges.map((edge) => edge.node),
(node) => documentTypeLabel(node.documentType, __),
);
return (
<div>
<References
references={fragment.references.edges.map((edge) => edge.node)}
/>
<Documents
audits={trustCenter.audits.edges}
documents={fragment.documents.edges}
url={`/trust/${trustCenter.slug}/documents`}
/>
<Subprocessors
organizationName={trustCenter.organization.name}
vendors={fragment.vendors.edges}
url={`/trust/${trustCenter.slug}/subprocessors`}
/>
</div>
);
}
function Documents({
documents,
audits,
url,
}: {
documents: OverviewPageFragment$data["documents"]["edges"];
audits: NonNullable<
TrustGraphQuery$data["trustCenterBySlug"]
>["audits"]["edges"];
url: string;
}) {
const { __ } = useTranslate();
const documentsPerType = groupBy(
documents.map((edge) => edge.node),
(node) => documentTypeLabel(node.documentType, __),
);
const hasAudits = audits.length > 0;
const hasDocuments = hasAudits || documents.length > 0;
if (!hasDocuments) {
return null;
}
return (
<div>
<h2 className="font-medium mb-1">{__("Documents")}</h2>
<p className="text-sm text-txt-secondary mb-4">
{__("Security and compliance documentation:")}
</p>
<Rows className="mb-8">
<RowHeader>{__("Certifications")}</RowHeader>
{trustCenter.audits.edges.map((edge) => (
<AuditRow key={edge.node.id} audit={edge.node} />
))}
{audits.length > 0 && (
<>
<RowHeader>{__("Certifications")}</RowHeader>
{audits.map((audit) => (
<AuditRow key={audit.node.id} audit={audit.node} />
))}
</>
)}
{objectEntries(documentsPerType).map(([label, documents]) => (
<Fragment key={label}>
<RowHeader>{label}</RowHeader>
@@ -79,30 +120,43 @@ export function OverviewPage() {
))}
</Fragment>
))}
<Link
to={`/trust/${trustCenter.slug}/documents`}
className="text-sm font-medium flex gap-2 items-center"
>
<Link to={url} className="text-sm font-medium flex gap-2 items-center">
{__("See all documents")}
<IconChevronRight size={16} />
</Link>
</Rows>
</div>
);
}
function Subprocessors({
vendors,
url,
organizationName,
}: {
vendors: OverviewPageFragment$data["vendors"]["edges"];
url: string;
organizationName: string;
}) {
const { __ } = useTranslate();
if (vendors.length === 0) {
return null;
}
return (
<div>
<h2 className="font-medium mb-1">{__("Subprocessors")}</h2>
<p className="text-sm text-txt-secondary mb-4">
{sprintf(
__("Third-party subprocessors %s work with:"),
trustCenter.organization.name,
organizationName,
)}
</p>
<Rows className="mb-8 *:py-5">
{fragment.vendors.edges.map((edge) => (
<VendorRow key={edge.node.id} vendor={edge.node} />
{vendors.map((vendor) => (
<VendorRow key={vendor.node.id} vendor={vendor.node} />
))}
<Link
to={`/trust/${trustCenter.slug}/subprocessors`}
className="text-sm font-medium flex gap-2 items-center"
>
<Link to={url} className="text-sm font-medium flex gap-2 items-center">
{__("See all subprocessors")}
<IconChevronRight size={16} />
</Link>