diff --git a/.changeset/metal-donuts-suffer.md b/.changeset/metal-donuts-suffer.md
new file mode 100644
index 0000000000..c4129f8083
--- /dev/null
+++ b/.changeset/metal-donuts-suffer.md
@@ -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.
diff --git a/packages/admin/admin/src/common/buttons/feedback/FeedbackButton.tsx b/packages/admin/admin/src/common/buttons/feedback/FeedbackButton.tsx
index 6b8bba5d48..8ca5d8a5f4 100644
--- a/packages/admin/admin/src/common/buttons/feedback/FeedbackButton.tsx
+++ b/packages/admin/admin/src/common/buttons/feedback/FeedbackButton.tsx
@@ -61,7 +61,6 @@ export function FeedbackButton(inProps: FeedbackButtonProps) {
tooltipSuccessMessage = ,
tooltipErrorMessage = ,
slotProps,
-
...restProps
} = useThemeProps({
props: inProps,
@@ -71,16 +70,17 @@ export function FeedbackButton(inProps: FeedbackButtonProps) {
const [displayState, setDisplayState] = React.useState("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";
}
};
@@ -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";
@@ -119,23 +119,23 @@ export function FeedbackButton(inProps: FeedbackButtonProps) {
const tooltip = (
- {startIcon ? startIcon : endIcon}
+ {startIcon || endIcon}
);
return (
}
startIcon={startIcon && tooltip}
diff --git a/packages/admin/admin/src/dataGrid/CrudContextMenu.tsx b/packages/admin/admin/src/dataGrid/CrudContextMenu.tsx
index c183e152d4..f0b435360b 100644
--- a/packages/admin/admin/src/dataGrid/CrudContextMenu.tsx
+++ b/packages/admin/admin/src/dataGrid/CrudContextMenu.tsx
@@ -6,6 +6,7 @@ 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";
@@ -13,12 +14,14 @@ import { RowActionsMenu } from "../rowActions/RowActionsMenu";
interface DeleteDialogProps {
dialogOpen: boolean;
+ loading?: boolean;
+ hasErrors?: boolean;
onDelete: () => void;
onCancel: () => void;
}
const DeleteDialog: React.FC = (props) => {
- const { dialogOpen, onDelete, onCancel } = props;
+ const { dialogOpen, loading, hasErrors, onDelete, onCancel } = props;
return (
);
@@ -57,14 +68,25 @@ export function CrudContextMenu({ 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 () => {
@@ -166,10 +188,10 @@ export function CrudContextMenu({ url, onPaste, onDelete, refetchQueri
{
- setDeleteDialogOpen(false);
- }}
- onCancel={handleDeleteClick}
+ hasErrors={hasDeleteErrors}
+ loading={deleteLoading}
+ onCancel={() => setDeleteDialogOpen(false)}
+ onDelete={handleDeleteClick}
/>
>
);