@@ -1,389 +0,0 @@
|
||||
/**
|
||||
* @generated SignedSource<<ca40d9ddba0f52570c2c9cece97e15dc>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type TrustCenterReferenceGraphQuery$variables = {
|
||||
trustCenterId: string;
|
||||
};
|
||||
export type TrustCenterReferenceGraphQuery$data = {
|
||||
readonly node: {
|
||||
readonly __typename: "TrustCenter";
|
||||
readonly id: string;
|
||||
readonly references: {
|
||||
readonly __id: string;
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly cursor: string;
|
||||
readonly node: {
|
||||
readonly canDelete: boolean;
|
||||
readonly canUpdate: boolean;
|
||||
readonly createdAt: string;
|
||||
readonly description: string | null | undefined;
|
||||
readonly id: string;
|
||||
readonly logoUrl: string;
|
||||
readonly name: string;
|
||||
readonly rank: number;
|
||||
readonly updatedAt: string;
|
||||
readonly websiteUrl: string;
|
||||
};
|
||||
}>;
|
||||
readonly pageInfo: {
|
||||
readonly endCursor: string | null | undefined;
|
||||
readonly hasNextPage: boolean;
|
||||
readonly hasPreviousPage: boolean;
|
||||
readonly startCursor: string | null | undefined;
|
||||
};
|
||||
};
|
||||
} | {
|
||||
// This will never be '%other', but we need some
|
||||
// value in case none of the concrete values match.
|
||||
readonly __typename: "%other";
|
||||
};
|
||||
};
|
||||
export type TrustCenterReferenceGraphQuery = {
|
||||
response: TrustCenterReferenceGraphQuery$data;
|
||||
variables: TrustCenterReferenceGraphQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "trustCenterId"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "trustCenterId"
|
||||
}
|
||||
],
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v4 = {
|
||||
"kind": "Literal",
|
||||
"name": "orderBy",
|
||||
"value": {
|
||||
"direction": "ASC",
|
||||
"field": "RANK"
|
||||
}
|
||||
},
|
||||
v5 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasNextPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasPreviousPage",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "startCursor",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "endCursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v6 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "TrustCenterReferenceEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "cursor",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "TrustCenterReference",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "description",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "websiteUrl",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "logoUrl",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "rank",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "updatedAt",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": "canUpdate",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "action",
|
||||
"value": "core:trust-center-reference:update"
|
||||
}
|
||||
],
|
||||
"kind": "ScalarField",
|
||||
"name": "permission",
|
||||
"storageKey": "permission(action:\"core:trust-center-reference:update\")"
|
||||
},
|
||||
{
|
||||
"alias": "canDelete",
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "action",
|
||||
"value": "core:trust-center-reference:delete"
|
||||
}
|
||||
],
|
||||
"kind": "ScalarField",
|
||||
"name": "permission",
|
||||
"storageKey": "permission(action:\"core:trust-center-reference:delete\")"
|
||||
},
|
||||
(v2/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
v7 = {
|
||||
"kind": "ClientExtension",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__id",
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
v8 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 100
|
||||
},
|
||||
(v4/*: any*/)
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "TrustCenterReferenceGraphQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"kind": "RequiredField",
|
||||
"field": {
|
||||
"alias": "references",
|
||||
"args": [
|
||||
(v4/*: any*/)
|
||||
],
|
||||
"concreteType": "TrustCenterReferenceConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__TrustCenterReferencesSection_references_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v5/*: any*/),
|
||||
{
|
||||
"kind": "RequiredField",
|
||||
"field": (v6/*: any*/),
|
||||
"action": "THROW"
|
||||
},
|
||||
(v7/*: any*/)
|
||||
],
|
||||
"storageKey": "__TrustCenterReferencesSection_references_connection(orderBy:{\"direction\":\"ASC\",\"field\":\"RANK\"})"
|
||||
},
|
||||
"action": "THROW"
|
||||
}
|
||||
],
|
||||
"type": "TrustCenter",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "TrustCenterReferenceGraphQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v8/*: any*/),
|
||||
"concreteType": "TrustCenterReferenceConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "references",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v5/*: any*/),
|
||||
(v6/*: any*/),
|
||||
(v7/*: any*/)
|
||||
],
|
||||
"storageKey": "references(first:100,orderBy:{\"direction\":\"ASC\",\"field\":\"RANK\"})"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v8/*: any*/),
|
||||
"filters": [
|
||||
"orderBy"
|
||||
],
|
||||
"handle": "connection",
|
||||
"key": "TrustCenterReferencesSection_references",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "references"
|
||||
}
|
||||
],
|
||||
"type": "TrustCenter",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "3eaf772859927eca50f824a7298fd2d5",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"node",
|
||||
"references"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "TrustCenterReferenceGraphQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query TrustCenterReferenceGraphQuery(\n $trustCenterId: ID!\n) {\n node(id: $trustCenterId) {\n __typename\n ... on TrustCenter {\n id\n references(first: 100, orderBy: {field: RANK, direction: ASC}) {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n edges {\n cursor\n node {\n id\n name\n description\n websiteUrl\n logoUrl\n rank\n createdAt\n updatedAt\n canUpdate: permission(action: \"core:trust-center-reference:update\")\n canDelete: permission(action: \"core:trust-center-reference:delete\")\n __typename\n }\n }\n }\n }\n id\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "5c1e65a30423ec4357ef2cb546bca387";
|
||||
|
||||
export default node;
|
||||
@@ -1,259 +0,0 @@
|
||||
import { safeOpenUrl } from "@probo/helpers";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
IconArrowLink,
|
||||
IconPencil,
|
||||
IconPlusLarge,
|
||||
IconTrashCan,
|
||||
Table,
|
||||
Tbody,
|
||||
Td,
|
||||
Th,
|
||||
Thead,
|
||||
Tr,
|
||||
} from "@probo/ui";
|
||||
import { useRef, useState } from "react";
|
||||
import { useLazyLoadQuery } from "react-relay";
|
||||
|
||||
import type {
|
||||
TrustCenterReferenceGraphQuery$data,
|
||||
TrustCenterReferenceGraphQuery,
|
||||
} from "#/__generated__/core/TrustCenterReferenceGraphQuery.graphql";
|
||||
import {
|
||||
trustCenterReferencesQuery,
|
||||
useUpdateTrustCenterReferenceRankMutation,
|
||||
} from "#/hooks/graph/TrustCenterReferenceGraph";
|
||||
|
||||
import { DeleteTrustCenterReferenceDialog } from "./DeleteTrustCenterReferenceDialog";
|
||||
import {
|
||||
TrustCenterReferenceDialog,
|
||||
type TrustCenterReferenceDialogRef,
|
||||
} from "./TrustCenterReferenceDialog";
|
||||
|
||||
type Props = {
|
||||
trustCenterId: string;
|
||||
canCreateReference: boolean;
|
||||
};
|
||||
|
||||
export type Reference = Extract<
|
||||
TrustCenterReferenceGraphQuery$data["node"],
|
||||
{ __typename: "TrustCenter" }
|
||||
>["references"]["edges"][number]["node"];
|
||||
|
||||
export function TrustCenterReferencesSection({
|
||||
canCreateReference,
|
||||
trustCenterId,
|
||||
}: Props) {
|
||||
const { __ } = useTranslate();
|
||||
const dialogRef = useRef<TrustCenterReferenceDialogRef>(null);
|
||||
const [draggedIndex, setDraggedIndex] = useState<number | null>(null);
|
||||
const [dragOverIndex, setDragOverIndex] = useState<number | null>(null);
|
||||
const [refetchKey, setRefetchKey] = useState(0);
|
||||
const { node: trustCenterNode }
|
||||
= useLazyLoadQuery<TrustCenterReferenceGraphQuery>(
|
||||
trustCenterReferencesQuery,
|
||||
{ trustCenterId: trustCenterId || "" },
|
||||
{ fetchPolicy: "network-only", fetchKey: refetchKey },
|
||||
);
|
||||
if (trustCenterNode.__typename !== "TrustCenter") {
|
||||
throw new Error("invalid node type");
|
||||
}
|
||||
const [updateRank] = useUpdateTrustCenterReferenceRankMutation();
|
||||
|
||||
const references
|
||||
= trustCenterNode?.references?.edges?.map(edge => edge.node) || [];
|
||||
const referencesConnectionId = trustCenterNode?.references?.__id || "";
|
||||
|
||||
const handleCreate = () => {
|
||||
if (referencesConnectionId) {
|
||||
dialogRef.current?.openCreate(trustCenterId, referencesConnectionId);
|
||||
}
|
||||
};
|
||||
|
||||
const handleEdit = (reference: Reference) => {
|
||||
dialogRef.current?.openEdit(reference);
|
||||
};
|
||||
|
||||
const handleVisitWebsite = (websiteUrl: string) => {
|
||||
safeOpenUrl(websiteUrl);
|
||||
};
|
||||
|
||||
const handleDragStart = (index: number) => {
|
||||
setDraggedIndex(index);
|
||||
};
|
||||
|
||||
const handleDragOver = (e: React.DragEvent, index: number) => {
|
||||
e.preventDefault();
|
||||
if (draggedIndex !== index) {
|
||||
setDragOverIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDrop = async (targetIndex: number) => {
|
||||
if (draggedIndex === null || draggedIndex === targetIndex) {
|
||||
setDraggedIndex(null);
|
||||
setDragOverIndex(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const draggedRef = references[draggedIndex];
|
||||
const targetRank = references[targetIndex].rank;
|
||||
|
||||
await updateRank({
|
||||
variables: {
|
||||
input: {
|
||||
id: draggedRef.id,
|
||||
rank: targetRank,
|
||||
},
|
||||
},
|
||||
onCompleted: () => {
|
||||
setRefetchKey(prev => prev + 1);
|
||||
},
|
||||
});
|
||||
|
||||
setDraggedIndex(null);
|
||||
setDragOverIndex(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-base font-medium">{__("Trusted by")}</h2>
|
||||
<p className="text-sm text-txt-tertiary">
|
||||
{__("Showcase your customers and partners on your trust center")}
|
||||
</p>
|
||||
</div>
|
||||
{canCreateReference && (
|
||||
<Button icon={IconPlusLarge} onClick={handleCreate}>
|
||||
{__("Add Reference")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Table>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{__("Name")}</Th>
|
||||
<Th>{__("Description")}</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{references.length === 0 && (
|
||||
<Tr>
|
||||
<Td colSpan={3} className="text-center text-txt-secondary">
|
||||
{__("No references available")}
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
{references.map((reference: Reference, index: number) => (
|
||||
<ReferenceRow
|
||||
key={reference.id}
|
||||
reference={reference}
|
||||
index={index}
|
||||
isDragging={draggedIndex === index}
|
||||
isDropTarget={dragOverIndex === index && draggedIndex !== index}
|
||||
onEdit={() => handleEdit(reference)}
|
||||
connectionId={referencesConnectionId}
|
||||
onVisitWebsite={() => handleVisitWebsite(reference.websiteUrl)}
|
||||
onDragStart={() => handleDragStart(index)}
|
||||
onDragOver={e => handleDragOver(e, index)}
|
||||
onDrop={() => void handleDrop(index)}
|
||||
/>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
|
||||
<p className="text-xs text-txt-tertiary">
|
||||
{__("Drag and drop references to change their displayed order")}
|
||||
</p>
|
||||
|
||||
<TrustCenterReferenceDialog ref={dialogRef} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type ReferenceRowProps = {
|
||||
reference: Reference;
|
||||
index: number;
|
||||
isDragging: boolean;
|
||||
isDropTarget: boolean;
|
||||
onEdit: () => void;
|
||||
connectionId: string;
|
||||
onVisitWebsite: () => void;
|
||||
onDragStart: () => void;
|
||||
onDragOver: (e: React.DragEvent) => void;
|
||||
onDrop: () => void;
|
||||
};
|
||||
|
||||
function ReferenceRow({
|
||||
reference,
|
||||
isDragging,
|
||||
isDropTarget,
|
||||
onEdit,
|
||||
connectionId,
|
||||
onVisitWebsite,
|
||||
onDragStart,
|
||||
onDragOver,
|
||||
onDrop,
|
||||
}: ReferenceRowProps) {
|
||||
const [isMouseDown, setIsMouseDown] = useState(false);
|
||||
|
||||
const className = [
|
||||
isDragging && "opacity-50 cursor-grabbing",
|
||||
!isDragging && !isMouseDown && "cursor-grab",
|
||||
!isDragging && isMouseDown && "cursor-grabbing",
|
||||
isDropTarget && "!bg-primary-50 border-y-2 border-primary-500",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(" ");
|
||||
|
||||
return (
|
||||
<Tr
|
||||
draggable
|
||||
onDragStart={onDragStart}
|
||||
onDragOver={onDragOver}
|
||||
onDrop={onDrop}
|
||||
onMouseDown={() => setIsMouseDown(true)}
|
||||
onMouseUp={() => setIsMouseDown(false)}
|
||||
onMouseLeave={() => setIsMouseDown(false)}
|
||||
className={className}
|
||||
>
|
||||
<Td>
|
||||
<div className="flex items-center gap-3">
|
||||
<Avatar src={reference.logoUrl} name={reference.name} size="m" />
|
||||
<span className="font-medium">{reference.name}</span>
|
||||
</div>
|
||||
</Td>
|
||||
<Td>
|
||||
<span className="text-txt-secondary line-clamp-2">
|
||||
{reference.description}
|
||||
</span>
|
||||
</Td>
|
||||
<Td noLink width={200} className="text-end">
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Button
|
||||
variant="secondary"
|
||||
icon={IconArrowLink}
|
||||
onClick={onVisitWebsite}
|
||||
/>
|
||||
{reference.canUpdate && (
|
||||
<Button variant="secondary" icon={IconPencil} onClick={onEdit} />
|
||||
)}
|
||||
{reference.canDelete && (
|
||||
<DeleteTrustCenterReferenceDialog
|
||||
referenceId={reference.id}
|
||||
referenceName={reference.name}
|
||||
connectionId={connectionId}
|
||||
>
|
||||
<Button variant="danger" icon={IconTrashCan} />
|
||||
</DeleteTrustCenterReferenceDialog>
|
||||
)}
|
||||
</div>
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
}
|
||||
@@ -6,47 +6,6 @@ import type { TrustCenterReferenceGraphUpdateMutation } from "#/__generated__/co
|
||||
import type { TrustCenterReferenceGraphUpdateRankMutation } from "#/__generated__/core/TrustCenterReferenceGraphUpdateRankMutation.graphql";
|
||||
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
|
||||
|
||||
export const trustCenterReferencesQuery = graphql`
|
||||
query TrustCenterReferenceGraphQuery($trustCenterId: ID!) {
|
||||
node(id: $trustCenterId) {
|
||||
__typename
|
||||
... on TrustCenter {
|
||||
id
|
||||
references(first: 100, orderBy: { field: RANK, direction: ASC })
|
||||
@connection(key: "TrustCenterReferencesSection_references")
|
||||
@required(action: THROW) {
|
||||
__id
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
edges @required(action: THROW) {
|
||||
cursor
|
||||
node {
|
||||
id
|
||||
name
|
||||
description
|
||||
websiteUrl
|
||||
logoUrl
|
||||
rank
|
||||
createdAt
|
||||
updatedAt
|
||||
canUpdate: permission(
|
||||
action: "core:trust-center-reference:update"
|
||||
)
|
||||
canDelete: permission(
|
||||
action: "core:trust-center-reference:delete"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const createTrustCenterReferenceMutation = graphql`
|
||||
mutation TrustCenterReferenceGraphCreateMutation(
|
||||
$input: CreateTrustCenterReferenceInput!
|
||||
|
||||
@@ -1,294 +0,0 @@
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Checkbox,
|
||||
Dropzone,
|
||||
IconTrashCan,
|
||||
Spinner,
|
||||
useToast,
|
||||
} from "@probo/ui";
|
||||
import { useState } from "react";
|
||||
import { useOutletContext } from "react-router";
|
||||
|
||||
import type { TrustCenterGraphQuery$data } from "#/__generated__/core/TrustCenterGraphQuery.graphql";
|
||||
import {
|
||||
useDeleteTrustCenterNDAMutation,
|
||||
useUpdateTrustCenterMutation,
|
||||
useUploadTrustCenterNDAMutation,
|
||||
} from "#/hooks/graph/TrustCenterGraph";
|
||||
|
||||
import { SlackConnections } from "../../../components/organizations/SlackConnection";
|
||||
|
||||
export default function TrustCenterOverviewTab() {
|
||||
const { __ } = useTranslate();
|
||||
const { toast } = useToast();
|
||||
const { organization } = useOutletContext<TrustCenterGraphQuery$data>();
|
||||
|
||||
const [updateTrustCenter, isUpdating] = useUpdateTrustCenterMutation();
|
||||
const [uploadNDA, isUploadingNDA] = useUploadTrustCenterNDAMutation();
|
||||
const [deleteNDA, isDeletingNDA] = useDeleteTrustCenterNDAMutation();
|
||||
const [isActive, setIsActive] = useState(
|
||||
organization.trustCenter?.active || false,
|
||||
);
|
||||
|
||||
const canUpdateTrustCenter = organization.trustCenter?.canUpdate;
|
||||
|
||||
const handleToggleActive = async (active: boolean) => {
|
||||
if (!organization.trustCenter?.id) {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: __("Trust center not found"),
|
||||
variant: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setIsActive(active);
|
||||
|
||||
await updateTrustCenter({
|
||||
variables: {
|
||||
input: {
|
||||
trustCenterId: organization.trustCenter.id,
|
||||
active,
|
||||
},
|
||||
},
|
||||
onError: () => {
|
||||
setIsActive(!active);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleNDAUpload = async (files: File[]) => {
|
||||
if (!organization.trustCenter?.id) {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: __("Trust center not found"),
|
||||
variant: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (files.length === 0) return;
|
||||
|
||||
const file = files[0];
|
||||
|
||||
await uploadNDA({
|
||||
variables: {
|
||||
input: {
|
||||
trustCenterId: organization.trustCenter.id,
|
||||
fileName: file.name,
|
||||
file: null,
|
||||
},
|
||||
},
|
||||
uploadables: {
|
||||
"input.file": file,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleNDADelete = async () => {
|
||||
if (!organization.trustCenter?.id) {
|
||||
toast({
|
||||
title: __("Error"),
|
||||
description: __("Trust center not found"),
|
||||
variant: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(__("Are you sure you want to delete the NDA file?"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
await deleteNDA({
|
||||
variables: {
|
||||
input: {
|
||||
trustCenterId: organization.trustCenter.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const trustCenterUrl = organization.trustCenter?.id
|
||||
? organization.customDomain?.domain
|
||||
? `https://${organization.customDomain.domain}`
|
||||
: `${window.location.origin}/trust/${organization.trustCenter.id}`
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-base font-medium">{__("Trust Center Status")}</h2>
|
||||
{isUpdating && <Spinner />}
|
||||
</div>
|
||||
<Card padded className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1">
|
||||
<h3 className="font-medium">{__("Activate Trust Center")}</h3>
|
||||
<p className="text-sm text-txt-tertiary">
|
||||
{__(
|
||||
"Make your trust center publicly accessible to build customer confidence",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<Checkbox
|
||||
checked={isActive}
|
||||
onChange={checked => void handleToggleActive(checked)}
|
||||
disabled={!canUpdateTrustCenter}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isActive && trustCenterUrl && (
|
||||
<div className="mt-4 p-4 bg-accent-light rounded-lg border border-accent">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h4 className="font-medium text-accent-dark">
|
||||
{__("Your Trust Center is Live!")}
|
||||
</h4>
|
||||
<p className="text-sm text-accent-dark mt-1">
|
||||
{__("Your customers can now access your trust center at:")}
|
||||
</p>
|
||||
<a
|
||||
href={trustCenterUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm font-mono text-accent underline hover:no-underline"
|
||||
>
|
||||
{trustCenterUrl}
|
||||
</a>
|
||||
</div>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() =>
|
||||
window.open(trustCenterUrl, "_blank", "noopener,noreferrer")}
|
||||
>
|
||||
{__("View")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isActive && (
|
||||
<div className="mt-4 p-4 bg-tertiary rounded-lg border border-border-solid">
|
||||
<h4 className="font-medium text-txt-secondary">
|
||||
{__("Trust Center is Inactive")}
|
||||
</h4>
|
||||
<p className="text-sm text-txt-tertiary mt-1">
|
||||
{__(
|
||||
"Your trust center is currently not accessible to the public. Enable it to start sharing your compliance status.",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
{organization.trustCenter?.canGetNDA && (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-base font-medium">
|
||||
{__("Non-Disclosure Agreement")}
|
||||
</h2>
|
||||
{(isUploadingNDA || isDeletingNDA) && <Spinner />}
|
||||
</div>
|
||||
<Card padded className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
{!organization.trustCenter?.ndaFileName
|
||||
&& organization.trustCenter.canUploadNDA
|
||||
? (
|
||||
<p className="text-sm text-txt-tertiary">
|
||||
{__(
|
||||
"Upload a Non-Disclosure Agreement that visitors must accept before accessing your trust center",
|
||||
)}
|
||||
</p>
|
||||
)
|
||||
: (
|
||||
<></>
|
||||
)}
|
||||
{organization.trustCenter?.ndaFileName
|
||||
? (
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-sm font-medium">
|
||||
{organization.trustCenter.ndaFileName
|
||||
|| __("Non-Disclosure Agreement")}
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-xs text-txt-tertiary">
|
||||
{__(
|
||||
"Visitors will need to accept this NDA before accessing your trust center",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
if (organization.trustCenter?.ndaFileUrl) {
|
||||
window.open(
|
||||
organization.trustCenter.ndaFileUrl,
|
||||
"_blank",
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{__("Download PDF")}
|
||||
</Button>
|
||||
{organization.trustCenter?.canDeleteNDA && (
|
||||
<Button
|
||||
variant="quaternary"
|
||||
icon={IconTrashCan}
|
||||
onClick={() => void handleNDADelete()}
|
||||
disabled={isDeletingNDA}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
<>
|
||||
{canUpdateTrustCenter
|
||||
? (
|
||||
<Dropzone
|
||||
description={__("Upload PDF files up to 10MB")}
|
||||
isUploading={isUploadingNDA}
|
||||
onDrop={files => void handleNDAUpload(files)}
|
||||
accept={{
|
||||
"application/pdf": [".pdf"],
|
||||
}}
|
||||
maxSize={10}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<p className="text-sm text-txt-tertiary">
|
||||
{__("No NDA file uploaded")}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-base font-medium">{__("Integrations")}</h2>
|
||||
<Card padded>
|
||||
<SlackConnections
|
||||
canUpdate={!!organization.trustCenter?.canUpdate}
|
||||
organizationId={organization.id!}
|
||||
slackConnections={
|
||||
organization.slackConnections?.edges?.map(edge => edge.node)
|
||||
?? []
|
||||
}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { useOutletContext } from "react-router";
|
||||
|
||||
import type { TrustCenterGraphQuery$data } from "#/__generated__/core/TrustCenterGraphQuery.graphql";
|
||||
import { TrustCenterReferencesSection } from "#/components/trustCenter/TrustCenterReferencesSection";
|
||||
|
||||
export default function TrustCenterReferencesTab() {
|
||||
const { organization } = useOutletContext<TrustCenterGraphQuery$data>();
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
{organization.trustCenter?.id && (
|
||||
<TrustCenterReferencesSection
|
||||
trustCenterId={organization.trustCenter.id}
|
||||
canCreateReference={!!organization.trustCenter.canCreateReference}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -29,22 +29,6 @@ export const trustCenterRoutes = [
|
||||
lazy(() => import("#/pages/organizations/trustCenter/TrustCenterPage")),
|
||||
),
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
Fallback: LinkCardSkeleton,
|
||||
Component: lazy(
|
||||
() =>
|
||||
import("#/pages/organizations/trustCenter/TrustCenterOverviewTab"),
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "trust-by",
|
||||
Fallback: LinkCardSkeleton,
|
||||
Component: lazy(
|
||||
() =>
|
||||
import("#/pages/organizations/trustCenter/TrustCenterReferencesTab"),
|
||||
),
|
||||
},
|
||||
{
|
||||
path: "audits",
|
||||
Fallback: LinkCardSkeleton,
|
||||
|
||||
Reference in New Issue
Block a user