Add granular permissions on document and report
Signed-off-by: Jonathan <contact@grafikart.fr>
This commit is contained in:
committed by
Sacha Al Himdani
parent
3543de0bf8
commit
2ee30efed0
@@ -6,7 +6,6 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
FrameworkLogo,
|
|
||||||
IconArrowInbox,
|
IconArrowInbox,
|
||||||
IconLock,
|
IconLock,
|
||||||
IconMedal,
|
IconMedal,
|
||||||
@@ -14,11 +13,10 @@ import {
|
|||||||
Table,
|
Table,
|
||||||
} from "@probo/ui";
|
} from "@probo/ui";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import { useIsAuthenticated } from "/hooks/useIsAuthenticated";
|
|
||||||
import type { AuditRowDownloadMutation } from "./__generated__/AuditRowDownloadMutation.graphql";
|
import type { AuditRowDownloadMutation } from "./__generated__/AuditRowDownloadMutation.graphql";
|
||||||
import { useMutationWithToasts } from "/hooks/useMutationWithToast";
|
import { useMutationWithToasts } from "/hooks/useMutationWithToast";
|
||||||
import { downloadFile } from "@probo/helpers";
|
import { downloadFile } from "@probo/helpers";
|
||||||
import type { PropsWithChildren } from "react";
|
import { type PropsWithChildren, useState } from "react";
|
||||||
import { useLocation } from "react-router";
|
import { useLocation } from "react-router";
|
||||||
import { RequestAccessDialog } from "/components/RequestAccessDialog.tsx";
|
import { RequestAccessDialog } from "/components/RequestAccessDialog.tsx";
|
||||||
|
|
||||||
@@ -35,6 +33,8 @@ const auditRowFragment = graphql`
|
|||||||
report {
|
report {
|
||||||
id
|
id
|
||||||
filename
|
filename
|
||||||
|
isUserAuthorized
|
||||||
|
hasUserRequestedAccess
|
||||||
}
|
}
|
||||||
framework {
|
framework {
|
||||||
id
|
id
|
||||||
@@ -46,7 +46,6 @@ const auditRowFragment = graphql`
|
|||||||
export function AuditRow(props: { audit: AuditRowFragment$key }) {
|
export function AuditRow(props: { audit: AuditRowFragment$key }) {
|
||||||
const audit = useFragment(auditRowFragment, props.audit);
|
const audit = useFragment(auditRowFragment, props.audit);
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const isAuthenticated = useIsAuthenticated();
|
|
||||||
const [commitDownload, downloading] =
|
const [commitDownload, downloading] =
|
||||||
useMutationWithToasts<AuditRowDownloadMutation>(downloadMutation);
|
useMutationWithToasts<AuditRowDownloadMutation>(downloadMutation);
|
||||||
const handleDownload = () => {
|
const handleDownload = () => {
|
||||||
@@ -64,14 +63,17 @@ export function AuditRow(props: { audit: AuditRowFragment$key }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [hasRequested, setHasRequested] = useState(
|
||||||
|
audit.report?.hasUserRequestedAccess,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div className="text-sm border-1 border-border-solid -mt-[1px] flex gap-3 flex-col md:flex-row md:justify-between px-6 py-3">
|
<div className="text-sm border-1 border-border-solid -mt-[1px] flex gap-3 flex-col md:flex-row md:justify-between px-6 py-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<IconMedal size={16} className="flex-none" />
|
<IconMedal size={16} className="flex-none text-txt-tertiary" />
|
||||||
{audit.framework.name}
|
{audit.framework.name}
|
||||||
</div>
|
</div>
|
||||||
{audit.report ? (
|
{audit.report && audit.report.isUserAuthorized && (
|
||||||
isAuthenticated ? (
|
|
||||||
<Button
|
<Button
|
||||||
className="w-full md:w-max"
|
className="w-full md:w-max"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@@ -81,18 +83,22 @@ export function AuditRow(props: { audit: AuditRowFragment$key }) {
|
|||||||
>
|
>
|
||||||
{__("Download")}
|
{__("Download")}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
)}
|
||||||
<RequestAccessDialog>
|
{audit.report && !audit.report.isUserAuthorized && (
|
||||||
|
<RequestAccessDialog
|
||||||
|
reportId={audit.report.id}
|
||||||
|
onSuccess={() => setHasRequested(true)}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={hasRequested}
|
||||||
className="w-full md:w-max"
|
className="w-full md:w-max"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon={IconLock}
|
icon={IconLock}
|
||||||
>
|
>
|
||||||
{__("Request access")}
|
{hasRequested ? __("Access requested") : __("Request access")}
|
||||||
</Button>
|
</Button>
|
||||||
</RequestAccessDialog>
|
</RequestAccessDialog>
|
||||||
)
|
)}
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -108,11 +114,20 @@ export function AuditRowAvatar(props: { audit: AuditRowFragment$key }) {
|
|||||||
const audit = useFragment(auditRowFragment, props.audit);
|
const audit = useFragment(auditRowFragment, props.audit);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuditDialog audit={props.audit}>
|
<AuditDialog
|
||||||
|
audit={props.audit}
|
||||||
|
logo={logos[audit.framework.name as keyof typeof logos]}
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
className="block cursor-pointer aspect-square"
|
className="block cursor-pointer aspect-square"
|
||||||
title={`Logo ${audit.framework.name}`}
|
title={`Logo ${audit.framework.name}`}
|
||||||
>
|
>
|
||||||
|
{audit.framework.name in logos ? (
|
||||||
|
<img
|
||||||
|
src={logos[audit.framework.name as keyof typeof logos]}
|
||||||
|
alt={`${audit.framework.name} Logo`}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<div
|
<div
|
||||||
className="bg-[#F0F7E2] aspect-square w-full rounded-full text-xs text-[#000] font-bold flex items-center justify-center pb-6 px-2"
|
className="bg-[#F0F7E2] aspect-square w-full rounded-full text-xs text-[#000] font-bold flex items-center justify-center pb-6 px-2"
|
||||||
style={{ background: "url(/trust/logos/blank.svg) no-repeat" }}
|
style={{ background: "url(/trust/logos/blank.svg) no-repeat" }}
|
||||||
@@ -122,28 +137,6 @@ export function AuditRowAvatar(props: { audit: AuditRowFragment$key }) {
|
|||||||
{audit.framework.name}
|
{audit.framework.name}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
|
||||||
</AuditDialog>
|
|
||||||
<AuditDialog audit={props.audit}>
|
|
||||||
<button
|
|
||||||
className="block cursor-pointer aspect-square"
|
|
||||||
title={`Logo ${audit.framework.name}`}
|
|
||||||
>
|
|
||||||
{audit.framework.name in logos ? (
|
|
||||||
<img
|
|
||||||
className="block aspect-square w-full"
|
|
||||||
width={75}
|
|
||||||
height={75}
|
|
||||||
src={logos[audit.framework.name as keyof typeof logos]}
|
|
||||||
alt={`Logo ${audit.framework.name}`}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
className="bg-[#F0F7E2] aspect-square w-full rounded-full text-xs text-[#000] font-bold flex items-center justify-center pb-4 px-2"
|
|
||||||
style={{ background: "url(/trust/logos/blank.png)" }}
|
|
||||||
>
|
|
||||||
{audit.framework.name}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</AuditDialog>
|
</AuditDialog>
|
||||||
@@ -152,7 +145,7 @@ export function AuditRowAvatar(props: { audit: AuditRowFragment$key }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function AuditDialog(
|
function AuditDialog(
|
||||||
props: PropsWithChildren<{ audit: AuditRowFragment$key }>,
|
props: PropsWithChildren<{ audit: AuditRowFragment$key; logo?: string }>,
|
||||||
) {
|
) {
|
||||||
const audit = useFragment(auditRowFragment, props.audit);
|
const audit = useFragment(auditRowFragment, props.audit);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
@@ -174,11 +167,13 @@ function AuditDialog(
|
|||||||
title={<Breadcrumb items={items} />}
|
title={<Breadcrumb items={items} />}
|
||||||
>
|
>
|
||||||
<DialogContent className="p-4 lg:p-8 space-y-6">
|
<DialogContent className="p-4 lg:p-8 space-y-6">
|
||||||
<FrameworkLogo
|
{props.logo && (
|
||||||
|
<img
|
||||||
alt={audit.framework.name}
|
alt={audit.framework.name}
|
||||||
name={audit.framework.name}
|
src={props.logo}
|
||||||
className="size-24 block mx-auto"
|
className="size-24 block mx-auto"
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
<h2 className="text-xl font-semibold mb-1">{audit.framework.name}</h2>
|
<h2 className="text-xl font-semibold mb-1">{audit.framework.name}</h2>
|
||||||
<p className="text-txt-secondary">Framework description</p>
|
<p className="text-txt-secondary">Framework description</p>
|
||||||
<Table>
|
<Table>
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import {
|
|||||||
Spinner,
|
Spinner,
|
||||||
} from "@probo/ui";
|
} from "@probo/ui";
|
||||||
import { useTranslate } from "@probo/i18n";
|
import { useTranslate } from "@probo/i18n";
|
||||||
import { useIsAuthenticated } from "/hooks/useIsAuthenticated";
|
|
||||||
import type { DocumentRowDownloadMutation } from "./__generated__/DocumentRowDownloadMutation.graphql";
|
import type { DocumentRowDownloadMutation } from "./__generated__/DocumentRowDownloadMutation.graphql";
|
||||||
import { useMutationWithToasts } from "/hooks/useMutationWithToast";
|
import { useMutationWithToasts } from "/hooks/useMutationWithToast";
|
||||||
import { downloadFile } from "@probo/helpers";
|
import { downloadFile } from "@probo/helpers";
|
||||||
import { RequestAccessDialog } from "/components/RequestAccessDialog.tsx";
|
import { RequestAccessDialog } from "/components/RequestAccessDialog.tsx";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
const downloadMutation = graphql`
|
const downloadMutation = graphql`
|
||||||
mutation DocumentRowDownloadMutation($input: ExportDocumentPDFInput!) {
|
mutation DocumentRowDownloadMutation($input: ExportDocumentPDFInput!) {
|
||||||
@@ -27,13 +27,14 @@ const documentRowFragment = graphql`
|
|||||||
fragment DocumentRowFragment on Document {
|
fragment DocumentRowFragment on Document {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
isUserAuthorized
|
||||||
|
hasUserRequestedAccess
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export function DocumentRow(props: { document: DocumentRowFragment$key }) {
|
export function DocumentRow(props: { document: DocumentRowFragment$key }) {
|
||||||
const document = useFragment(documentRowFragment, props.document);
|
const document = useFragment(documentRowFragment, props.document);
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
const isAuthenticated = useIsAuthenticated();
|
|
||||||
const [commitDownload, downloading] =
|
const [commitDownload, downloading] =
|
||||||
useMutationWithToasts<DocumentRowDownloadMutation>(downloadMutation);
|
useMutationWithToasts<DocumentRowDownloadMutation>(downloadMutation);
|
||||||
const handleDownload = () => {
|
const handleDownload = () => {
|
||||||
@@ -48,13 +49,16 @@ export function DocumentRow(props: { document: DocumentRowFragment$key }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const [hasRequested, setHasRequested] = useState(
|
||||||
|
document.hasUserRequestedAccess,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div className="text-sm border-1 border-border-solid -mt-[1px] flex gap-3 flex-col md:flex-row md:justify-between px-6 py-3">
|
<div className="text-sm border-1 border-border-solid -mt-[1px] flex gap-3 flex-col md:flex-row md:justify-between px-6 py-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<IconPageTextLine size={16} className=" flex-none" />
|
<IconPageTextLine size={16} className=" flex-none text-txt-tertiary" />
|
||||||
{document.title}
|
{document.title}
|
||||||
</div>
|
</div>
|
||||||
{isAuthenticated ? (
|
{document.isUserAuthorized ? (
|
||||||
<Button
|
<Button
|
||||||
className="w-full md:w-max"
|
className="w-full md:w-max"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
@@ -65,13 +69,17 @@ export function DocumentRow(props: { document: DocumentRowFragment$key }) {
|
|||||||
{__("Download")}
|
{__("Download")}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<RequestAccessDialog>
|
<RequestAccessDialog
|
||||||
|
documentId={document.id}
|
||||||
|
onSuccess={() => setHasRequested(true)}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
|
disabled={hasRequested}
|
||||||
className="w-full md:w-max"
|
className="w-full md:w-max"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
icon={IconLock}
|
icon={IconLock}
|
||||||
>
|
>
|
||||||
{__("Request access")}
|
{hasRequested ? __("Access requested") : __("Request access")}
|
||||||
</Button>
|
</Button>
|
||||||
</RequestAccessDialog>
|
</RequestAccessDialog>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ export function OrganizationSidebar({
|
|||||||
<hr className="my-6 -mx-6 h-[1px] bg-border-low border-none" />
|
<hr className="my-6 -mx-6 h-[1px] bg-border-low border-none" />
|
||||||
|
|
||||||
{/* Certifications */}
|
{/* Certifications */}
|
||||||
|
{trustCenter.audits.edges.length > 0 && (
|
||||||
|
<>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h2 className="text-xs text-txt-secondary flex gap-1 items-center">
|
<h2 className="text-xs text-txt-secondary flex gap-1 items-center">
|
||||||
<IconMedal size={16} />
|
<IconMedal size={16} />
|
||||||
@@ -89,6 +91,8 @@ export function OrganizationSidebar({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr className="my-6 -mx-6 h-[1px] bg-border-low border-none" />
|
<hr className="my-6 -mx-6 h-[1px] bg-border-low border-none" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
{!isAuthenticated && (
|
{!isAuthenticated && (
|
||||||
|
|||||||
@@ -15,27 +15,26 @@ import { useFormWithSchema } from "/hooks/useFormWithSchema";
|
|||||||
import { graphql } from "relay-runtime";
|
import { graphql } from "relay-runtime";
|
||||||
import { useMutationWithToasts } from "/hooks/useMutationWithToast";
|
import { useMutationWithToasts } from "/hooks/useMutationWithToast";
|
||||||
import { useTrustCenter } from "/hooks/useTrustCenter";
|
import { useTrustCenter } from "/hooks/useTrustCenter";
|
||||||
|
import { type FormEventHandler, type PropsWithChildren } from "react";
|
||||||
|
import { useIsAuthenticated } from "/hooks/useIsAuthenticated.ts";
|
||||||
|
|
||||||
type Props = {
|
type Props = PropsWithChildren<{
|
||||||
children: React.ReactNode;
|
documentId?: string;
|
||||||
};
|
reportId?: string;
|
||||||
|
onSuccess?: () => void;
|
||||||
|
}>;
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const requestAccessMutation = graphql`
|
export function RequestAccessDialog({
|
||||||
mutation RequestAccessDialogMutation($input: RequestAllAccessesInput!) {
|
children,
|
||||||
requestAllAccesses(input: $input) {
|
documentId,
|
||||||
trustCenterAccess {
|
reportId,
|
||||||
id
|
onSuccess,
|
||||||
}
|
}: Props) {
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export function RequestAccessDialog({ children }: Props) {
|
|
||||||
const trustCenter = useTrustCenter();
|
const trustCenter = useTrustCenter();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { __ } = useTranslate();
|
const { __ } = useTranslate();
|
||||||
@@ -45,32 +44,37 @@ export function RequestAccessDialog({ children }: Props) {
|
|||||||
email: "",
|
email: "",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const isAuthenticated = useIsAuthenticated();
|
||||||
const dialogRef = useDialogRef();
|
const dialogRef = useDialogRef();
|
||||||
const [commitRequestAccess, isRequestingAccess] = useMutationWithToasts(
|
const [commitMutation, isMutating] = useMutation({ documentId, reportId });
|
||||||
requestAccessMutation,
|
|
||||||
{
|
const submitCallback = (data: z.infer<typeof schema> | null) => {
|
||||||
onSuccess: () => {
|
commitMutation(data)
|
||||||
|
.then(() => {
|
||||||
|
onSuccess?.();
|
||||||
toast({
|
toast({
|
||||||
title: __("Success"),
|
title: __("Success"),
|
||||||
description: __("Access request submitted successfully"),
|
description: __("Access request submitted successfully"),
|
||||||
variant: "success",
|
variant: "success",
|
||||||
});
|
});
|
||||||
dialogRef.current?.close();
|
dialogRef.current?.close();
|
||||||
},
|
})
|
||||||
},
|
.catch((error) => {
|
||||||
);
|
console.error(error);
|
||||||
|
toast({
|
||||||
|
title: __("Error"),
|
||||||
|
description: __("Cannot request access"),
|
||||||
|
variant: "error",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onSubmit = handleSubmit((data) => {
|
const onSubmit: FormEventHandler<HTMLFormElement> = isAuthenticated
|
||||||
commitRequestAccess({
|
? (e) => {
|
||||||
variables: {
|
e.preventDefault();
|
||||||
input: {
|
submitCallback(null);
|
||||||
trustCenterId: trustCenter.id,
|
}
|
||||||
name: data.name,
|
: handleSubmit(submitCallback);
|
||||||
email: data.email,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
ref={dialogRef}
|
ref={dialogRef}
|
||||||
@@ -90,6 +94,7 @@ export function RequestAccessDialog({ children }: Props) {
|
|||||||
trustCenter.organization.name,
|
trustCenter.organization.name,
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
{!isAuthenticated && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Field
|
<Field
|
||||||
label={__("Full name")}
|
label={__("Full name")}
|
||||||
@@ -104,9 +109,10 @@ export function RequestAccessDialog({ children }: Props) {
|
|||||||
type="email"
|
type="email"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button disabled={isRequestingAccess} type="submit">
|
<Button disabled={isMutating} type="submit">
|
||||||
{__("Continue")}
|
{__("Continue")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
@@ -114,3 +120,103 @@ export function RequestAccessDialog({ children }: Props) {
|
|||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const requestAccessMutation = graphql`
|
||||||
|
mutation RequestAccessDialogMutation($input: RequestAllAccessesInput!) {
|
||||||
|
requestAllAccesses(input: $input) {
|
||||||
|
trustCenterAccess {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const requestDocumentAccessMutation = graphql`
|
||||||
|
mutation RequestAccessDialogDocumentMutation(
|
||||||
|
$input: RequestDocumentAccessInput!
|
||||||
|
) {
|
||||||
|
requestDocumentAccess(input: $input) {
|
||||||
|
trustCenterAccess {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const requestReportAccessMutation = graphql`
|
||||||
|
mutation RequestAccessDialogReportMutation(
|
||||||
|
$input: RequestReportAccessInput!
|
||||||
|
) {
|
||||||
|
requestReportAccess(input: $input) {
|
||||||
|
trustCenterAccess {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the correct mutation using the shape
|
||||||
|
*/
|
||||||
|
function useMutation({
|
||||||
|
documentId,
|
||||||
|
reportId,
|
||||||
|
}: Pick<Props, "documentId" | "reportId">): [
|
||||||
|
(data: z.infer<typeof schema> | null) => Promise<unknown>,
|
||||||
|
boolean,
|
||||||
|
] {
|
||||||
|
const trustCenter = useTrustCenter();
|
||||||
|
const [commitRequestAccess, isRequestingAccess] = useMutationWithToasts(
|
||||||
|
requestAccessMutation,
|
||||||
|
);
|
||||||
|
const [commitRequestDocumentAccess, isRequestingDocumentAccess] =
|
||||||
|
useMutationWithToasts(requestDocumentAccessMutation);
|
||||||
|
const [commitRequestReportAccess, isRequestingReportAccess] =
|
||||||
|
useMutationWithToasts(requestReportAccessMutation);
|
||||||
|
|
||||||
|
if (reportId) {
|
||||||
|
return [
|
||||||
|
(data) => {
|
||||||
|
return commitRequestReportAccess({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
trustCenterId: trustCenter.id,
|
||||||
|
reportId: reportId,
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isRequestingReportAccess,
|
||||||
|
];
|
||||||
|
} else if (documentId) {
|
||||||
|
return [
|
||||||
|
(data) => {
|
||||||
|
return commitRequestDocumentAccess({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
trustCenterId: trustCenter.id,
|
||||||
|
documentId: documentId,
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isRequestingDocumentAccess,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
(data) => {
|
||||||
|
return commitRequestAccess({
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
trustCenterId: trustCenter.id,
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isRequestingAccess,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<5ad8bcd5ca3b7635248d13cef0a24edf>>
|
* @generated SignedSource<<2f595b4efd5e7b13207d433830a64c98>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -17,7 +17,9 @@ export type AuditRowFragment$data = {
|
|||||||
};
|
};
|
||||||
readonly report: {
|
readonly report: {
|
||||||
readonly filename: string;
|
readonly filename: string;
|
||||||
|
readonly hasUserRequestedAccess: boolean;
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
|
readonly isUserAuthorized: boolean;
|
||||||
} | null | undefined;
|
} | null | undefined;
|
||||||
readonly " $fragmentType": "AuditRowFragment";
|
readonly " $fragmentType": "AuditRowFragment";
|
||||||
};
|
};
|
||||||
@@ -55,6 +57,20 @@ return {
|
|||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "filename",
|
"name": "filename",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "isUserAuthorized",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasUserRequestedAccess",
|
||||||
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -84,6 +100,6 @@ return {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(node as any).hash = "255e447eb5ac9b4cb889e7a8f0463902";
|
(node as any).hash = "3aabed006b65dc913c81a63f0f6f4523";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<266bdec238fe7397f3cff10dc7da8fc6>>
|
* @generated SignedSource<<396f9d87342c909ca373f60a1e6f7ff3>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -11,7 +11,9 @@
|
|||||||
import { ReaderFragment } from 'relay-runtime';
|
import { ReaderFragment } from 'relay-runtime';
|
||||||
import { FragmentRefs } from "relay-runtime";
|
import { FragmentRefs } from "relay-runtime";
|
||||||
export type DocumentRowFragment$data = {
|
export type DocumentRowFragment$data = {
|
||||||
|
readonly hasUserRequestedAccess: boolean;
|
||||||
readonly id: string;
|
readonly id: string;
|
||||||
|
readonly isUserAuthorized: boolean;
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
readonly " $fragmentType": "DocumentRowFragment";
|
readonly " $fragmentType": "DocumentRowFragment";
|
||||||
};
|
};
|
||||||
@@ -39,12 +41,26 @@ const node: ReaderFragment = {
|
|||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "title",
|
"name": "title",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "isUserAuthorized",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasUserRequestedAccess",
|
||||||
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"type": "Document",
|
"type": "Document",
|
||||||
"abstractKey": null
|
"abstractKey": null
|
||||||
};
|
};
|
||||||
|
|
||||||
(node as any).hash = "437d68812bcc68724d2e347fea22b5e3";
|
(node as any).hash = "1b0f0b9cae621268d72b0fd0646aa672";
|
||||||
|
|
||||||
export default node;
|
export default node;
|
||||||
|
|||||||
108
apps/trust/src/components/__generated__/RequestAccessDialogDocumentMutation.graphql.ts
generated
Normal file
108
apps/trust/src/components/__generated__/RequestAccessDialogDocumentMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<446953c5eafa3b9a465d245da3bea1af>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type RequestDocumentAccessInput = {
|
||||||
|
documentId: string;
|
||||||
|
email?: string | null | undefined;
|
||||||
|
name?: string | null | undefined;
|
||||||
|
trustCenterId: string;
|
||||||
|
};
|
||||||
|
export type RequestAccessDialogDocumentMutation$variables = {
|
||||||
|
input: RequestDocumentAccessInput;
|
||||||
|
};
|
||||||
|
export type RequestAccessDialogDocumentMutation$data = {
|
||||||
|
readonly requestDocumentAccess: {
|
||||||
|
readonly trustCenterAccess: {
|
||||||
|
readonly id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RequestAccessDialogDocumentMutation = {
|
||||||
|
response: RequestAccessDialogDocumentMutation$data;
|
||||||
|
variables: RequestAccessDialogDocumentMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concreteType": "RequestAccessesPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "requestDocumentAccess",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "TrustCenterAccess",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "trustCenterAccess",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RequestAccessDialogDocumentMutation",
|
||||||
|
"selections": (v1/*: any*/),
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RequestAccessDialogDocumentMutation",
|
||||||
|
"selections": (v1/*: any*/)
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "2ed1f0d19711a9f22acdc6251dbfca8f",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RequestAccessDialogDocumentMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation RequestAccessDialogDocumentMutation(\n $input: RequestDocumentAccessInput!\n) {\n requestDocumentAccess(input: $input) {\n trustCenterAccess {\n id\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "c3ebabe2f3fac32e5035cc7acfd54799";
|
||||||
|
|
||||||
|
export default node;
|
||||||
108
apps/trust/src/components/__generated__/RequestAccessDialogReportMutation.graphql.ts
generated
Normal file
108
apps/trust/src/components/__generated__/RequestAccessDialogReportMutation.graphql.ts
generated
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* @generated SignedSource<<74bc40a8998c962930b3f0b63dc6acd9>>
|
||||||
|
* @lightSyntaxTransform
|
||||||
|
* @nogrep
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import { ConcreteRequest } from 'relay-runtime';
|
||||||
|
export type RequestReportAccessInput = {
|
||||||
|
email?: string | null | undefined;
|
||||||
|
name?: string | null | undefined;
|
||||||
|
reportId: string;
|
||||||
|
trustCenterId: string;
|
||||||
|
};
|
||||||
|
export type RequestAccessDialogReportMutation$variables = {
|
||||||
|
input: RequestReportAccessInput;
|
||||||
|
};
|
||||||
|
export type RequestAccessDialogReportMutation$data = {
|
||||||
|
readonly requestReportAccess: {
|
||||||
|
readonly trustCenterAccess: {
|
||||||
|
readonly id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export type RequestAccessDialogReportMutation = {
|
||||||
|
response: RequestAccessDialogReportMutation$data;
|
||||||
|
variables: RequestAccessDialogReportMutation$variables;
|
||||||
|
};
|
||||||
|
|
||||||
|
const node: ConcreteRequest = (function(){
|
||||||
|
var v0 = [
|
||||||
|
{
|
||||||
|
"defaultValue": null,
|
||||||
|
"kind": "LocalArgument",
|
||||||
|
"name": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
v1 = [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": [
|
||||||
|
{
|
||||||
|
"kind": "Variable",
|
||||||
|
"name": "input",
|
||||||
|
"variableName": "input"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concreteType": "RequestAccessesPayload",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "requestReportAccess",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"concreteType": "TrustCenterAccess",
|
||||||
|
"kind": "LinkedField",
|
||||||
|
"name": "trustCenterAccess",
|
||||||
|
"plural": false,
|
||||||
|
"selections": [
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "id",
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"storageKey": null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return {
|
||||||
|
"fragment": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Fragment",
|
||||||
|
"metadata": null,
|
||||||
|
"name": "RequestAccessDialogReportMutation",
|
||||||
|
"selections": (v1/*: any*/),
|
||||||
|
"type": "Mutation",
|
||||||
|
"abstractKey": null
|
||||||
|
},
|
||||||
|
"kind": "Request",
|
||||||
|
"operation": {
|
||||||
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
|
"kind": "Operation",
|
||||||
|
"name": "RequestAccessDialogReportMutation",
|
||||||
|
"selections": (v1/*: any*/)
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"cacheID": "da69c3e370244e4a9a7793b06b2abdd5",
|
||||||
|
"id": null,
|
||||||
|
"metadata": {},
|
||||||
|
"name": "RequestAccessDialogReportMutation",
|
||||||
|
"operationKind": "mutation",
|
||||||
|
"text": "mutation RequestAccessDialogReportMutation(\n $input: RequestReportAccessInput!\n) {\n requestReportAccess(input: $input) {\n trustCenterAccess {\n id\n }\n }\n}\n"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
(node as any).hash = "3ef2b6424ba751f15f91ad7f4bd28fc5";
|
||||||
|
|
||||||
|
export default node;
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import { useFragment } from "react-relay";
|
import { useFragment } from "react-relay";
|
||||||
import { graphql } from "relay-runtime";
|
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 { Link, useOutletContext } from "react-router";
|
||||||
import { groupBy, objectEntries, sprintf } from "@probo/helpers";
|
import { groupBy, objectEntries, sprintf } from "@probo/helpers";
|
||||||
import type { TrustGraphQuery$data } from "/queries/__generated__/TrustGraphQuery.graphql";
|
import type { TrustGraphQuery$data } from "/queries/__generated__/TrustGraphQuery.graphql";
|
||||||
@@ -51,26 +54,64 @@ export function OverviewPage() {
|
|||||||
trustCenter: OverviewPageFragment$key &
|
trustCenter: OverviewPageFragment$key &
|
||||||
TrustGraphQuery$data["trustCenterBySlug"];
|
TrustGraphQuery$data["trustCenterBySlug"];
|
||||||
}>();
|
}>();
|
||||||
const { __ } = useTranslate();
|
|
||||||
const fragment = useFragment(overviewFragment, trustCenter);
|
const fragment = useFragment(overviewFragment, trustCenter);
|
||||||
const documentsPerType = groupBy(
|
|
||||||
fragment.documents.edges.map((edge) => edge.node),
|
|
||||||
(node) => documentTypeLabel(node.documentType, __),
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<References
|
<References
|
||||||
references={fragment.references.edges.map((edge) => edge.node)}
|
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>
|
<h2 className="font-medium mb-1">{__("Documents")}</h2>
|
||||||
<p className="text-sm text-txt-secondary mb-4">
|
<p className="text-sm text-txt-secondary mb-4">
|
||||||
{__("Security and compliance documentation:")}
|
{__("Security and compliance documentation:")}
|
||||||
</p>
|
</p>
|
||||||
<Rows className="mb-8">
|
<Rows className="mb-8">
|
||||||
|
{audits.length > 0 && (
|
||||||
|
<>
|
||||||
<RowHeader>{__("Certifications")}</RowHeader>
|
<RowHeader>{__("Certifications")}</RowHeader>
|
||||||
{trustCenter.audits.edges.map((edge) => (
|
{audits.map((audit) => (
|
||||||
<AuditRow key={edge.node.id} audit={edge.node} />
|
<AuditRow key={audit.node.id} audit={audit.node} />
|
||||||
))}
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{objectEntries(documentsPerType).map(([label, documents]) => (
|
{objectEntries(documentsPerType).map(([label, documents]) => (
|
||||||
<Fragment key={label}>
|
<Fragment key={label}>
|
||||||
<RowHeader>{label}</RowHeader>
|
<RowHeader>{label}</RowHeader>
|
||||||
@@ -79,30 +120,43 @@ export function OverviewPage() {
|
|||||||
))}
|
))}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
<Link
|
<Link to={url} className="text-sm font-medium flex gap-2 items-center">
|
||||||
to={`/trust/${trustCenter.slug}/documents`}
|
|
||||||
className="text-sm font-medium flex gap-2 items-center"
|
|
||||||
>
|
|
||||||
{__("See all documents")}
|
{__("See all documents")}
|
||||||
<IconChevronRight size={16} />
|
<IconChevronRight size={16} />
|
||||||
</Link>
|
</Link>
|
||||||
</Rows>
|
</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>
|
<h2 className="font-medium mb-1">{__("Subprocessors")}</h2>
|
||||||
<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:"),
|
||||||
trustCenter.organization.name,
|
organizationName,
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
<Rows className="mb-8 *:py-5">
|
<Rows className="mb-8 *:py-5">
|
||||||
{fragment.vendors.edges.map((edge) => (
|
{vendors.map((vendor) => (
|
||||||
<VendorRow key={edge.node.id} vendor={edge.node} />
|
<VendorRow key={vendor.node.id} vendor={vendor.node} />
|
||||||
))}
|
))}
|
||||||
<Link
|
<Link to={url} className="text-sm font-medium flex gap-2 items-center">
|
||||||
to={`/trust/${trustCenter.slug}/subprocessors`}
|
|
||||||
className="text-sm font-medium flex gap-2 items-center"
|
|
||||||
>
|
|
||||||
{__("See all subprocessors")}
|
{__("See all subprocessors")}
|
||||||
<IconChevronRight size={16} />
|
<IconChevronRight size={16} />
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<55d256287ee091b57754d2d76080ad25>>
|
* @generated SignedSource<<f592abfc32b9882d40bdfd0d91908ea2>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -214,6 +214,20 @@ return {
|
|||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "title",
|
"name": "title",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "isUserAuthorized",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasUserRequestedAccess",
|
||||||
|
"storageKey": null
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
@@ -230,12 +244,12 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "71e1dc4102d19cdd2fb8d0ff60a391ca",
|
"cacheID": "8a333723782b24714393e89240704cf2",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "TrustGraphDocumentsQuery",
|
"name": "TrustGraphDocumentsQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query TrustGraphDocumentsQuery(\n $slug: String!\n) {\n trustCenterBySlug(slug: $slug) {\n id\n organization {\n name\n id\n }\n documents(first: 50) {\n edges {\n node {\n id\n documentType\n ...DocumentRowFragment\n }\n }\n }\n }\n}\n\nfragment DocumentRowFragment on Document {\n id\n title\n}\n"
|
"text": "query TrustGraphDocumentsQuery(\n $slug: String!\n) {\n trustCenterBySlug(slug: $slug) {\n id\n organization {\n name\n id\n }\n documents(first: 50) {\n edges {\n node {\n id\n documentType\n ...DocumentRowFragment\n }\n }\n }\n }\n}\n\nfragment DocumentRowFragment on Document {\n id\n title\n isUserAuthorized\n hasUserRequestedAccess\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @generated SignedSource<<25d09fc2d93d9fbbcde08bd8a8d48214>>
|
* @generated SignedSource<<a763db35fb72256cc3905206fc18e60b>>
|
||||||
* @lightSyntaxTransform
|
* @lightSyntaxTransform
|
||||||
* @nogrep
|
* @nogrep
|
||||||
*/
|
*/
|
||||||
@@ -150,7 +150,21 @@ v14 = [
|
|||||||
"name": "first",
|
"name": "first",
|
||||||
"value": 50
|
"value": 50
|
||||||
}
|
}
|
||||||
];
|
],
|
||||||
|
v15 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "isUserAuthorized",
|
||||||
|
"storageKey": null
|
||||||
|
},
|
||||||
|
v16 = {
|
||||||
|
"alias": null,
|
||||||
|
"args": null,
|
||||||
|
"kind": "ScalarField",
|
||||||
|
"name": "hasUserRequestedAccess",
|
||||||
|
"storageKey": null
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
"fragment": {
|
"fragment": {
|
||||||
"argumentDefinitions": (v0/*: any*/),
|
"argumentDefinitions": (v0/*: any*/),
|
||||||
@@ -422,6 +436,8 @@ return {
|
|||||||
"name": "title",
|
"name": "title",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
|
(v15/*: any*/),
|
||||||
|
(v16/*: any*/),
|
||||||
{
|
{
|
||||||
"alias": null,
|
"alias": null,
|
||||||
"args": null,
|
"args": null,
|
||||||
@@ -478,7 +494,9 @@ return {
|
|||||||
"kind": "ScalarField",
|
"kind": "ScalarField",
|
||||||
"name": "filename",
|
"name": "filename",
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
}
|
},
|
||||||
|
(v15/*: any*/),
|
||||||
|
(v16/*: any*/)
|
||||||
],
|
],
|
||||||
"storageKey": null
|
"storageKey": null
|
||||||
},
|
},
|
||||||
@@ -510,12 +528,12 @@ return {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"params": {
|
"params": {
|
||||||
"cacheID": "3303b20452c558a107492263e7fc0c61",
|
"cacheID": "512205bc2cccff46b097cabaab4ec338",
|
||||||
"id": null,
|
"id": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"name": "TrustGraphQuery",
|
"name": "TrustGraphQuery",
|
||||||
"operationKind": "query",
|
"operationKind": "query",
|
||||||
"text": "query TrustGraphQuery(\n $slug: String!\n) {\n trustCenterBySlug(slug: $slug) {\n id\n slug\n isUserAuthenticated\n hasAcceptedNonDisclosureAgreement\n ndaFileName\n ndaFileUrl\n organization {\n name\n description\n websiteUrl\n logoUrl\n email\n headquarterAddress\n id\n }\n ...OverviewPageFragment\n audits(first: 50) {\n edges {\n node {\n id\n ...AuditRowFragment\n }\n }\n }\n }\n}\n\nfragment AuditRowFragment on Audit {\n report {\n id\n filename\n }\n framework {\n id\n name\n }\n}\n\nfragment DocumentRowFragment on Document {\n id\n title\n}\n\nfragment OverviewPageFragment on TrustCenter {\n references(first: 14) {\n edges {\n node {\n id\n name\n logoUrl\n websiteUrl\n }\n }\n }\n vendors(first: 3) {\n edges {\n node {\n id\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n}\n\nfragment VendorRowFragment on Vendor {\n id\n name\n category\n websiteUrl\n privacyPolicyUrl\n countries\n}\n"
|
"text": "query TrustGraphQuery(\n $slug: String!\n) {\n trustCenterBySlug(slug: $slug) {\n id\n slug\n isUserAuthenticated\n hasAcceptedNonDisclosureAgreement\n ndaFileName\n ndaFileUrl\n organization {\n name\n description\n websiteUrl\n logoUrl\n email\n headquarterAddress\n id\n }\n ...OverviewPageFragment\n audits(first: 50) {\n edges {\n node {\n id\n ...AuditRowFragment\n }\n }\n }\n }\n}\n\nfragment AuditRowFragment on Audit {\n report {\n id\n filename\n isUserAuthorized\n hasUserRequestedAccess\n }\n framework {\n id\n name\n }\n}\n\nfragment DocumentRowFragment on Document {\n id\n title\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment OverviewPageFragment on TrustCenter {\n references(first: 14) {\n edges {\n node {\n id\n name\n logoUrl\n websiteUrl\n }\n }\n }\n vendors(first: 3) {\n edges {\n node {\n id\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n}\n\nfragment VendorRowFragment on Vendor {\n id\n name\n category\n websiteUrl\n privacyPolicyUrl\n countries\n}\n"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user