diff --git a/apps/console/src/pages/organizations/compliance-page/_components/CompliancePageAliasField.tsx b/apps/console/src/pages/organizations/compliance-page/_components/CompliancePageAliasField.tsx new file mode 100644 index 000000000..a49816d47 --- /dev/null +++ b/apps/console/src/pages/organizations/compliance-page/_components/CompliancePageAliasField.tsx @@ -0,0 +1,124 @@ +// Copyright (c) 2026 Probo Inc . +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +import { useTranslate } from "@probo/i18n"; +import { Field } from "@probo/ui"; +import { useCallback, useEffect, useState } from "react"; +import { graphql } from "relay-runtime"; + +import { useMutationWithToasts } from "#/hooks/useMutationWithToasts"; + +const setTrustCenterAliasMutation = graphql` + mutation CompliancePageAliasField_setTrustCenterAliasMutation( + $input: SetTrustCenterAliasInput! + ) { + setTrustCenterAlias(input: $input) { + alias { + resourceId + alias + } + } + } +`; + +const removeTrustCenterAliasMutation = graphql` + mutation CompliancePageAliasField_removeTrustCenterAliasMutation( + $input: RemoveTrustCenterAliasInput! + ) { + removeTrustCenterAlias(input: $input) { + deletedResourceId + } + } +`; + +export function CompliancePageAliasField(props: { + resourceId: string; + alias: string | null | undefined; + canSetAlias: boolean; + canRemoveAlias: boolean; +}) { + const { resourceId, alias, canSetAlias, canRemoveAlias } = props; + + const { __ } = useTranslate(); + const [value, setValue] = useState(alias ?? ""); + + useEffect(() => { + setValue(alias ?? ""); + }, [alias]); + + const [setTrustCenterAlias, isSettingAlias] = useMutationWithToasts( + setTrustCenterAliasMutation, + { + successMessage: __("Alias updated successfully."), + errorMessage: __("Failed to update alias"), + }, + ); + const [removeTrustCenterAlias, isRemovingAlias] = useMutationWithToasts( + removeTrustCenterAliasMutation, + { + successMessage: __("Alias removed successfully."), + errorMessage: __("Failed to remove alias"), + }, + ); + + const handleBlur = useCallback(async () => { + const trimmed = value.trim(); + const current = alias ?? ""; + + if (trimmed === current) { + return; + } + + if (trimmed === "") { + if (current !== "" && canRemoveAlias) { + await removeTrustCenterAlias({ + variables: { + input: { + resourceId, + }, + }, + }); + } + + return; + } + + if (!canSetAlias) { + return; + } + + await setTrustCenterAlias({ + variables: { + input: { + resourceId, + alias: trimmed, + }, + }, + }); + }, [alias, canRemoveAlias, canSetAlias, removeTrustCenterAlias, resourceId, setTrustCenterAlias, value]); + + const canEdit = canSetAlias || (canRemoveAlias && (alias ?? "") !== ""); + + return ( + setValue(event.target.value)} + onBlur={() => void handleBlur()} + disabled={!canEdit || isSettingAlias || isRemovingAlias} + placeholder={__("e.g. privacy-policy")} + className="min-w-[160px]" + /> + ); +} diff --git a/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditList.tsx b/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditList.tsx index 7029c6baa..8e7319463 100644 --- a/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditList.tsx +++ b/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditList.tsx @@ -53,6 +53,7 @@ export function CompliancePageAuditList(props: { fragmentRef: CompliancePageAudi {__("Name")} {__("Valid Until")} {__("State")} + {__("Alias")} {__("Visibility")} diff --git a/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditListItem.tsx b/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditListItem.tsx index 09104141e..a86d52318 100644 --- a/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditListItem.tsx +++ b/apps/console/src/pages/organizations/compliance-page/audits/_components/CompliancePageAuditListItem.tsx @@ -25,6 +25,8 @@ import type { CompliancePageAuditListItem_updateAuditVisibilityMutation } from " import { useMutationWithToasts } from "#/hooks/useMutationWithToasts"; import { useOrganizationId } from "#/hooks/useOrganizationId"; +import { CompliancePageAliasField } from "../../_components/CompliancePageAliasField"; + const compliancePageFragment = graphql` fragment CompliancePageAuditListItem_compliancePageFragment on TrustCenter { canUpdate: permission(action: "core:trust-center:update") @@ -35,6 +37,9 @@ const auditFragment = graphql` fragment CompliancePageAuditListItem_auditFragment on Audit { id name + alias + canSetAlias: permission(action: "core:trust-center-alias:set") + canRemoveAlias: permission(action: "core:trust-center-alias:remove") framework { name } @@ -111,6 +116,14 @@ export function CompliancePageAuditListItem(props: { {getAuditStateLabel(__, audit.state)} + + + {__("Name")} {__("Type")} + {__("Alias")} {__("Visibility")} {publishedDocuments.length === 0 && ( - + {__("No documents available")} diff --git a/apps/console/src/pages/organizations/compliance-page/documents/_components/CompliancePageDocumentListItem.tsx b/apps/console/src/pages/organizations/compliance-page/documents/_components/CompliancePageDocumentListItem.tsx index 98bcf6761..f869172b7 100644 --- a/apps/console/src/pages/organizations/compliance-page/documents/_components/CompliancePageDocumentListItem.tsx +++ b/apps/console/src/pages/organizations/compliance-page/documents/_components/CompliancePageDocumentListItem.tsx @@ -24,6 +24,8 @@ import type { CompliancePageDocumentListItem_documentFragment$key } from "#/__ge import { useMutationWithToasts } from "#/hooks/useMutationWithToasts"; import { useOrganizationId } from "#/hooks/useOrganizationId"; +import { CompliancePageAliasField } from "../../_components/CompliancePageAliasField"; + const compliancePageFragment = graphql` fragment CompliancePageDocumentListItem_compliancePageFragment on TrustCenter { canUpdate: permission(action: "core:trust-center:update") @@ -33,6 +35,9 @@ const compliancePageFragment = graphql` const documentFragment = graphql` fragment CompliancePageDocumentListItem_documentFragment on Document { id + alias + canSetAlias: permission(action: "core:trust-center-alias:set") + canRemoveAlias: permission(action: "core:trust-center-alias:remove") trustCenterVisibility latestPublishedVersion: versions( first: 1 @@ -113,6 +118,14 @@ export function CompliancePageDocumentListItem(props: { {latestVersion && } + + + {__("Name")} {__("Category")} {__("Upload Date")} + {__("Alias")} {__("Visibility")} @@ -81,7 +82,7 @@ export function CompliancePageFileList(props: { fragmentRef: CompliancePageFileL {files.edges.length === 0 && ( - + {__("No files available")} diff --git a/apps/console/src/pages/organizations/compliance-page/files/_components/CompliancePageFileListItem.tsx b/apps/console/src/pages/organizations/compliance-page/files/_components/CompliancePageFileListItem.tsx index 40438e76e..411576cd2 100644 --- a/apps/console/src/pages/organizations/compliance-page/files/_components/CompliancePageFileListItem.tsx +++ b/apps/console/src/pages/organizations/compliance-page/files/_components/CompliancePageFileListItem.tsx @@ -24,6 +24,8 @@ import type { CompliancePageFileListItem_fileFragment$data, CompliancePageFileLi import type { CompliancePageFileListItemMutation } from "#/__generated__/core/CompliancePageFileListItemMutation.graphql"; import { useMutationWithToasts } from "#/hooks/useMutationWithToasts"; +import { CompliancePageAliasField } from "../../_components/CompliancePageAliasField"; + const compliancePageFragment = graphql` fragment CompliancePageFileListItem_compliancePageFragment on TrustCenter { canUpdate: permission(action: "core:trust-center:update") @@ -34,6 +36,9 @@ const fileFragment = graphql` fragment CompliancePageFileListItem_fileFragment on TrustCenterFile { id name + alias + canSetAlias: permission(action: "core:trust-center-alias:set") + canRemoveAlias: permission(action: "core:trust-center-alias:remove") category file { downloadUrl @@ -103,6 +108,14 @@ export function CompliancePageFileListItem(props: { {file.category} {formatDate(file.createdAt)} + + +