Skip to content

Commit

Permalink
Use FeedbackButton in DeleteDialog of CrudContextMenu (#2423)
Browse files Browse the repository at this point in the history
  • Loading branch information
jomunker authored Aug 14, 2024
1 parent b1bbd6a commit c0488eb
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 27 deletions.
7 changes: 7 additions & 0 deletions .changeset/metal-donuts-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@comet/admin": minor
---

Use `FeedbackButton` in `DeleteDialog` of `CrudContextMenu`

This provides the user with feedback about the current status of the delete action.
28 changes: 14 additions & 14 deletions packages/admin/admin/src/common/buttons/feedback/FeedbackButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export function FeedbackButton(inProps: FeedbackButtonProps) {
tooltipSuccessMessage = <FormattedMessage id="comet.feedbackButton.tooltipSuccessMessage" defaultMessage="Success" />,
tooltipErrorMessage = <FormattedMessage id="comet.feedbackButton.tooltipErrorMessage" defaultMessage="Error" />,
slotProps,

...restProps
} = useThemeProps({
props: inProps,
Expand All @@ -71,16 +70,17 @@ export function FeedbackButton(inProps: FeedbackButtonProps) {
const [displayState, setDisplayState] = React.useState<FeedbackButtonDisplayState>("idle");

const ownerState: OwnerState = {
displayState: displayState,
displayState,
};

const resolveTooltipForDisplayState = (displayState: FeedbackButtonDisplayState) => {
if (displayState === "success") {
return "success";
} else if (displayState === "error") {
return "error";
} else {
return "neutral";
switch (displayState) {
case "error":
return "error";
case "success":
return "success";
default:
return "neutral";
}
};

Expand All @@ -92,8 +92,8 @@ export function FeedbackButton(inProps: FeedbackButtonProps) {
if (displayState === "idle" && loading) {
setDisplayState("loading");
} else if (displayState === "loading" && hasErrors) {
timeoutDuration = 500;
newDisplayState = "loading";
timeoutDuration = 0;
newDisplayState = "error";
} else if (displayState === "loading" && !loading && !hasErrors) {
timeoutDuration = 500;
newDisplayState = "success";
Expand All @@ -119,23 +119,23 @@ export function FeedbackButton(inProps: FeedbackButtonProps) {

const tooltip = (
<Tooltip
title={displayState === "error" ? tooltipErrorMessage : tooltipSuccessMessage}
title={displayState === "error" ? tooltipErrorMessage : displayState === "success" ? tooltipSuccessMessage : ""}
open={displayState === "error" || displayState === "success"}
placement={endIcon && !startIcon ? "top-end" : "top-start"}
variant={resolveTooltipForDisplayState(displayState)}
{...slotProps?.tooltip}
>
<span>{startIcon ? startIcon : endIcon}</span>
<span>{startIcon || endIcon}</span>
</Tooltip>
);

return (
<Root
ownerState={ownerState}
loading={loading}
loading={loading !== undefined ? loading : displayState === "loading"}
variant={variant}
color={color}
disabled={disabled || displayState === "loading"}
disabled={disabled || loading || displayState === "loading"}
loadingPosition={startIcon ? "start" : "end"}
loadingIndicator={<ThreeDotSaving />}
startIcon={startIcon && tooltip}
Expand Down
48 changes: 35 additions & 13 deletions packages/admin/admin/src/dataGrid/CrudContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ import { FormattedMessage, useIntl } from "react-intl";

import { readClipboardText } from "../clipboard/readClipboardText";
import { writeClipboardText } from "../clipboard/writeClipboardText";
import { FeedbackButton } from "../common/buttons/feedback/FeedbackButton";
import { useErrorDialog } from "../error/errordialog/useErrorDialog";
import { messages } from "../messages";
import { RowActionsItem } from "../rowActions/RowActionsItem";
import { RowActionsMenu } from "../rowActions/RowActionsMenu";

interface DeleteDialogProps {
dialogOpen: boolean;
loading?: boolean;
hasErrors?: boolean;
onDelete: () => void;
onCancel: () => void;
}

const DeleteDialog: React.FC<DeleteDialogProps> = (props) => {
const { dialogOpen, onDelete, onCancel } = props;
const { dialogOpen, loading, hasErrors, onDelete, onCancel } = props;

return (
<Dialog open={dialogOpen} onClose={onDelete}>
Expand All @@ -29,12 +32,20 @@ const DeleteDialog: React.FC<DeleteDialogProps> = (props) => {
<FormattedMessage id="comet.table.deleteDialog.content" defaultMessage="WARNING: This cannot be undone!" />
</DialogContent>
<DialogActions>
<Button onClick={onDelete} color="primary">
<Button onClick={onCancel} color="primary">
<FormattedMessage {...messages.no} />
</Button>
<Button onClick={onCancel} color="primary" variant="contained">
<FeedbackButton
startIcon={<DeleteIcon />}
onClick={onDelete}
loading={loading}
hasErrors={hasErrors}
color="primary"
variant="contained"
tooltipErrorMessage={<FormattedMessage id="comet.common.deleteFailed" defaultMessage="Failed to delete" />}
>
<FormattedMessage {...messages.yes} />
</Button>
</FeedbackButton>
</DialogActions>
</Dialog>
);
Expand All @@ -57,14 +68,25 @@ export function CrudContextMenu<CopyData>({ url, onPaste, onDelete, refetchQueri
const [deleteDialogOpen, setDeleteDialogOpen] = React.useState(false);
const [copyLoading, setCopyLoading] = React.useState(false);
const [pasting, setPasting] = React.useState(false);
const [deleteLoading, setDeleteLoading] = React.useState(false);
const [hasDeleteErrors, setHasDeleteErrors] = React.useState(false);

const handleDeleteClick = async () => {
if (!onDelete) return;
await onDelete({
client,
});
if (refetchQueries) await client.refetchQueries({ include: refetchQueries });
setDeleteDialogOpen(false);
setHasDeleteErrors(false);
setDeleteLoading(true);
try {
await onDelete({
client,
});
if (refetchQueries) await client.refetchQueries({ include: refetchQueries });
setDeleteDialogOpen(false);
} catch (_) {
setHasDeleteErrors(true);
throw new Error("Delete failed");
} finally {
setDeleteLoading(false);
}
};

const handlePasteClick = async () => {
Expand Down Expand Up @@ -166,10 +188,10 @@ export function CrudContextMenu<CopyData>({ url, onPaste, onDelete, refetchQueri
</RowActionsMenu>
<DeleteDialog
dialogOpen={deleteDialogOpen}
onDelete={() => {
setDeleteDialogOpen(false);
}}
onCancel={handleDeleteClick}
hasErrors={hasDeleteErrors}
loading={deleteLoading}
onCancel={() => setDeleteDialogOpen(false)}
onDelete={handleDeleteClick}
/>
</>
);
Expand Down

0 comments on commit c0488eb

Please sign in to comment.