Skip to content

Commit

Permalink
refactor(ui): Simplify delete dialog props
Browse files Browse the repository at this point in the history
This change allows for a wider variety in description for future delete
dialogs. The description is taken in as a prop and the item name and
descriptor are removed.

Signed-off-by: Mikko Murto <mikko.murto@doubleopen.org>
  • Loading branch information
mmurto committed Nov 29, 2024
1 parent c02640a commit 527fa7b
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 57 deletions.
73 changes: 37 additions & 36 deletions ui/src/components/delete-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,31 @@ import {
interface DeleteDialogProps {
open?: boolean;
setOpen?: React.Dispatch<React.SetStateAction<boolean>>;
item: {
descriptor: string;
name: string;
};
description: ReactNode;
onDelete: () => void;
isPending: boolean;
textConfirmation?: boolean;
/**
* Optional confirmation text to be required before deletion. If the text is provided, the user is
* required to type the text in an input field to confirm the deletion. If the text is not
* provided, the user can delete the item without any additional confirmation.
*/
confirmationText?: string;
trigger: ReactNode;
}

export const DeleteDialog = ({
open,
setOpen,
item,
onDelete,
description,
isPending,
textConfirmation = false,
confirmationText,
trigger,
}: DeleteDialogProps) => {
const [input, setInput] = useState('');
const isDeleteDisabled = textConfirmation && input !== item.name;
const isDeleteDisabled = confirmationText
? input !== confirmationText
: false;

// Reset the input field whenever the dialog is opened/closed
useEffect(() => {
Expand All @@ -76,42 +80,39 @@ export const DeleteDialog = ({
<TooltipTrigger asChild>
<AlertDialogTrigger asChild>{trigger}</AlertDialogTrigger>
</TooltipTrigger>
<TooltipContent>Delete this {item.descriptor}</TooltipContent>
<TooltipContent>Delete</TooltipContent>
</Tooltip>
{/* Adding the preventDefault will prevent focusing on the trigger after closing the modal (which would cause the tooltip to show) */}
<AlertDialogContent onCloseAutoFocus={(e) => e.preventDefault()}>
<AlertDialogHeader>
<div className='flex items-center'>
<OctagonAlert className='h-8 w-8 pr-2 text-red-500' />
<AlertDialogTitle>Delete {item.descriptor}</AlertDialogTitle>
<AlertDialogTitle>Confirm deletion</AlertDialogTitle>
</div>
</AlertDialogHeader>
{textConfirmation ? (
<AlertDialogDescription>
<div className='flex flex-col gap-2'>
<div>
Are you sure you want to delete this {item.descriptor}:{' '}
<span className='font-bold'>{item.name}</span>?
</div>
<div>
Deleting might have unwanted results and side effects, and the
deletion is irreversible. Please type{' '}
<span className='font-bold'>{item.name}</span> below to confirm
deletion.
</div>
<Input
autoFocus
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<AlertDialogDescription>
<div className='flex flex-col gap-2'>
<div>{description}</div>
<div>
Deleting might have unwanted results and side effects, and the
deletion is irreversible.
</div>
</AlertDialogDescription>
) : (
<AlertDialogDescription>
Are you sure you want to delete this {item.descriptor}:{' '}
<span className='font-bold'>{item.name}</span>?
</AlertDialogDescription>
)}
{confirmationText && (
<>
<div>
Please type{' '}
<span className='font-bold'>{confirmationText}</span> below to
confirm deletion.
</div>
<Input
autoFocus
value={input}
onChange={(e) => setInput(e.target.value)}
/>
</>
)}
</div>
</AlertDialogDescription>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<Button
Expand All @@ -121,7 +122,7 @@ export const DeleteDialog = ({
>
{isPending ? (
<>
<span className='sr-only'>Deleting {item.descriptor}...</span>
<span className='sr-only'>Deleting...</span>
<Loader2 size={16} className='mx-3 animate-spin' />
</>
) : (
Expand Down
12 changes: 7 additions & 5 deletions ui/src/routes/admin/users/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,15 @@ const columns = [
<DeleteDialog
open={openDelDialog}
setOpen={setOpenDelDialog}
item={{
descriptor: 'user',
name: row.original.username,
}}
onDelete={() => delUser({ username: row.original.username })}
isPending={isDelPending}
textConfirmation={true}
confirmationText={row.original.username}
description={
<>
Are you sure you want to delete the user{' '}
<span className='font-bold'>{row.original.username}</span>?
</>
}
trigger={<DeleteIconButton />}
/>
</div>
Expand Down
10 changes: 6 additions & 4 deletions ui/src/routes/organizations/$orgId/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,13 @@ const OrganizationComponent = () => {
</Tooltip>
</div>
<DeleteDialog
item={{
descriptor: 'organization',
name: organization.name,
}}
onDelete={handleDelete}
description={
<>
Are you sure you want to delete the organization{' '}
<span className='font-bold'>{organization.name}</span>?
</>
}
isPending={isPending}
trigger={<DeleteIconButton />}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,18 @@ const ActionCell = ({ row }: CellContext<InfrastructureService, unknown>) => {
<DeleteDialog
open={openDelDialog}
setOpen={setOpenDelDialog}
item={{ descriptor: 'infrastructure service', name: row.original.name }}
onDelete={() =>
delService({
organizationId: Number.parseInt(params.orgId),
serviceName: row.original.name,
})
}
description={
<>
Are you sure you want to delete the infrastructure service{' '}
<span className='font-bold'>{row.original.name}</span>?
</>
}
isPending={delIsPending}
trigger={<DeleteIconButton />}
/>
Expand Down
10 changes: 6 additions & 4 deletions ui/src/routes/organizations/$orgId/products/$productId/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,12 @@ const ProductComponent = () => {
</Tooltip>
</div>
<DeleteDialog
item={{
descriptor: 'product',
name: product.name,
}}
description={
<>
Are you sure you want to delete the product{' '}
<span className='font-bold'>{product.name}</span>?
</>
}
onDelete={handleDelete}
isPending={isPending}
trigger={<DeleteIconButton />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,12 @@ const ActionCell = ({ row }: CellContext<Secret, unknown>) => {
<DeleteDialog
open={openDelDialog}
setOpen={setOpenDelDialog}
item={{ descriptor: 'secret', name: row.original.name }}
description={
<>
Are you sure you want to delete the secret{' '}
<span className='font-bold'>{row.original.name}</span>?
</>
}
onDelete={() =>
deleteSecret({
repositoryId: repo.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,12 @@ const RepositorySettingsPage = () => {
<div className='flex justify-between'>
<div>Delete this repository</div>
<DeleteDialog
item={{
descriptor: 'repository',
name: repository.url,
}}
description={
<>
Are you sure you want to delete the repository{' '}
<span className='font-bold'>{repository.url}</span>?
</>
}
onDelete={handleDelete}
isPending={deleteIsPending}
trigger={<Button variant='destructive'>Delete repository</Button>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,12 @@ const ActionCell = ({ row }: CellContext<Secret, unknown>) => {
<DeleteDialog
open={openDelDialog}
setOpen={setOpenDelDialog}
item={{ descriptor: 'secret', name: row.original.name }}
description={
<>
Are you sure you want to delete the secret{' '}
<span className='font-bold'>{row.original.name}</span>?
</>
}
onDelete={() =>
deleteSecret({
productId: product.id,
Expand Down
7 changes: 6 additions & 1 deletion ui/src/routes/organizations/$orgId/secrets/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,12 @@ const ActionCell = ({ row }: CellContext<Secret, unknown>) => {
<DeleteDialog
open={openDelDialog}
setOpen={setOpenDelDialog}
item={{ descriptor: 'secret', name: row.original.name }}
description={
<>
Are you sure you want to delete the secret{' '}
<span className='font-bold'>{row.original.name}</span>?
</>
}
onDelete={() =>
delSecret({
organizationId: organization.id,
Expand Down

0 comments on commit 527fa7b

Please sign in to comment.