diff --git a/apps/console/src/components/trustCenter/DeleteTrustCenterReferenceDialog.tsx b/apps/console/src/components/trustCenter/DeleteTrustCenterReferenceDialog.tsx new file mode 100644 index 000000000..2fd399d50 --- /dev/null +++ b/apps/console/src/components/trustCenter/DeleteTrustCenterReferenceDialog.tsx @@ -0,0 +1,83 @@ +import { + Button, + Dialog, + DialogContent, + DialogFooter, + IconTrashCan, + Spinner, + useDialogRef, +} from "@probo/ui"; +import { useTranslate } from "@probo/i18n"; +import { sprintf } from "@probo/helpers"; +import { useMutationWithToasts } from "/hooks/useMutationWithToasts"; +import { deleteTrustCenterReferenceMutation } from "/hooks/graph/TrustCenterReferenceGraph"; + +type Props = { + children: React.ReactNode; + referenceId: string; + referenceName: string; + connectionId: string; + onSuccess?: () => void; +}; + +export function DeleteTrustCenterReferenceDialog({ + children, + referenceId, + referenceName, + connectionId, + onSuccess, +}: Props) { + const { __ } = useTranslate(); + const ref = useDialogRef(); + + const [mutate, isDeleting] = useMutationWithToasts(deleteTrustCenterReferenceMutation, { + successMessage: __("Reference deleted successfully"), + errorMessage: __("Failed to delete reference"), + }); + + const handleDelete = async () => { + await mutate({ + variables: { + input: { + id: referenceId, + }, + connections: [connectionId], + }, + }); + + onSuccess?.(); + ref.current?.close(); + }; + + return ( + + +

+ {sprintf( + __("Are you sure you want to delete the reference \"%s\"?"), + referenceName + )} +

+

+ {__("This action cannot be undone.")} +

+
+ + + + +
+ ); +} diff --git a/apps/console/src/components/trustCenter/TrustCenterReferenceDialog.tsx b/apps/console/src/components/trustCenter/TrustCenterReferenceDialog.tsx new file mode 100644 index 000000000..8713914f2 --- /dev/null +++ b/apps/console/src/components/trustCenter/TrustCenterReferenceDialog.tsx @@ -0,0 +1,262 @@ +import { useTranslate } from "@probo/i18n"; +import { + Button, + Dialog, + DialogContent, + DialogFooter, + Dropzone, + Field, + Spinner, + Textarea, + useDialogRef, +} from "@probo/ui"; +import { type ReactNode, useState, useImperativeHandle, forwardRef } from "react"; +import { z } from "zod"; +import { useFormWithSchema } from "/hooks/useFormWithSchema"; +import { + useCreateTrustCenterReferenceMutation, + useUpdateTrustCenterReferenceMutation +} from "/hooks/graph/TrustCenterReferenceGraph"; + +const referenceSchema = z.object({ + name: z.string().min(1, "Name is required"), + description: z.string(), + websiteUrl: z.string().url("Please enter a valid URL"), +}); + +type ReferenceFormData = z.infer; + +export type TrustCenterReferenceDialogRef = { + openCreate: (trustCenterId: string, connectionId: string) => void; + openEdit: (reference: { + id: string; + name: string; + description: string; + websiteUrl: string; + }) => void; +}; + +type Reference = { + id: string; + name: string; + description: string; + websiteUrl: string; +}; + +export const TrustCenterReferenceDialog = forwardRef( + function TrustCenterReferenceDialog({ children }, ref) { + const { __ } = useTranslate(); + const dialogRef = useDialogRef(); + const [mode, setMode] = useState<'create' | 'edit'>('create'); + const [trustCenterId, setTrustCenterId] = useState(""); + const [connectionId, setConnectionId] = useState(""); + const [editReference, setEditReference] = useState(null); + const [uploadedFile, setUploadedFile] = useState(null); + + const [createReference, isCreating] = useCreateTrustCenterReferenceMutation(); + const [updateReference, isUpdating] = useUpdateTrustCenterReferenceMutation(); + + const { register, handleSubmit, formState: { errors }, reset } = useFormWithSchema( + referenceSchema, + { + defaultValues: { + name: "", + description: "", + websiteUrl: "", + }, + } + ); + + useImperativeHandle(ref, () => ({ + openCreate: (tId: string, cId: string) => { + setMode('create'); + setTrustCenterId(tId); + setConnectionId(cId); + setEditReference(null); + setUploadedFile(null); + reset({ + name: "", + description: "", + websiteUrl: "", + }); + dialogRef.current?.open(); + }, + openEdit: (reference: Reference) => { + setMode('edit'); + setEditReference(reference); + setUploadedFile(null); + reset({ + name: reference.name, + description: reference.description, + websiteUrl: reference.websiteUrl, + }); + dialogRef.current?.open(); + }, + })); + + const handleDrop = (files: File[]) => { + if (files.length > 0) { + const file = files[0]; + setUploadedFile(file); + } + }; + + const onSubmit = handleSubmit(async (data: ReferenceFormData) => { + if (mode === 'create') { + if (!uploadedFile) { + return; + } + + await createReference({ + variables: { + input: { + trustCenterId, + name: data.name, + description: data.description, + websiteUrl: data.websiteUrl, + logoFile: null, + }, + connections: [connectionId], + }, + uploadables: { + "input.logoFile": uploadedFile, + }, + onSuccess: () => { + reset(); + setUploadedFile(null); + dialogRef.current?.close(); + }, + }); + } else if (editReference) { + const input: { + id: string; + name: string; + description: string; + websiteUrl: string; + logoFile?: null; + } = { + id: editReference.id, + name: data.name, + description: data.description, + websiteUrl: data.websiteUrl, + }; + + const uploadables: Record = {}; + + if (uploadedFile) { + input.logoFile = null; + uploadables["input.logoFile"] = uploadedFile; + } + + await updateReference({ + variables: { input }, + uploadables: Object.keys(uploadables).length > 0 ? uploadables : undefined, + onSuccess: () => { + reset(); + setUploadedFile(null); + dialogRef.current?.close(); + }, + }); + } + }); + + const handleClose = () => { + reset(); + setUploadedFile(null); + }; + + const isSubmitting = isCreating || isUpdating; + const title = mode === 'create' ? __("Add Reference") : __("Edit Reference"); + + return ( + <> + {children && ( + mode === 'create' && dialogRef.current?.open()}> + {children} + + )} + + +
+ + + + +