diff --git a/apps/console/src/components/FrameworkLogo.tsx b/apps/console/src/components/FrameworkLogo.tsx deleted file mode 100644 index eadd2de8f..000000000 --- a/apps/console/src/components/FrameworkLogo.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { availableFrameworks } from "@probo/helpers"; -import { Avatar } from "@probo/ui"; - -const availableLogos = new Map( - availableFrameworks.map((framework) => [framework.name, framework.logo]) -); - -export function FrameworkLogo({ name }: { name: string }) { - const logo = availableLogos.get(name); - return logo ? ( - - ) : ( - - ); -} diff --git a/apps/console/src/hooks/graph/AuditGraph.ts b/apps/console/src/hooks/graph/AuditGraph.ts index e69e4dd69..4696aa95f 100644 --- a/apps/console/src/hooks/graph/AuditGraph.ts +++ b/apps/console/src/hooks/graph/AuditGraph.ts @@ -36,6 +36,8 @@ export const auditNodeQuery = graphql` framework { id name + lightLogoURL + darkLogoURL } organization { id diff --git a/apps/console/src/hooks/graph/__generated__/AuditGraphNodeQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/AuditGraphNodeQuery.graphql.ts index 5446526d2..196fd6a35 100644 --- a/apps/console/src/hooks/graph/__generated__/AuditGraphNodeQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/AuditGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -17,7 +17,9 @@ export type AuditGraphNodeQuery$data = { readonly node: { readonly createdAt?: any; readonly framework?: { + readonly darkLogoURL: string | null | undefined; readonly id: string; + readonly lightLogoURL: string | null | undefined; readonly name: string; }; readonly id?: string; @@ -151,31 +153,47 @@ v9 = { "name": "state", "storageKey": null }, -v10 = [ - (v2/*: any*/), - (v3/*: any*/) -], -v11 = { +v10 = { "alias": null, "args": null, "concreteType": "Framework", "kind": "LinkedField", "name": "framework", "plural": false, - "selections": (v10/*: any*/), + "selections": [ + (v2/*: any*/), + (v3/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null + } + ], "storageKey": null }, -v12 = { +v11 = { "alias": null, "args": null, "concreteType": "Organization", "kind": "LinkedField", "name": "organization", "plural": false, - "selections": (v10/*: any*/), + "selections": [ + (v2/*: any*/), + (v3/*: any*/) + ], "storageKey": null }, -v13 = { +v12 = { "alias": null, "args": null, "kind": "ScalarField", @@ -207,10 +225,10 @@ return { (v7/*: any*/), (v8/*: any*/), (v9/*: any*/), + (v10/*: any*/), (v11/*: any*/), - (v12/*: any*/), (v6/*: any*/), - (v13/*: any*/) + (v12/*: any*/) ], "type": "Audit", "abstractKey": null @@ -253,10 +271,10 @@ return { (v7/*: any*/), (v8/*: any*/), (v9/*: any*/), + (v10/*: any*/), (v11/*: any*/), - (v12/*: any*/), (v6/*: any*/), - (v13/*: any*/) + (v12/*: any*/) ], "type": "Audit", "abstractKey": null @@ -267,16 +285,16 @@ return { ] }, "params": { - "cacheID": "eede00ab53ccd396e92b7fe6c1f1c2a2", + "cacheID": "af5fde4e1522c98b908630fdf1451ae9", "id": null, "metadata": {}, "name": "AuditGraphNodeQuery", "operationKind": "query", - "text": "query AuditGraphNodeQuery(\n $auditId: ID!\n) {\n node(id: $auditId) {\n __typename\n ... on Audit {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n mimeType\n size\n downloadUrl\n createdAt\n }\n reportUrl\n state\n framework {\n id\n name\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" + "text": "query AuditGraphNodeQuery(\n $auditId: ID!\n) {\n node(id: $auditId) {\n __typename\n ... on Audit {\n id\n name\n validFrom\n validUntil\n report {\n id\n filename\n mimeType\n size\n downloadUrl\n createdAt\n }\n reportUrl\n state\n framework {\n id\n name\n lightLogoURL\n darkLogoURL\n }\n organization {\n id\n name\n }\n createdAt\n updatedAt\n }\n id\n }\n}\n" } }; })(); -(node as any).hash = "c07896ae39a7d16b42c7ee4216dc28fa"; +(node as any).hash = "db92119c6d6f000963a0ff3d0fb74dfd"; export default node; diff --git a/apps/console/src/hooks/graph/__generated__/FrameworkGraphListQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/FrameworkGraphListQuery.graphql.ts index 0d4e9fd07..c9723c524 100644 --- a/apps/console/src/hooks/graph/__generated__/FrameworkGraphListQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/FrameworkGraphListQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<7aaf0b32e40fe8c723a28ab9590b62b5>> * @lightSyntaxTransform * @nogrep */ @@ -243,6 +243,20 @@ return { "name": "description", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null + }, (v3/*: any*/) ], "storageKey": null @@ -275,7 +289,7 @@ return { ] }, "params": { - "cacheID": "b31afd68395ae800a18885bca3abfa1c", + "cacheID": "90e970007a500be89809ac0f2a77bccd", "id": null, "metadata": { "connection": [ @@ -292,7 +306,7 @@ return { }, "name": "FrameworkGraphListQuery", "operationKind": "query", - "text": "query FrameworkGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n frameworks(first: 100) {\n edges {\n node {\n id\n ...FrameworksPageCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n}\n" + "text": "query FrameworkGraphListQuery(\n $organizationId: ID!\n) {\n organization: node(id: $organizationId) {\n __typename\n ... on Organization {\n id\n frameworks(first: 100) {\n edges {\n node {\n id\n ...FrameworksPageCardFragment\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n id\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n}\n" } }; })(); diff --git a/apps/console/src/hooks/graph/__generated__/FrameworkGraphNodeQuery.graphql.ts b/apps/console/src/hooks/graph/__generated__/FrameworkGraphNodeQuery.graphql.ts index 94d5a9d8f..d615bc172 100644 --- a/apps/console/src/hooks/graph/__generated__/FrameworkGraphNodeQuery.graphql.ts +++ b/apps/console/src/hooks/graph/__generated__/FrameworkGraphNodeQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<8901b5c750861080551542d26c2681d6>> + * @generated SignedSource<<6fcc115e1ab6df38ede8756968ae7a6a>> * @lightSyntaxTransform * @nogrep */ @@ -123,6 +123,20 @@ return { "name": "description", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null + }, { "alias": null, "args": null, @@ -228,12 +242,12 @@ return { ] }, "params": { - "cacheID": "29d6f638feb1bb633169abcfe083f5d2", + "cacheID": "68c09567aff1176075300c645f5d117d", "id": null, "metadata": {}, "name": "FrameworkGraphNodeQuery", "operationKind": "query", - "text": "query FrameworkGraphNodeQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n ... on Framework {\n id\n name\n ...FrameworkDetailPageFragment\n }\n id\n }\n}\n\nfragment FrameworkDetailPageFragment on Framework {\n id\n name\n description\n organization {\n name\n id\n }\n controls(first: 250, orderBy: {field: SECTION_TITLE, direction: ASC}) {\n edges {\n node {\n id\n sectionTitle\n name\n status\n exclusionJustification\n }\n }\n }\n}\n" + "text": "query FrameworkGraphNodeQuery(\n $frameworkId: ID!\n) {\n node(id: $frameworkId) {\n __typename\n ... on Framework {\n id\n name\n ...FrameworkDetailPageFragment\n }\n id\n }\n}\n\nfragment FrameworkDetailPageFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n organization {\n name\n id\n }\n controls(first: 250, orderBy: {field: SECTION_TITLE, direction: ASC}) {\n edges {\n node {\n id\n sectionTitle\n name\n status\n exclusionJustification\n }\n }\n }\n}\n" } }; })(); diff --git a/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx b/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx index c8d521c13..cbf47ed52 100644 --- a/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx +++ b/apps/console/src/pages/organizations/audits/AuditDetailsPage.tsx @@ -25,14 +25,24 @@ import { IconArrowInbox, useConfirm, useToast, + FrameworkLogo, } from "@probo/ui"; import { useTranslate } from "@probo/i18n"; import { useOrganizationId } from "/hooks/useOrganizationId"; -import { FrameworkLogo } from "/components/FrameworkLogo"; import { ControlledField } from "/components/form/ControlledField"; import { useFormWithSchema } from "/hooks/useFormWithSchema"; import z from "zod"; -import { getAuditStateLabel, getAuditStateVariant, auditStates, fileSize, sprintf, formatDatetime, formatError, formatDate, type GraphQLError } from "@probo/helpers"; +import { + getAuditStateLabel, + getAuditStateVariant, + auditStates, + fileSize, + sprintf, + formatDatetime, + formatError, + formatDate, + type GraphQLError, +} from "@probo/helpers"; import type { AuditGraphNodeQuery } from "/hooks/graph/__generated__/AuditGraphNodeQuery.graphql"; import { use } from "react"; import { PermissionsContext } from "/providers/PermissionsContext"; @@ -42,7 +52,13 @@ const updateAuditSchema = z.object({ name: z.string().nullable().optional(), validFrom: z.string().optional(), validUntil: z.string().optional(), - state: z.enum(["NOT_STARTED", "IN_PROGRESS", "COMPLETED", "REJECTED", "OUTDATED"]), + state: z.enum([ + "NOT_STARTED", + "IN_PROGRESS", + "COMPLETED", + "REJECTED", + "OUTDATED", + ]), }); type Props = { @@ -50,7 +66,10 @@ type Props = { }; export default function AuditDetailsPage(props: Props) { - const audit = usePreloadedQuery(auditNodeQuery, props.queryRef); + const audit = usePreloadedQuery( + auditNodeQuery, + props.queryRef + ); const auditEntry = audit.node; const { __ } = useTranslate(); const organizationId = useOrganizationId(); @@ -58,19 +77,20 @@ export default function AuditDetailsPage(props: Props) { const navigate = useNavigate(); const deleteAudit = useDeleteAudit( - { id: auditEntry.id!, framework: { name: auditEntry.framework!.name} }, + { id: auditEntry.id!, framework: { name: auditEntry.framework!.name } }, ConnectionHandler.getConnectionID(organizationId, "AuditsPage_audits"), () => navigate(`/organizations/${organizationId}/audits`) ); - const { control, formState, handleSubmit, register, reset } = useFormWithSchema(updateAuditSchema, { - defaultValues: { - name: auditEntry.name || null, - validFrom: auditEntry.validFrom?.split('T')[0] || "", - validUntil: auditEntry.validUntil?.split('T')[0] || "", - state: auditEntry.state || "NOT_STARTED", - }, - }); + const { control, formState, handleSubmit, register, reset } = + useFormWithSchema(updateAuditSchema, { + defaultValues: { + name: auditEntry.name || null, + validFrom: auditEntry.validFrom?.split("T")[0] || "", + validUntil: auditEntry.validUntil?.split("T")[0] || "", + state: auditEntry.state || "NOT_STARTED", + }, + }); const updateAudit = useUpdateAudit(); const [uploadAuditReport, isUploading] = useUploadAuditReport(); @@ -98,7 +118,10 @@ export default function AuditDetailsPage(props: Props) { } catch (error) { toast({ title: __("Error"), - description: formatError(__("Failed to update audit"), error as GraphQLError), + description: formatError( + __("Failed to update audit"), + error as GraphQLError + ), variant: "error", }); } @@ -131,7 +154,9 @@ export default function AuditDetailsPage(props: Props) { to: `/organizations/${organizationId}/audits`, }, { - label: (auditEntry.name || auditEntry.framework?.name) ?? __("Unknown Audit"), + label: + (auditEntry.name || auditEntry.framework?.name) ?? + __("Unknown Audit"), }, ]} /> @@ -139,10 +164,16 @@ export default function AuditDetailsPage(props: Props) {
- +
{auditEntry.framework?.name}
- + {getAuditStateLabel(__, auditEntry.state || "NOT_STARTED")}
@@ -187,12 +218,10 @@ export default function AuditDetailsPage(props: Props) {
- {formState.isDirty && ( - isAuthorized("Audit", "updateAudit") && ( - - ) + {formState.isDirty && isAuthorized("Audit", "updateAudit") && ( + )}
@@ -201,7 +230,7 @@ export default function AuditDetailsPage(props: Props) {

{__("Audit Report")}

- {auditEntry.report ? ( + {auditEntry.report ? (
@@ -211,11 +240,10 @@ export default function AuditDetailsPage(props: Props) { {auditEntry.report.filename}

+ {fileSize(__, auditEntry.report.size)} - {fileSize(__, auditEntry.report.size)} - - - {__("Uploaded")} {formatDate(auditEntry.report.createdAt)} + {__("Uploaded")}{" "} + {formatDate(auditEntry.report.createdAt)}
@@ -224,7 +252,7 @@ export default function AuditDetailsPage(props: Props) { { if (auditEntry.report?.downloadUrl) { - window.open(auditEntry.report.downloadUrl, '_blank'); + window.open(auditEntry.report.downloadUrl, "_blank"); } }} icon={IconArrowInbox} @@ -244,10 +272,14 @@ export default function AuditDetailsPage(props: Props) { ) : (

- {__("Upload the final audit report document (PDF recommended)")} + {__( + "Upload the final audit report document (PDF recommended)" + )}

{ if (files.length > 0 && auditEntry.id) { diff --git a/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx b/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx index 60b8ce097..3c3828c01 100644 --- a/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx +++ b/apps/console/src/pages/organizations/frameworks/FrameworkDetailPage.tsx @@ -10,12 +10,12 @@ import { Button, ControlItem, DropdownItem, + FrameworkLogo, IconPencil, IconPlusLarge, IconTrashCan, PageHeader, } from "@probo/ui"; -import { FrameworkLogo } from "/components/FrameworkLogo"; import { connectionListKey, frameworkNodeQuery, @@ -39,6 +39,8 @@ const frameworkDetailFragment = graphql` id name description + lightLogoURL + darkLogoURL organization { name } @@ -70,12 +72,8 @@ const generateFrameworkStateOfApplicabilityMutation = graphql` `; const exportFrameworkMutation = graphql` - mutation FrameworkDetailPageExportFrameworkMutation( - $frameworkId: ID! - ) { - exportFramework( - input: { frameworkId: $frameworkId } - ) { + mutation FrameworkDetailPageExportFrameworkMutation($frameworkId: ID!) { + exportFramework(input: { frameworkId: $frameworkId }) { exportJobId } } @@ -120,7 +118,8 @@ export default function FrameworkDetailPage(props: Props) { exportFrameworkMutation, { errorMessage: "Failed to export framework", - successMessage: "Framework export started successfully. You will receive an email when the export is ready.", + successMessage: + "Framework export started successfully. You will receive an email when the export is ready.", } ); @@ -193,7 +192,11 @@ export default function FrameworkDetailPage(props: Props) { {__("Export Framework")} {isAuthorized("Framework", "deleteFramework") && ( - + {__("Delete")} )} diff --git a/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx b/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx index cd2298104..3a4292939 100644 --- a/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx +++ b/apps/console/src/pages/organizations/frameworks/FrameworksPage.tsx @@ -5,6 +5,7 @@ import { Card, DropdownItem, FileButton, + FrameworkLogo, FrameworkSelector, IconFolderUpload, IconPencil, @@ -27,7 +28,6 @@ import { Link } from "react-router"; import type { FrameworksPageCardFragment$key } from "./__generated__/FrameworksPageCardFragment.graphql"; import { useMutationWithToasts } from "/hooks/useMutationWithToasts"; import { useState, type ChangeEventHandler, use } from "react"; -import { FrameworkLogo } from "/components/FrameworkLogo"; import { FrameworkFormDialog } from "./dialogs/FrameworkFormDialog"; import { PermissionsContext } from "/providers/PermissionsContext"; @@ -120,7 +120,8 @@ export default function FrameworksPage(props: Props) { const isLoading = isUploading || isImporting; - const hasAnyAction = isAuthorized("Framework", "updateFramework") || + const hasAnyAction = + isAuthorized("Framework", "updateFramework") || isAuthorized("Framework", "deleteFramework"); return ( @@ -172,6 +173,8 @@ const frameworkCardFragment = graphql` id name description + lightLogoURL + darkLogoURL } `; @@ -200,7 +203,11 @@ function FrameworkCard(props: FrameworkCardProps) { framework={framework} />
- + {props.hasAnyAction && ( {isAuthorized("Framework", "updateFramework") && ( diff --git a/apps/console/src/pages/organizations/frameworks/__generated__/FrameworkDetailPageFragment.graphql.ts b/apps/console/src/pages/organizations/frameworks/__generated__/FrameworkDetailPageFragment.graphql.ts index ccbebe2d9..de73066cc 100644 --- a/apps/console/src/pages/organizations/frameworks/__generated__/FrameworkDetailPageFragment.graphql.ts +++ b/apps/console/src/pages/organizations/frameworks/__generated__/FrameworkDetailPageFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<<1da75e11f49e841800329ded9f67a1d4>> * @lightSyntaxTransform * @nogrep */ @@ -24,8 +24,10 @@ export type FrameworkDetailPageFragment$data = { }; }>; }; + readonly darkLogoURL: string | null | undefined; readonly description: string | null | undefined; readonly id: string; + readonly lightLogoURL: string | null | undefined; readonly name: string; readonly organization: { readonly name: string; @@ -67,6 +69,20 @@ return { "name": "description", "storageKey": null }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null + }, { "alias": null, "args": null, @@ -167,6 +183,6 @@ return { }; })(); -(node as any).hash = "c31fd5c0f675d2524f736d69c4ebebe3"; +(node as any).hash = "34a82531b8812ee16e75eb035bc739e8"; export default node; diff --git a/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageCardFragment.graphql.ts b/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageCardFragment.graphql.ts index 9df986da3..5e782ccc1 100644 --- a/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageCardFragment.graphql.ts +++ b/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageCardFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<9fdc712e118402371c9951169aac320a>> + * @generated SignedSource<<412cc494e90709fca575c68f6deef112>> * @lightSyntaxTransform * @nogrep */ @@ -11,8 +11,10 @@ import { ReaderFragment } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; export type FrameworksPageCardFragment$data = { + readonly darkLogoURL: string | null | undefined; readonly description: string | null | undefined; readonly id: string; + readonly lightLogoURL: string | null | undefined; readonly name: string; readonly " $fragmentType": "FrameworksPageCardFragment"; }; @@ -47,12 +49,26 @@ const node: ReaderFragment = { "kind": "ScalarField", "name": "description", "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null } ], "type": "Framework", "abstractKey": null }; -(node as any).hash = "4481f380673963e72f88071031e37d14"; +(node as any).hash = "fe86a14971741a77f587ae015ebf0a22"; export default node; diff --git a/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageImportMutation.graphql.ts b/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageImportMutation.graphql.ts index 5546d50c5..9473b3c28 100644 --- a/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageImportMutation.graphql.ts +++ b/apps/console/src/pages/organizations/frameworks/__generated__/FrameworksPageImportMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<9436ef052ea63a9785d82ec810e810f1>> + * @generated SignedSource<<2256362d89b6b5c2f5c707acb44d283e>> * @lightSyntaxTransform * @nogrep */ @@ -158,6 +158,20 @@ return { "kind": "ScalarField", "name": "description", "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null } ], "storageKey": null @@ -187,12 +201,12 @@ return { ] }, "params": { - "cacheID": "87a38788cb2e060657b552af69acb707", + "cacheID": "5584472f1e68fac3d766662c6d5dab90", "id": null, "metadata": {}, "name": "FrameworksPageImportMutation", "operationKind": "mutation", - "text": "mutation FrameworksPageImportMutation(\n $input: ImportFrameworkInput!\n) {\n importFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n}\n" + "text": "mutation FrameworksPageImportMutation(\n $input: ImportFrameworkInput!\n) {\n importFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n}\n" } }; })(); diff --git a/apps/console/src/pages/organizations/frameworks/dialogs/__generated__/FrameworkFormDialogMutation.graphql.ts b/apps/console/src/pages/organizations/frameworks/dialogs/__generated__/FrameworkFormDialogMutation.graphql.ts index 975746b3d..4ac0f32b2 100644 --- a/apps/console/src/pages/organizations/frameworks/dialogs/__generated__/FrameworkFormDialogMutation.graphql.ts +++ b/apps/console/src/pages/organizations/frameworks/dialogs/__generated__/FrameworkFormDialogMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -159,6 +159,20 @@ return { "kind": "ScalarField", "name": "description", "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null } ], "storageKey": null @@ -188,12 +202,12 @@ return { ] }, "params": { - "cacheID": "931895b4bbb7caacd8ee0ee69de76cd6", + "cacheID": "c66177d87b59d87fdf7cbc9268af431a", "id": null, "metadata": {}, "name": "FrameworkFormDialogMutation", "operationKind": "mutation", - "text": "mutation FrameworkFormDialogMutation(\n $input: CreateFrameworkInput!\n) {\n createFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n}\n" + "text": "mutation FrameworkFormDialogMutation(\n $input: CreateFrameworkInput!\n) {\n createFramework(input: $input) {\n frameworkEdge {\n node {\n id\n ...FrameworksPageCardFragment\n }\n }\n }\n}\n\nfragment FrameworksPageCardFragment on Framework {\n id\n name\n description\n lightLogoURL\n darkLogoURL\n}\n" } }; })(); diff --git a/apps/trust/public/logos/blank.svg b/apps/trust/public/logos/blank.svg deleted file mode 100644 index ce4a70196..000000000 --- a/apps/trust/public/logos/blank.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/trust/public/logos/gdpr.svg b/apps/trust/public/logos/gdpr.svg deleted file mode 100644 index 30f46b7e6..000000000 --- a/apps/trust/public/logos/gdpr.svg +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/trust/public/logos/hipaa.svg b/apps/trust/public/logos/hipaa.svg deleted file mode 100644 index 3dfb97088..000000000 --- a/apps/trust/public/logos/hipaa.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/trust/public/logos/iso27001.svg b/apps/trust/public/logos/iso27001.svg deleted file mode 100644 index 3c1ea751b..000000000 --- a/apps/trust/public/logos/iso27001.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/trust/public/logos/soc2.svg b/apps/trust/public/logos/soc2.svg deleted file mode 100644 index 1c28c4a29..000000000 --- a/apps/trust/public/logos/soc2.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/trust/src/components/AuditRow.tsx b/apps/trust/src/components/AuditRow.tsx index 267bb30b9..6a9a67579 100644 --- a/apps/trust/src/components/AuditRow.tsx +++ b/apps/trust/src/components/AuditRow.tsx @@ -6,6 +6,7 @@ import { Button, Dialog, DialogContent, + FrameworkLogo, IconArrowInbox, IconLock, IconMedal, @@ -15,7 +16,7 @@ import { import { useTranslate } from "@probo/i18n"; import type { AuditRowDownloadMutation } from "./__generated__/AuditRowDownloadMutation.graphql"; import { useMutationWithToasts } from "/hooks/useMutationWithToast"; -import { downloadFile, getLogoUrl } from "@probo/helpers"; +import { downloadFile } from "@probo/helpers"; import { type PropsWithChildren, useState } from "react"; import { useLocation } from "react-router"; import { RequestAccessDialog } from "/components/RequestAccessDialog.tsx"; @@ -39,6 +40,8 @@ const auditRowFragment = graphql` framework { id name + lightLogoURL + darkLogoURL } } `; @@ -106,41 +109,19 @@ export function AuditRow(props: { audit: AuditRowFragment$key }) { export function AuditRowAvatar(props: { audit: AuditRowFragment$key }) { const audit = useFragment(auditRowFragment, props.audit); - const logos = { - "ISO 27001 (2022)": getLogoUrl("iso27001.svg"), - "SOC 2": getLogoUrl("soc2.svg"), - HIPAA: getLogoUrl("hipaa.svg"), - GDPR: getLogoUrl("gdpr.svg"), - }; - return ( <> - + @@ -170,13 +151,12 @@ function AuditDialog( title={} > - {props.logo && ( - {audit.framework.name} - )} +

{audit.framework.name}

diff --git a/apps/trust/src/components/OrganizationSidebar.tsx b/apps/trust/src/components/OrganizationSidebar.tsx index be4ebd9c6..ca8bfa377 100644 --- a/apps/trust/src/components/OrganizationSidebar.tsx +++ b/apps/trust/src/components/OrganizationSidebar.tsx @@ -90,7 +90,7 @@ export function OrganizationSidebar({ -
+
)} diff --git a/apps/trust/src/components/__generated__/AuditRowFragment.graphql.ts b/apps/trust/src/components/__generated__/AuditRowFragment.graphql.ts index 869cb53ed..e3ef922e2 100644 --- a/apps/trust/src/components/__generated__/AuditRowFragment.graphql.ts +++ b/apps/trust/src/components/__generated__/AuditRowFragment.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<2f595b4efd5e7b13207d433830a64c98>> + * @generated SignedSource<<3265a0991323eee4011c668b68d1b365>> * @lightSyntaxTransform * @nogrep */ @@ -12,7 +12,9 @@ import { ReaderFragment } from 'relay-runtime'; import { FragmentRefs } from "relay-runtime"; export type AuditRowFragment$data = { readonly framework: { + readonly darkLogoURL: string | null | undefined; readonly id: string; + readonly lightLogoURL: string | null | undefined; readonly name: string; }; readonly report: { @@ -90,6 +92,20 @@ return { "kind": "ScalarField", "name": "name", "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null } ], "storageKey": null @@ -100,6 +116,6 @@ return { }; })(); -(node as any).hash = "3aabed006b65dc913c81a63f0f6f4523"; +(node as any).hash = "417e65b500df4b4cff874dab2bea90ee"; export default node; diff --git a/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts b/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts index a5fa95c19..2e82a16b4 100644 --- a/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts +++ b/apps/trust/src/queries/__generated__/TrustGraphCurrentQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -533,7 +533,21 @@ return { "plural": false, "selections": [ (v0/*: any*/), - (v6/*: any*/) + (v6/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null + } ], "storageKey": null } @@ -552,12 +566,12 @@ return { ] }, "params": { - "cacheID": "da8080ccbc08adb03fbf360f1e472f84", + "cacheID": "f098177c07810cbe7609821d63c22b0b", "id": null, "metadata": {}, "name": "TrustGraphCurrentQuery", "operationKind": "query", - "text": "query TrustGraphCurrentQuery {\n currentTrustCenter {\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 countries\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n trustCenterFiles(first: 5) {\n edges {\n node {\n id\n category\n ...TrustCenterFileRowFragment\n }\n }\n }\n}\n\nfragment TrustCenterFileRowFragment on TrustCenterFile {\n id\n name\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment VendorRowFragment on Vendor {\n id\n name\n category\n websiteUrl\n privacyPolicyUrl\n countries\n}\n" + "text": "query TrustGraphCurrentQuery {\n currentTrustCenter {\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 lightLogoURL\n darkLogoURL\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 countries\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n trustCenterFiles(first: 5) {\n edges {\n node {\n id\n category\n ...TrustCenterFileRowFragment\n }\n }\n }\n}\n\nfragment TrustCenterFileRowFragment on TrustCenterFile {\n id\n name\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment VendorRowFragment on Vendor {\n id\n name\n category\n websiteUrl\n privacyPolicyUrl\n countries\n}\n" } }; })(); diff --git a/apps/trust/src/queries/__generated__/TrustGraphQuery.graphql.ts b/apps/trust/src/queries/__generated__/TrustGraphQuery.graphql.ts index 2a76a419f..964f4f2cc 100644 --- a/apps/trust/src/queries/__generated__/TrustGraphQuery.graphql.ts +++ b/apps/trust/src/queries/__generated__/TrustGraphQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<8b9ec6ee6f688ae6f6d1463104c72df4>> + * @generated SignedSource<<6458ae0015d6100916a1d446c608f61c>> * @lightSyntaxTransform * @nogrep */ @@ -549,7 +549,21 @@ return { "plural": false, "selections": [ (v2/*: any*/), - (v8/*: any*/) + (v8/*: any*/), + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "lightLogoURL", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "darkLogoURL", + "storageKey": null + } ], "storageKey": null } @@ -568,12 +582,12 @@ return { ] }, "params": { - "cacheID": "f3ac933cf00a798d12b1a8e1fedcaee9", + "cacheID": "7f7d3a2db2deb10550db16704993a2d0", "id": null, "metadata": {}, "name": "TrustGraphQuery", "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 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 countries\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n trustCenterFiles(first: 5) {\n edges {\n node {\n id\n category\n ...TrustCenterFileRowFragment\n }\n }\n }\n}\n\nfragment TrustCenterFileRowFragment on TrustCenterFile {\n id\n name\n isUserAuthorized\n hasUserRequestedAccess\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 lightLogoURL\n darkLogoURL\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 countries\n ...VendorRowFragment\n }\n }\n }\n documents(first: 5) {\n edges {\n node {\n id\n ...DocumentRowFragment\n documentType\n }\n }\n }\n trustCenterFiles(first: 5) {\n edges {\n node {\n id\n category\n ...TrustCenterFileRowFragment\n }\n }\n }\n}\n\nfragment TrustCenterFileRowFragment on TrustCenterFile {\n id\n name\n isUserAuthorized\n hasUserRequestedAccess\n}\n\nfragment VendorRowFragment on Vendor {\n id\n name\n category\n websiteUrl\n privacyPolicyUrl\n countries\n}\n" } }; })(); diff --git a/packages/helpers/src/frameworks.ts b/packages/helpers/src/frameworks.ts deleted file mode 100644 index 5d97b04a3..000000000 --- a/packages/helpers/src/frameworks.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const availableFrameworks = [ - { - id: "ISO27001-2022", - name: "ISO 27001 (2022)", - logo: "/logos/iso27001.png", - description: "Information security management systems", - }, - { - id: "SOC2", - name: "SOC 2", - logo: "/logos/soc2.png", - description: "System and Organization Controls 2", - }, - { - id: "HIPAA", - name: "HIPAA", - logo: "/logos/hipaa.png", - description: "Health Insurance Portability and Accountability Act", - }, -]; diff --git a/packages/helpers/src/index.ts b/packages/helpers/src/index.ts index 7781c4df1..c433ff048 100644 --- a/packages/helpers/src/index.ts +++ b/packages/helpers/src/index.ts @@ -24,7 +24,6 @@ export { countries, type CountryCode, } from "./countries"; -export { availableFrameworks } from "./frameworks"; export { getDocumentTypeLabel, documentTypes, @@ -63,7 +62,7 @@ export { export { promisifyMutation } from "./relay"; export { fileType, fileSize } from "./file"; export { formatDatetime, formatDate } from "./date"; -export { getLogoUrl, getTrustCenterUrl } from "./trustCenter"; +export { getTrustCenterUrl } from "./trustCenter"; export { formatError, type GraphQLError } from "./error"; export { Role, getAssignableRoles } from "./roles"; export { diff --git a/packages/helpers/src/trustCenter.ts b/packages/helpers/src/trustCenter.ts index 755a1e5dc..4ddfe7fda 100644 --- a/packages/helpers/src/trustCenter.ts +++ b/packages/helpers/src/trustCenter.ts @@ -1,15 +1,3 @@ -export function getLogoUrl(logoPath: string): string { - const path = window.location.pathname; - const trustMatch = path.match(/^\/trust\/([^/]+)/); - - if (!trustMatch) { - return `/logos/${logoPath}`; - } - - const slugOrId = trustMatch[1]; - return `/trust/${slugOrId}/logos/${logoPath}`; -} - export function getTrustCenterUrl(path: string): string { const currentPath = window.location.pathname; const trustMatch = currentPath.match(/^\/trust\/([^/]+)/); diff --git a/packages/ui/src/Atoms/FrameworkLogo/FrameworkLogo.tsx b/packages/ui/src/Atoms/FrameworkLogo/FrameworkLogo.tsx new file mode 100644 index 000000000..5b3206bdd --- /dev/null +++ b/packages/ui/src/Atoms/FrameworkLogo/FrameworkLogo.tsx @@ -0,0 +1,34 @@ +import clsx from "clsx"; +import { Avatar } from "../Avatar/Avatar"; + +interface FrameworkLogoProps { + className?: string; + darkLogoURL?: string | null; + lightLogoURL?: string | null; + name: string; +} + +export function FrameworkLogo(props: FrameworkLogoProps) { + const { className, lightLogoURL, darkLogoURL, name } = props; + + return lightLogoURL || darkLogoURL ? ( + <> + {lightLogoURL && ( + {name} + )} + {darkLogoURL && ( + + )} + + ) : ( + + ); +} diff --git a/packages/ui/src/Atoms/Frameworks/CASA.tsx b/packages/ui/src/Atoms/Frameworks/CASA.tsx index 6ee780f4e..1279d7bc3 100644 --- a/packages/ui/src/Atoms/Frameworks/CASA.tsx +++ b/packages/ui/src/Atoms/Frameworks/CASA.tsx @@ -1,6 +1,9 @@ -export function CASA() { +export function CASA(props: { className?: string }) { + const { className } = props; + return ( ; - -type Story = StoryObj; - -export const Default: Story = { - args: { - name: "SOC 2", - className: "size-12", - }, -}; diff --git a/packages/ui/src/Molecules/Badge/FrameworkLogo.tsx b/packages/ui/src/Molecules/Badge/FrameworkLogo.tsx deleted file mode 100644 index f3c7f711b..000000000 --- a/packages/ui/src/Molecules/Badge/FrameworkLogo.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { availableFrameworks } from "@probo/helpers"; -import { Avatar } from "../../Atoms/Avatar/Avatar.tsx"; - -const availableLogos = new Map( - availableFrameworks.map((framework) => [framework.name, framework.logo]), -); - -export function FrameworkLogo({ - name, - alt, - className, -}: { - name: string; - alt?: string; - className?: string; -}) { - const logo = availableLogos.get(name); - return logo ? ( - {alt} - ) : ( - - ); -} diff --git a/packages/ui/src/Molecules/FrameworkSelector/FrameworkSelector.tsx b/packages/ui/src/Molecules/FrameworkSelector/FrameworkSelector.tsx index 1bed2822b..3c260ef2a 100644 --- a/packages/ui/src/Molecules/FrameworkSelector/FrameworkSelector.tsx +++ b/packages/ui/src/Molecules/FrameworkSelector/FrameworkSelector.tsx @@ -1,8 +1,31 @@ import { Dropdown, DropdownItem } from "../../Atoms/Dropdown/Dropdown"; import { IconChevronDown, IconPlusLarge } from "../../Atoms/Icons"; import { Button } from "../../Atoms/Button/Button"; -import { availableFrameworks } from "@probo/helpers"; import { useTranslate } from "@probo/i18n"; +import { ISO27001 } from "../../Atoms/Frameworks/ISO27001"; +import { SOC2 } from "../../Atoms/Frameworks/SOC2"; +import { HIPAA } from "../../Atoms/Frameworks/HIPAA"; + +const availableFrameworks = [ + { + id: "ISO27001-2022", + name: "ISO 27001 (2022)", + logo: , + description: "Information security management systems", + }, + { + id: "SOC2", + name: "SOC 2", + logo: , + description: "System and Organization Controls 2", + }, + { + id: "HIPAA", + name: "HIPAA", + logo: , + description: "Health Insurance Portability and Accountability Act", + }, +]; type Framework = (typeof availableFrameworks)[number]; @@ -58,11 +81,7 @@ function FrameworkItem(props: { framework?: Framework; onClick: () => void }) { } return ( - {props.framework.name} + {props.framework.logo}
{props.framework.name} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index bc5ae30bc..967159602 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -10,6 +10,7 @@ export { // Atoms export * from "./Atoms/Icons"; export { Logo } from "./Atoms/Logo/Logo"; +export { FrameworkLogo } from "./Atoms/FrameworkLogo/FrameworkLogo"; export { SidebarItem } from "./Atoms/Sidebar/SidebarItem"; export { Button } from "./Atoms/Button/Button"; export { Card } from "./Atoms/Card/Card"; @@ -77,7 +78,6 @@ export { DocumentClassificationBadge } from "./Molecules/Badge/DocumentClassific export { SentitivityOptions } from "./Molecules/Select/SentitivityOptions"; export { ImpactOptions } from "./Molecules/Select/ImpactOptions"; export { DurationPicker } from "./Molecules/DurationPicker/DurationPicker"; -export { FrameworkLogo } from "./Molecules/Badge/FrameworkLogo"; export { EditableCell } from "./Molecules/Table/EditableCell"; export { TextCell } from "./Molecules/Table/TextCell"; export {