Handle document list state + API payload

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-09 18:01:40 +01:00
parent e52282e0f5
commit eab3af5f26
23 changed files with 507 additions and 239 deletions

View File

@@ -13,6 +13,7 @@
},
"dependencies": {
"@hookform/resolvers": "^5.0.1",
"@probo/coredata": "^1.0.0",
"@probo/helpers": "^1.0.0",
"@probo/hooks": "1.0.0",
"@probo/i18n": "1.0.0",

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<25b79c235754d47097b2ca28f1f3e9a0>>
* @generated SignedSource<<4d6afeeeed479773202c8516eeb63620>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -9,13 +9,18 @@
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type TrustCenterDocumentAccessStatus = "GRANTED" | "REJECTED" | "REQUESTED" | "REVOKED";
export type UpdateTrustCenterAccessInput = {
active?: boolean | null | undefined;
documentIds?: ReadonlyArray<string> | null | undefined;
documents?: ReadonlyArray<TrustCenterDocumentAccessInput> | null | undefined;
id: string;
name?: string | null | undefined;
reportIds?: ReadonlyArray<string> | null | undefined;
trustCenterFileIds?: ReadonlyArray<string> | null | undefined;
reports?: ReadonlyArray<TrustCenterDocumentAccessInput> | null | undefined;
trustCenterFiles?: ReadonlyArray<TrustCenterDocumentAccessInput> | null | undefined;
};
export type TrustCenterDocumentAccessInput = {
id: string;
status: TrustCenterDocumentAccessStatus;
};
export type TrustCenterAccessGraphUpdateMutation$variables = {
input: UpdateTrustCenterAccessInput;

View File

@@ -1,73 +1,15 @@
import {
Badge,
Button,
Checkbox,
Dialog,
DialogContent,
DialogFooter,
Field,
Spinner,
Table,
Tbody,
Td,
Th,
Thead,
Tr,
} from "@probo/ui";
import type { TrustCenterAccess, TrustCenterDocumentAccessStatus } from "@probo/coredata";
import { getTrustCenterDocumentAccessInfo, type TrustCenterDocumentAccessInfo } from "@probo/helpers";
import { Button, Checkbox, Dialog, DialogContent, DialogFooter, Field, Spinner } from "@probo/ui";
import { usePreloadedQuery, type PreloadedQuery, useQueryLoader } from "react-relay";
import type { TrustCenterAccessGraphLoadDocumentAccessesQuery } from "/hooks/graph/__generated__/TrustCenterAccessGraphLoadDocumentAccessesQuery.graphql";
import type { TrustCenterDocumentAccess } from "/coredata/TrustCenterDocumentAccess";
import { loadTrustCenterAccessDocumentAccessesQuery, updateTrustCenterAccessMutation } from "/hooks/graph/TrustCenterAccessGraph";
import { useTranslate } from "@probo/i18n";
import z from "zod";
import { useFormWithSchema } from "/hooks/useFormWithSchema";
import type { TrustCenterAccess } from "/coredata/TrustCenterAccess";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { Suspense, useEffect } from "react";
function getDocumentAccessInfo(
docAccess: TrustCenterDocumentAccess,
__: (key: string) => string
) {
if (docAccess.document) {
return {
variant: "info" as const,
name: docAccess.document?.title,
type: __("Document"),
category: docAccess.document?.documentType,
id: docAccess.document?.id,
requested: docAccess.requested,
active: docAccess.active,
status: docAccess.status,
};
}
if (docAccess.report) {
return {
variant: "success" as const,
name: docAccess.report?.filename,
type: __("Report"),
category: docAccess.report?.audit?.framework?.name,
id: docAccess.report?.id,
requested: docAccess.requested,
active: docAccess.active,
status: docAccess.status,
};
}
if (docAccess.trustCenterFile) {
return {
variant: "highlight" as const,
name: docAccess.trustCenterFile?.name,
type: __("File"),
category: docAccess.trustCenterFile?.category,
id: docAccess.trustCenterFile?.id,
requested: docAccess.requested,
active: docAccess.active,
status: docAccess.status,
};
}
throw new Error("Unknown trust center access document type");
}
import { Suspense, useCallback, useEffect, useState } from "react";
import { TrustCenterDocumentAccessList } from "./TrustCenterDocumentAccessList";
interface TrustCenterAccessEditDialogProps {
access: TrustCenterAccess;
@@ -121,7 +63,30 @@ export function TrustCenterAccessEditForm(props: TrustCenterAccessEditFormProps)
loadTrustCenterAccessDocumentAccessesQuery,
queryRef,
)
const documentAccesses: TrustCenterDocumentAccess[] = data.node.availableDocumentAccesses?.edges.map(edge => edge.node) ?? [];
const initialDocumentAccesses = (data.node.availableDocumentAccesses?.edges.map(edge => edge.node) ?? []).map(da => getTrustCenterDocumentAccessInfo(da, __))
const initialStatusByID = initialDocumentAccesses.reduce<Record<string, TrustCenterDocumentAccessStatus>>((acc, docAccess) => {
acc[docAccess.id] = docAccess.status;
return acc
}, {})
const [documentAccesses, setDocumentAccesses] = useState<TrustCenterDocumentAccessInfo[]>(initialDocumentAccesses);
const handleUpdateDocumentAccessStatus = useCallback((documentAccess: TrustCenterDocumentAccessInfo, status: TrustCenterDocumentAccessStatus) => {
setDocumentAccesses((prev) => {
const nextDocumentAccesses = [...prev];
const docAccessIndex = nextDocumentAccesses.findIndex(element => element.id === documentAccess.id)
const previousDocAccess = nextDocumentAccesses[docAccessIndex];
nextDocumentAccesses.splice(docAccessIndex, 1, { ...previousDocAccess, status });
return nextDocumentAccesses;
})
}, [])
const handleGrantAllDocumentAccess = useCallback(() => {
setDocumentAccesses((prev) => prev.map(element => ({...element, status: "GRANTED"})))
}, [])
const handleRejectOrRevokeAllDocumentAccess = useCallback(() => {
setDocumentAccesses((prev) => prev.map(element => ({...element, status: initialStatusByID[element.id] === "GRANTED" ? "REVOKED" : "REJECTED"})))
}, [initialStatusByID])
const editSchema = z.object({
name: z.string().min(1, __("Name is required")).min(2, __("Name must be at least 2 characters long")),
@@ -137,20 +102,23 @@ export function TrustCenterAccessEditForm(props: TrustCenterAccessEditFormProps)
});
const handleSubmit = editForm.handleSubmit(async (data) => {
const { documentIds, reportIds, trustCenterFileIds } = documentAccesses.reduce(
(acc, docAccess) => {
// TODO status update
if (docAccess.document?.id) {
acc.documentIds.push(docAccess.document.id);
} else if (docAccess.report?.id) {
acc.reportIds.push(docAccess.report.id);
} else if (docAccess.trustCenterFile?.id) {
acc.trustCenterFileIds.push(docAccess.trustCenterFile.id);
}
return acc;
},
{ documentIds: [] as string[], reportIds: [] as string[], trustCenterFileIds: [] as string[] }
);
const documents: {id: string, status: TrustCenterDocumentAccessStatus}[] = []
const reports: {id: string, status: TrustCenterDocumentAccessStatus}[] = []
const trustCenterFiles: {id: string, status: TrustCenterDocumentAccessStatus}[] = [];
for (const docAccess of documentAccesses) {
switch (docAccess.type) {
case "document":
documents.push({id: docAccess.id, status: docAccess.status});
break;
case "report":
reports.push({id: docAccess.id, status: docAccess.status});
break;
case "file":
trustCenterFiles.push({id: docAccess.id, status: docAccess.status});
break;
}
}
await updateTrustCenterAccess({
variables: {
@@ -158,14 +126,12 @@ export function TrustCenterAccessEditForm(props: TrustCenterAccessEditFormProps)
id: access.id,
name: data.name.trim(),
active: data.active,
documentIds,
reportIds,
trustCenterFileIds,
documents,
reports,
trustCenterFiles,
},
},
onSuccess: () => {
onSubmit();
},
onSuccess: onSubmit,
});
});
@@ -201,7 +167,13 @@ export function TrustCenterAccessEditForm(props: TrustCenterAccessEditFormProps)
</div>
</div>
<TrustCenterDocumentAccessList documentAccesses={documentAccesses} />
<TrustCenterDocumentAccessList
documentAccesses={documentAccesses}
initialStatusByID={initialStatusByID}
onGrantAll={handleGrantAllDocumentAccess}
onRejectOrRevokeAll={handleRejectOrRevokeAllDocumentAccess}
onUpdateStatus={handleUpdateDocumentAccessStatus}
/>
</DialogContent>
<DialogFooter>
@@ -213,103 +185,3 @@ export function TrustCenterAccessEditForm(props: TrustCenterAccessEditFormProps)
</form>
);
}
function TrustCenterDocumentAccessList(props: {
documentAccesses: TrustCenterDocumentAccess[];
}) {
const { documentAccesses } = props;
const { __ } = useTranslate();
const formattedDocumentAccesses: NonNullable<ReturnType<typeof getDocumentAccessInfo>>[] = documentAccesses
?.map((docAccess) => getDocumentAccessInfo(docAccess, __)) ?? [];
const showGrantCTA = formattedDocumentAccesses.some(da => da.status !== "GRANTED");
const showRejectCTA = formattedDocumentAccesses.some(da => da.status !== "REJECTED" && da.status !== "REVOKED");
return (
<div>
<div className="flex justify-between items-center mb-4">
<h4 className="font-medium text-txt-primary">
{__("Document Access Permissions")}
</h4>
{showGrantCTA &&
<Button
type="button"
variant="tertiary"
// TODO onClick
className="text-xs h-7 min-h-7"
>
{__("Grant All")}
</Button>
}
{showRejectCTA &&
<Button
type="button"
variant="danger"
// TODO onCLick
className="text-xs h-7 min-h-7"
>
{__("Reject All")}
</Button>
}
</div>
{formattedDocumentAccesses.length > 0 ? (
<div className="bg-bg-secondary rounded-lg overflow-hidden">
<Table>
<Thead>
<Tr>
<Th>{__("Name")}</Th>
<Th>{__("Type")}</Th>
<Th>{__("Category")}</Th>
<Th>
{__("Access")}
</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody>
{formattedDocumentAccesses.map((info) => {
const { variant, name, type, category, id, status } = info;
return (
<Tr key={id}>
<Td>
<div className="font-medium text-txt-primary">
{name}
</div>
</Td>
<Td>
<Badge variant={variant}>
{type}
</Badge>
</Td>
<Td>
<div className="text-txt-secondary">
{category || "-"}
</div>
</Td>
<Td>
<Badge variant="info">
{status}
</Badge>
</Td>
<Td>
<div className="flex justify-end">
{/* TODO DROPDOWN */}
</div>
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</div>
) : (
<div className="text-center text-txt-tertiary py-8">
{__("No documents available")}
</div>
)}
</div>
)
}

View File

@@ -1,5 +1,5 @@
import type { TrustCenterAccess } from "@probo/coredata";
import { Button, IconCheckmark1, IconCrossLargeX, IconPencil, IconTrashCan, Td, Tr } from "@probo/ui";
import type { TrustCenterAccess } from "/coredata/TrustCenterAccess";
import { formatDate } from "@probo/helpers";
import { use, useCallback, useState } from "react";
import { PermissionsContext } from "/providers/PermissionsContext";

View File

@@ -26,8 +26,8 @@ import {
import { useFormWithSchema } from "/hooks/useFormWithSchema";
import { useMutationWithToasts } from "/hooks/useMutationWithToasts";
import { PermissionsContext } from "/providers/PermissionsContext";
import type { TrustCenterAccess } from "/coredata/TrustCenterAccess";
import { TrustCenterAccessItem } from "./TrustCenterAccessItem";
import type { TrustCenterAccess } from "@probo/coredata";
type ContextType = {
organization: {

View File

@@ -0,0 +1,125 @@
import type { TrustCenterDocumentAccessStatus } from "@probo/coredata";
import { getTrustCenterDocumentAccessStatusBadgeVariant, type TrustCenterDocumentAccessInfo } from "@probo/helpers";
import { useTranslate } from "@probo/i18n";
import { Badge, Button, Table, Tbody, Td, Th, Thead, Tr } from "@probo/ui";
interface TrustCenterDocumentAccessListProps {
documentAccesses: TrustCenterDocumentAccessInfo[];
initialStatusByID: Record<string, TrustCenterDocumentAccessStatus>;
onGrantAll: () => void;
onRejectOrRevokeAll: () => void;
onUpdateStatus: (docAccess: TrustCenterDocumentAccessInfo, status: TrustCenterDocumentAccessStatus) => void;
}
export function TrustCenterDocumentAccessList(props: TrustCenterDocumentAccessListProps) {
const { documentAccesses, initialStatusByID, onGrantAll, onRejectOrRevokeAll, onUpdateStatus } = props;
const { __ } = useTranslate();
const showGrantCTA = documentAccesses.some(da => da.status !== "GRANTED");
const showRejectCTA = documentAccesses.some(da => da.status !== "REJECTED" && da.status !== "REVOKED");
return (
<div>
<div className="flex justify-between items-center mb-4">
<h4 className="font-medium text-txt-primary">
{__("Document Access Permissions")}
</h4>
<div className="ml-auto flex items-center gap-4">
{showGrantCTA &&
<Button
type="button"
variant="success"
onClick={onGrantAll}
className="text-xs h-7 min-h-7"
>
{__("Grant All")}
</Button>
}
{showRejectCTA &&
<Button
type="button"
variant="danger"
onClick={onRejectOrRevokeAll}
className="text-xs h-7 min-h-7"
>
{__("Reject/Revoke All")}
</Button>
}
</div>
</div>
{documentAccesses.length > 0 ? (
<div className="bg-bg-secondary rounded-lg overflow-hidden">
<Table>
<Thead>
<Tr>
<Th>{__("Name")}</Th>
<Th>{__("Type")}</Th>
<Th>{__("Category")}</Th>
<Th>
{__("Access")}
</Th>
<Th></Th>
</Tr>
</Thead>
<Tbody>
{documentAccesses.map((docAccess) => {
return (
<Tr key={docAccess.id}>
<Td>
<div className="font-medium text-txt-primary">
{docAccess.name}
</div>
</Td>
<Td>
<Badge variant={docAccess.variant}>
{docAccess.type}
</Badge>
</Td>
<Td>
<div className="text-txt-secondary">
{docAccess.category || "-"}
</div>
</Td>
<Td>
<Badge variant={getTrustCenterDocumentAccessStatusBadgeVariant(docAccess.status)}>
{docAccess.status}
</Badge>
</Td>
<Td className="flex justify-end">
{docAccess.status !== "GRANTED" &&
<Button
type="button"
variant="success"
onClick={() => onUpdateStatus(docAccess, "GRANTED")}
className="text-xs h-7 min-h-7"
>
{__("Grant")}
</Button>
}
{docAccess.status !== "REJECTED" && docAccess.status !== "REVOKED" &&
<Button
type="button"
variant="danger"
onClick={() => onUpdateStatus(docAccess, initialStatusByID[docAccess.id] === "GRANTED" ? "REVOKED" : "REJECTED")}
className="text-xs h-7 min-h-7"
>
{initialStatusByID[docAccess.id] === "GRANTED" ? __("Revoke") : __("Reject")}
</Button>
}
</Td>
</Tr>
);
})}
</Tbody>
</Table>
</div>
) : (
<div className="text-center text-txt-tertiary py-8">
{__("No documents available")}
</div>
)}
</div>
)
}

View File

@@ -28,6 +28,9 @@ export default defineConfig({
"/components": fileURLToPath(
new URL("./src/components", import.meta.url),
),
"/coredata": fileURLToPath(
new URL("./src/coredata", import.meta.url),
),
"/hooks": fileURLToPath(new URL("./src/hooks", import.meta.url)),
"/layouts": fileURLToPath(new URL("./src/layouts", import.meta.url)),
"/pages": fileURLToPath(new URL("./src/pages", import.meta.url)),

19
package-lock.json generated
View File

@@ -25,6 +25,7 @@
"version": "0.0.0",
"dependencies": {
"@hookform/resolvers": "^5.0.1",
"@probo/coredata": "^1.0.0",
"@probo/helpers": "^1.0.0",
"@probo/hooks": "1.0.0",
"@probo/i18n": "1.0.0",
@@ -2606,6 +2607,10 @@
"resolved": "apps/console",
"link": true
},
"node_modules/@probo/coredata": {
"resolved": "packages/coredata",
"link": true
},
"node_modules/@probo/emails": {
"resolved": "packages/emails",
"link": true
@@ -19295,6 +19300,17 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"packages/coredata": {
"name": "@probo/coredata",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"@probo/prettier": "1.0.0",
"prettier": "^3.5.3",
"typescript": "^5.8.3",
"vitest": "^3.1.3"
}
},
"packages/emails": {
"name": "@probo/emails",
"version": "0.1.0",
@@ -19330,6 +19346,9 @@
"name": "@probo/helpers",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@probo/coredata": "^1.0.0"
},
"devDependencies": {
"@probo/prettier": "1.0.0",
"prettier": "^3.5.3",

View File

@@ -0,0 +1,21 @@
{
"name": "@probo/coredata",
"version": "1.0.0",
"description": "",
"main": "./src/index.ts",
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"format": "prettier --write ./src"
},
"prettier": "@probo/prettier",
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@probo/prettier": "1.0.0",
"prettier": "^3.5.3",
"typescript": "^5.8.3",
"vitest": "^3.1.3"
}
}

View File

@@ -1,6 +1,15 @@
export const trustCenterDocumentAccessStatus = {
REQUESTED: "REQUESTED",
GRANTED: "GRANTED",
REJECTED: "REJECTED",
REVOKED: "REVOKED",
} as const;
export type TrustCenterDocumentAccessStatus = (typeof trustCenterDocumentAccessStatus)[keyof typeof trustCenterDocumentAccessStatus];
export type TrustCenterDocumentAccess = {
active: boolean;
status: string;
status: TrustCenterDocumentAccessStatus;
requested: boolean;
document?: {
id: string;

View File

@@ -0,0 +1,2 @@
export type { TrustCenterAccess } from "./TrustCenterAccess";
export type { TrustCenterDocumentAccess, TrustCenterDocumentAccessStatus } from "./TrustCenterDocumentAccess";

View File

@@ -0,0 +1,5 @@
{
"compilerOptions": {
"lib": ["ES2021", "dom"],
}
}

View File

@@ -17,5 +17,8 @@
"prettier": "^3.5.3",
"typescript": "^5.8.3",
"vitest": "^3.1.3"
},
"dependencies": {
"@probo/coredata": "^1.0.0"
}
}

View File

@@ -66,3 +66,8 @@ export { formatDatetime, formatDate } from "./date";
export { getLogoUrl, getTrustCenterUrl } from "./trustCenter";
export { formatError, type GraphQLError } from "./error";
export { Role, getAssignableRoles } from "./roles";
export {
getTrustCenterDocumentAccessInfo,
getTrustCenterDocumentAccessStatusBadgeVariant,
type TrustCenterDocumentAccessInfo,
} from "./trustCenterDocumentAccess";

View File

@@ -0,0 +1,92 @@
import type { TrustCenterDocumentAccess, TrustCenterDocumentAccessStatus } from "@probo/coredata";
export function getTrustCenterDocumentAccessStatusBadgeVariant(status: TrustCenterDocumentAccessStatus) {
switch (status) {
case "REQUESTED":
return "warning" as const;
case "GRANTED":
return "success" as const;
case "REJECTED":
case "REVOKED":
return "danger" as const;
}
}
export type TrustCenterDocumentAccessInfo = {
variant: "info",
name: string,
type: "document",
typeLabel: string,
category: string;
id: string;
requested: boolean;
active: boolean;
status: TrustCenterDocumentAccessStatus;
} | {
variant: "success",
name: string,
type: "report",
typeLabel: string,
category: string;
id: string;
requested: boolean;
active: boolean;
status: TrustCenterDocumentAccessStatus;
} | {
variant: "highlight",
name: string,
type: "file",
typeLabel: string,
category: string;
id: string;
requested: boolean;
active: boolean;
status: TrustCenterDocumentAccessStatus;
}
export function getTrustCenterDocumentAccessInfo(
docAccess: TrustCenterDocumentAccess,
__: (key: string) => string
): TrustCenterDocumentAccessInfo {
if (docAccess.document) {
return {
variant: "info" as const,
name: docAccess.document.title,
type: "document",
typeLabel: __("Document"),
category: docAccess.document.documentType,
id: docAccess.document.id,
requested: docAccess.requested,
active: docAccess.active,
status: docAccess.status,
};
}
if (docAccess.report) {
return {
variant: "success" as const,
name: docAccess.report.filename,
type: "report",
typeLabel: __("Report"),
category: docAccess.report.audit?.framework.name ?? "",
id: docAccess.report.id,
requested: docAccess.requested,
active: docAccess.active,
status: docAccess.status,
};
}
if (docAccess.trustCenterFile) {
return {
variant: "highlight" as const,
name: docAccess.trustCenterFile.name,
type: "file",
typeLabel: __("File"),
category: docAccess.trustCenterFile.category,
id: docAccess.trustCenterFile.id,
requested: docAccess.requested,
active: docAccess.active,
status: docAccess.status,
};
}
throw new Error("Unknown trust center access document type");
}

View File

@@ -21,6 +21,7 @@ export const button = tv({
quaternary:
"bg-highlight text-txt-primary hover:bg-highlight-hover active:bg-highlight-pressed",
danger: "bg-danger-plain text-txt-invert hover:bg-danger-hover shadow-base hover:shadow-hover active:bg-danger-pressed border border-border-danger",
success: "bg-success-plain text-txt-invert hover:text-invert hover:bg-success-hover shadow-base hover:shadow-hover active:bg-success-pressed border border-border-success",
},
disabled: {
true: "opacity-60 cursor-default",
@@ -47,7 +48,8 @@ type Props = PropsWithChildren<
| "secondary"
| "tertiary"
| "quaternary"
| "danger";
| "danger"
| "success";
to?: string;
asChild?: boolean;
} & VariantProps<typeof button>

View File

@@ -61,6 +61,7 @@
--color-subtle-hover: #0027000d;
--color-highlight-hover: #022a0213;
--color-accent-hover: #1e2c1c;
--color-success-hover: #1e2c1c;
--color-active-hover: #d7f2b0;
--color-danger-hover: #cf393f;
@@ -72,6 +73,7 @@
--color-subtle-pressed: #022a0213;
--color-highlight-pressed: #02210219;
--color-accent-pressed: #293a25;
--color-success-pressed: #293a25;
--color-active-pressed: #c9e894;
--color-danger-pressed: #c6373c;
@@ -197,6 +199,7 @@
--color-highlight: rgba(214, 251, 196, 0.06);
--color-active: rgba(239, 254, 226, 0.08);
--color-accent: #c4f042;
--color-success-plain: #c4f042;
--color-danger: rgba(254, 58, 61, 0.13);
--color-danger-plain: rgba(254, 58, 61, 0.13);
--color-danger-dark: rgba(255, 89, 95, 0.94);
@@ -225,6 +228,7 @@
--color-subtle-hover: rgba(214, 251, 196, 0.06);
--color-highlight-hover: rgba(233, 254, 223, 0.1);
--color-accent-hover: rgba(183, 255, 50, 0.82);
--color-success-hover: rgba(183, 255, 50, 0.82);
--color-active-hover: rgba(233, 254, 223, 0.1);
--color-danger-hover: rgba(254, 58, 61, 0.7);
@@ -236,6 +240,7 @@
--color-subtle-pressed: rgba(239, 254, 226, 0.08);
--color-highlight-pressed: rgba(236, 254, 229, 0.13);
--color-accent-pressed: rgba(209, 255, 70, 0.94);
--color-success-pressed: rgba(209, 255, 70, 0.94);
--color-active-pressed: rgba(236, 254, 229, 0.13);
--color-danger-pressed: rgba(254, 58, 61, 0.5);
}

View File

@@ -40,13 +40,18 @@ type (
Name string
}
UpdateTrustCenterDocumentAccessRequest struct {
ID gid.GID
Status coredata.TrustCenterDocumentAccessStatus
}
UpdateTrustCenterAccessRequest struct {
ID gid.GID
Name *string
Active *bool
DocumentIDs []gid.GID
ReportIDs []gid.GID
TrustCenterFileIDs []gid.GID
ID gid.GID
Name *string
Active *bool
DocumentAccesses []UpdateTrustCenterDocumentAccessRequest
ReportAccesses []UpdateTrustCenterDocumentAccessRequest
TrustCenterFileAccesses []UpdateTrustCenterDocumentAccessRequest
}
TrustCenterAccessData struct {
@@ -70,15 +75,15 @@ func (utcar *UpdateTrustCenterAccessRequest) Validate() error {
v.Check(utcar.ID, "id", validator.Required(), validator.GID(coredata.TrustCenterAccessEntityType))
v.Check(utcar.Name, "name", validator.SafeTextNoNewLine(TitleMaxLength))
v.CheckEach(utcar.DocumentIDs, "document_ids", func(index int, item any) {
v.Check(item, fmt.Sprintf("document_ids[%d]", index), validator.Required(), validator.GID(coredata.DocumentEntityType))
})
v.CheckEach(utcar.ReportIDs, "report_ids", func(index int, item any) {
v.Check(item, fmt.Sprintf("report_ids[%d]", index), validator.Required(), validator.GID(coredata.ReportEntityType))
})
v.CheckEach(utcar.TrustCenterFileIDs, "trust_center_file_ids", func(index int, item any) {
v.Check(item, fmt.Sprintf("trust_center_file_ids[%d]", index), validator.Required(), validator.GID(coredata.TrustCenterFileEntityType))
})
for i, docAccess := range utcar.DocumentAccesses {
v.Check(docAccess, fmt.Sprintf("documentAccesses[%d].ID", i), validator.Required(), validator.GID(coredata.DocumentEntityType))
}
for i, reportAccess := range utcar.ReportAccesses {
v.Check(reportAccess, fmt.Sprintf("reportAccesses[%d].ID", i), validator.Required(), validator.GID(coredata.ReportEntityType))
}
for i, reportAccess := range utcar.TrustCenterFileAccesses {
v.Check(reportAccess, fmt.Sprintf("trustCenterFileAccesses[%d].ID", i), validator.Required(), validator.GID(coredata.TrustCenterFileEntityType))
}
return v.Error()
}

View File

@@ -3189,13 +3189,18 @@ input CreateTrustCenterAccessInput {
active: Boolean!
}
input TrustCenterDocumentAccessInput {
id: ID!
status: TrustCenterDocumentAccessStatus!
}
input UpdateTrustCenterAccessInput {
id: ID!
name: String
active: Boolean
documentIds: [ID!]
reportIds: [ID!]
trustCenterFileIds: [ID!]
documents: [TrustCenterDocumentAccessInput!]
reports: [TrustCenterDocumentAccessInput!]
trustCenterFiles: [TrustCenterDocumentAccessInput!]
}
input DeleteTrustCenterAccessInput {

View File

@@ -9414,6 +9414,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
ec.unmarshalInputSnapshotOrder,
ec.unmarshalInputTaskOrder,
ec.unmarshalInputTrustCenterAccessOrder,
ec.unmarshalInputTrustCenterDocumentAccessInput,
ec.unmarshalInputTrustCenterDocumentAccessOrder,
ec.unmarshalInputTrustCenterFileOrder,
ec.unmarshalInputTrustCenterReferenceOrder,
@@ -12749,13 +12750,18 @@ input CreateTrustCenterAccessInput {
active: Boolean!
}
input TrustCenterDocumentAccessInput {
id: ID!
status: TrustCenterDocumentAccessStatus!
}
input UpdateTrustCenterAccessInput {
id: ID!
name: String
active: Boolean
documentIds: [ID!]
reportIds: [ID!]
trustCenterFileIds: [ID!]
documents: [TrustCenterDocumentAccessInput!]
reports: [TrustCenterDocumentAccessInput!]
trustCenterFiles: [TrustCenterDocumentAccessInput!]
}
input DeleteTrustCenterAccessInput {
@@ -61747,6 +61753,40 @@ func (ec *executionContext) unmarshalInputTrustCenterAccessOrder(ctx context.Con
return it, nil
}
func (ec *executionContext) unmarshalInputTrustCenterDocumentAccessInput(ctx context.Context, obj any) (types.TrustCenterDocumentAccessInput, error) {
var it types.TrustCenterDocumentAccessInput
asMap := map[string]any{}
for k, v := range obj.(map[string]any) {
asMap[k] = v
}
fieldsInOrder := [...]string{"id", "status"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
continue
}
switch k {
case "id":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id"))
data, err := ec.unmarshalNID2goᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
if err != nil {
return it, err
}
it.ID = data
case "status":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
data, err := ec.unmarshalNTrustCenterDocumentAccessStatus2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐTrustCenterDocumentAccessStatus(ctx, v)
if err != nil {
return it, err
}
it.Status = data
}
}
return it, nil
}
func (ec *executionContext) unmarshalInputTrustCenterDocumentAccessOrder(ctx context.Context, obj any) (types.OrderBy[coredata.TrustCenterDocumentAccessOrderField], error) {
var it types.OrderBy[coredata.TrustCenterDocumentAccessOrderField]
asMap := map[string]any{}
@@ -63291,7 +63331,7 @@ func (ec *executionContext) unmarshalInputUpdateTrustCenterAccessInput(ctx conte
asMap[k] = v
}
fieldsInOrder := [...]string{"id", "name", "active", "documentIds", "reportIds", "trustCenterFileIds"}
fieldsInOrder := [...]string{"id", "name", "active", "documents", "reports", "trustCenterFiles"}
for _, k := range fieldsInOrder {
v, ok := asMap[k]
if !ok {
@@ -63319,27 +63359,27 @@ func (ec *executionContext) unmarshalInputUpdateTrustCenterAccessInput(ctx conte
return it, err
}
it.Active = data
case "documentIds":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("documentIds"))
data, err := ec.unmarshalOID2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
case "documents":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("documents"))
data, err := ec.unmarshalOTrustCenterDocumentAccessInput2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterDocumentAccessInput(ctx, v)
if err != nil {
return it, err
}
it.DocumentIds = data
case "reportIds":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reportIds"))
data, err := ec.unmarshalOID2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
it.Documents = data
case "reports":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("reports"))
data, err := ec.unmarshalOTrustCenterDocumentAccessInput2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterDocumentAccessInput(ctx, v)
if err != nil {
return it, err
}
it.ReportIds = data
case "trustCenterFileIds":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("trustCenterFileIds"))
data, err := ec.unmarshalOID2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋgidᚐGID(ctx, v)
it.Reports = data
case "trustCenterFiles":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("trustCenterFiles"))
data, err := ec.unmarshalOTrustCenterDocumentAccessInput2ᚕgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterDocumentAccessInput(ctx, v)
if err != nil {
return it, err
}
it.TrustCenterFileIds = data
it.TrustCenterFiles = data
}
}
@@ -89828,6 +89868,11 @@ func (ec *executionContext) marshalNTrustCenterDocumentAccessEdge2ᚖgoᚗprobo
return ec._TrustCenterDocumentAccessEdge(ctx, sel, v)
}
func (ec *executionContext) unmarshalNTrustCenterDocumentAccessInput2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterDocumentAccessInput(ctx context.Context, v any) (*types.TrustCenterDocumentAccessInput, error) {
res, err := ec.unmarshalInputTrustCenterDocumentAccessInput(ctx, v)
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) unmarshalNTrustCenterDocumentAccessOrderField2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐTrustCenterDocumentAccessOrderField(ctx context.Context, v any) (coredata.TrustCenterDocumentAccessOrderField, error) {
tmp, err := graphql.UnmarshalString(v)
res := unmarshalNTrustCenterDocumentAccessOrderField2goᚗproboᚗincᚋproboᚋpkgᚋcoredataᚐTrustCenterDocumentAccessOrderField[tmp]
@@ -93382,6 +93427,24 @@ func (ec *executionContext) unmarshalOTrustCenterAccessOrder2ᚖgoᚗproboᚗinc
return &res, graphql.ErrorOnPath(ctx, err)
}
func (ec *executionContext) unmarshalOTrustCenterDocumentAccessInput2ᚕᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterDocumentAccessInputᚄ(ctx context.Context, v any) ([]*types.TrustCenterDocumentAccessInput, error) {
if v == nil {
return nil, nil
}
var vSlice []any
vSlice = graphql.CoerceList(v)
var err error
res := make([]*types.TrustCenterDocumentAccessInput, len(vSlice))
for i := range vSlice {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
res[i], err = ec.unmarshalNTrustCenterDocumentAccessInput2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐTrustCenterDocumentAccessInput(ctx, vSlice[i])
if err != nil {
return nil, err
}
}
return res, nil
}
func (ec *executionContext) unmarshalOTrustCenterDocumentAccessOrder2ᚖgoᚗproboᚗincᚋproboᚋpkgᚋserverᚋapiᚋconsoleᚋv1ᚋtypesᚐOrderBy(ctx context.Context, v any) (*types.OrderBy[coredata.TrustCenterDocumentAccessOrderField], error) {
if v == nil {
return nil, nil

View File

@@ -1807,6 +1807,11 @@ type TrustCenterDocumentAccessEdge struct {
Node *TrustCenterDocumentAccess `json:"node"`
}
type TrustCenterDocumentAccessInput struct {
ID gid.GID `json:"id"`
Status coredata.TrustCenterDocumentAccessStatus `json:"status"`
}
type TrustCenterEdge struct {
Cursor page.CursorKey `json:"cursor"`
Node *TrustCenter `json:"node"`
@@ -2140,12 +2145,12 @@ type UpdateTaskPayload struct {
}
type UpdateTrustCenterAccessInput struct {
ID gid.GID `json:"id"`
Name *string `json:"name,omitempty"`
Active *bool `json:"active,omitempty"`
DocumentIds []gid.GID `json:"documentIds,omitempty"`
ReportIds []gid.GID `json:"reportIds,omitempty"`
TrustCenterFileIds []gid.GID `json:"trustCenterFileIds,omitempty"`
ID gid.GID `json:"id"`
Name *string `json:"name,omitempty"`
Active *bool `json:"active,omitempty"`
Documents []*TrustCenterDocumentAccessInput `json:"documents,omitempty"`
Reports []*TrustCenterDocumentAccessInput `json:"reports,omitempty"`
TrustCenterFiles []*TrustCenterDocumentAccessInput `json:"trustCenterFiles,omitempty"`
}
type UpdateTrustCenterAccessPayload struct {

View File

@@ -1661,13 +1661,34 @@ func (r *mutationResolver) UpdateTrustCenterAccess(ctx context.Context, input ty
prb := r.ProboService(ctx, input.ID.TenantID())
var documentAccesses []probo.UpdateTrustCenterDocumentAccessRequest
var reportAccesses []probo.UpdateTrustCenterDocumentAccessRequest
var fileAccesses []probo.UpdateTrustCenterDocumentAccessRequest
for _, documentAccess := range documentAccesses {
documentAccesses = append(documentAccesses, probo.UpdateTrustCenterDocumentAccessRequest{
ID: documentAccess.ID,
Status: documentAccess.Status,
})
}
for _, reportAccess := range reportAccesses {
reportAccesses = append(reportAccesses, probo.UpdateTrustCenterDocumentAccessRequest{
ID: reportAccess.ID,
Status: reportAccess.Status,
})
}
for _, fileAccess := range fileAccesses {
fileAccesses = append(fileAccesses, probo.UpdateTrustCenterDocumentAccessRequest{
ID: fileAccess.ID,
Status: fileAccess.Status,
})
}
access, err := prb.TrustCenterAccesses.Update(ctx, &probo.UpdateTrustCenterAccessRequest{
ID: input.ID,
Name: input.Name,
Active: input.Active,
DocumentIDs: input.DocumentIds,
ReportIDs: input.ReportIds,
TrustCenterFileIDs: input.TrustCenterFileIds,
ID: input.ID,
Name: input.Name,
Active: input.Active,
DocumentAccesses: documentAccesses,
ReportAccesses: reportAccesses,
TrustCenterFileAccesses: fileAccesses,
})
if err != nil {
panic(fmt.Errorf("cannot update trust center access: %w", err))