mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): split out delete workflow dialog logic into singleton
This commit is contained in:
@@ -27,6 +27,7 @@ import RefreshAfterResetModal from 'features/system/components/SettingsModal/Ref
|
||||
import { configChanged } from 'features/system/store/configSlice';
|
||||
import { selectLanguage } from 'features/system/store/systemSelectors';
|
||||
import { AppContent } from 'features/ui/components/AppContent';
|
||||
import { DeleteWorkflowDialog } from 'features/workflowLibrary/components/DeleteLibraryWorkflowConfirmationAlertDialog';
|
||||
import { NewWorkflowConfirmationAlertDialog } from 'features/workflowLibrary/components/NewWorkflowConfirmationAlertDialog';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import i18n from 'i18n';
|
||||
@@ -109,6 +110,7 @@ const App = ({ config = DEFAULT_CONFIG, studioInitAction }: Props) => {
|
||||
<StylePresetModal />
|
||||
<ClearQueueConfirmationsAlertDialog />
|
||||
<NewWorkflowConfirmationAlertDialog />
|
||||
<DeleteWorkflowDialog />
|
||||
<RefreshAfterResetModal />
|
||||
<DeleteBoardModal />
|
||||
<GlobalImageHotkeys />
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Badge, ConfirmationAlertDialog, Flex, IconButton, Spacer, Text, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { Badge, Flex, IconButton, Spacer, Text, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { EMPTY_OBJECT } from 'app/store/constants';
|
||||
import { $projectUrl } from 'app/store/nanostores/projectId';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useDisclosure } from 'common/hooks/useBoolean';
|
||||
import dateFormat, { masks } from 'dateformat';
|
||||
import { useWorkflowListMenu } from 'features/nodes/store/workflowListMenu';
|
||||
import { selectWorkflowId, workflowModeChanged } from 'features/nodes/store/workflowSlice';
|
||||
import { useDeleteLibraryWorkflow } from 'features/workflowLibrary/hooks/useDeleteLibraryWorkflow';
|
||||
import { useDeleteWorkflow } from 'features/workflowLibrary/components/DeleteLibraryWorkflowConfirmationAlertDialog';
|
||||
import { useDownloadWorkflow } from 'features/workflowLibrary/hooks/useDownloadWorkflow';
|
||||
import { useGetAndLoadLibraryWorkflow } from 'features/workflowLibrary/hooks/useGetAndLoadLibraryWorkflow';
|
||||
import type { MouseEvent } from 'react';
|
||||
@@ -20,7 +19,6 @@ import { CopyWorkflowLinkModal } from './CopyWorkflowLinkModal';
|
||||
import { WorkflowListItemTooltip } from './WorkflowListItemTooltip';
|
||||
|
||||
export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListItemDTO }) => {
|
||||
const deleteConfirmationDialog = useDisclosure(false);
|
||||
const copyWorkflowLinkModal = useDisclosure(false);
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
@@ -39,7 +37,7 @@ export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListIte
|
||||
const workflowId = useAppSelector(selectWorkflowId);
|
||||
const downloadWorkflow = useDownloadWorkflow();
|
||||
|
||||
const { deleteWorkflow, deleteWorkflowResult } = useDeleteLibraryWorkflow(EMPTY_OBJECT);
|
||||
const deleteWorkflow = useDeleteWorkflow();
|
||||
const { getAndLoadWorkflow } = useGetAndLoadLibraryWorkflow({
|
||||
onSuccess: workflowListMenu.close,
|
||||
});
|
||||
@@ -68,23 +66,13 @@ export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListIte
|
||||
[getAndLoadWorkflow, workflow.workflow_id, dispatch, workflowListMenu]
|
||||
);
|
||||
|
||||
const handleDeleteWorklow = useCallback(
|
||||
(e?: MouseEvent<HTMLButtonElement>) => {
|
||||
e?.stopPropagation();
|
||||
setIsHovered(false);
|
||||
deleteWorkflow(workflow.workflow_id);
|
||||
deleteConfirmationDialog.close();
|
||||
},
|
||||
[deleteWorkflow, workflow.workflow_id, deleteConfirmationDialog]
|
||||
);
|
||||
|
||||
const handleClickDelete = useCallback(
|
||||
(e: MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
setIsHovered(false);
|
||||
deleteConfirmationDialog.open();
|
||||
deleteWorkflow(workflow);
|
||||
},
|
||||
[deleteConfirmationDialog]
|
||||
[deleteWorkflow, workflow]
|
||||
);
|
||||
|
||||
const handleClickShare = useCallback(
|
||||
@@ -158,7 +146,6 @@ export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListIte
|
||||
variant="ghost"
|
||||
aria-label={t('workflows.edit')}
|
||||
onClick={handleClickEdit}
|
||||
isLoading={deleteWorkflowResult.isLoading}
|
||||
icon={<PiPencilBold />}
|
||||
/>
|
||||
</Tooltip>
|
||||
@@ -201,7 +188,6 @@ export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListIte
|
||||
variant="ghost"
|
||||
aria-label={t('workflows.delete')}
|
||||
onClick={handleClickDelete}
|
||||
isLoading={deleteWorkflowResult.isLoading}
|
||||
colorScheme="error"
|
||||
icon={<PiTrashBold />}
|
||||
/>
|
||||
@@ -209,17 +195,6 @@ export const WorkflowListItem = ({ workflow }: { workflow: WorkflowRecordListIte
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<ConfirmationAlertDialog
|
||||
isOpen={deleteConfirmationDialog.isOpen}
|
||||
onClose={deleteConfirmationDialog.close}
|
||||
title={t('workflows.deleteWorkflow')}
|
||||
acceptCallback={handleDeleteWorklow}
|
||||
acceptButtonText={t('common.delete')}
|
||||
cancelButtonText={t('common.cancel')}
|
||||
useInert={false}
|
||||
>
|
||||
<p>{t('workflows.deleteWorkflow2')}</p>
|
||||
</ConfirmationAlertDialog>
|
||||
<CopyWorkflowLinkModal
|
||||
isOpen={copyWorkflowLinkModal.isOpen}
|
||||
onClose={copyWorkflowLinkModal.close}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { ConfirmationAlertDialog, Text } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import { atom } from 'nanostores';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDeleteWorkflowMutation, workflowsApi } from 'services/api/endpoints/workflows';
|
||||
import type { WorkflowRecordListItemDTO } from 'services/api/types';
|
||||
|
||||
const $workflowToDelete = atom<WorkflowRecordListItemDTO | null>(null);
|
||||
const clearWorkflowToDelete = () => $workflowToDelete.set(null);
|
||||
|
||||
export const useDeleteWorkflow = () => {
|
||||
const deleteWorkflow = useCallback((workflow: WorkflowRecordListItemDTO) => {
|
||||
$workflowToDelete.set(workflow);
|
||||
}, []);
|
||||
|
||||
return deleteWorkflow;
|
||||
};
|
||||
|
||||
export const DeleteWorkflowDialog = () => {
|
||||
const { t } = useTranslation();
|
||||
const workflowToDelete = useStore($workflowToDelete);
|
||||
const [_deleteWorkflow] = useDeleteWorkflowMutation();
|
||||
|
||||
const deleteWorkflow = useCallback(async () => {
|
||||
if (!workflowToDelete) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await _deleteWorkflow(workflowToDelete.workflow_id).unwrap();
|
||||
toast({
|
||||
id: 'WORKFLOW_DELETED',
|
||||
title: t('toast.workflowDeleted'),
|
||||
});
|
||||
} catch {
|
||||
toast({
|
||||
id: `AUTH_ERROR_TOAST_${workflowsApi.endpoints.deleteWorkflow.name}`,
|
||||
title: t('toast.problemDeletingWorkflow'),
|
||||
status: 'error',
|
||||
});
|
||||
}
|
||||
}, [_deleteWorkflow, t, workflowToDelete]);
|
||||
|
||||
return (
|
||||
<ConfirmationAlertDialog
|
||||
isOpen={workflowToDelete !== null}
|
||||
onClose={clearWorkflowToDelete}
|
||||
title={t('workflows.deleteWorkflow')}
|
||||
acceptCallback={deleteWorkflow}
|
||||
acceptButtonText={t('common.delete')}
|
||||
cancelButtonText={t('common.cancel')}
|
||||
useInert={false}
|
||||
>
|
||||
<Text>{t('workflows.deleteWorkflow2')}</Text>
|
||||
</ConfirmationAlertDialog>
|
||||
);
|
||||
};
|
||||
@@ -1,44 +0,0 @@
|
||||
import { toast } from 'features/toast/toast';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDeleteWorkflowMutation, workflowsApi } from 'services/api/endpoints/workflows';
|
||||
|
||||
type UseDeleteLibraryWorkflowOptions = {
|
||||
onSuccess?: () => void;
|
||||
onError?: () => void;
|
||||
};
|
||||
|
||||
type UseDeleteLibraryWorkflowReturn = {
|
||||
deleteWorkflow: (workflow_id: string) => Promise<void>;
|
||||
deleteWorkflowResult: ReturnType<typeof useDeleteWorkflowMutation>[1];
|
||||
};
|
||||
|
||||
type UseDeleteLibraryWorkflow = (arg: UseDeleteLibraryWorkflowOptions) => UseDeleteLibraryWorkflowReturn;
|
||||
|
||||
export const useDeleteLibraryWorkflow: UseDeleteLibraryWorkflow = ({ onSuccess, onError }) => {
|
||||
const { t } = useTranslation();
|
||||
const [_deleteWorkflow, deleteWorkflowResult] = useDeleteWorkflowMutation();
|
||||
|
||||
const deleteWorkflow = useCallback(
|
||||
async (workflow_id: string) => {
|
||||
try {
|
||||
await _deleteWorkflow(workflow_id).unwrap();
|
||||
toast({
|
||||
id: 'WORKFLOW_DELETED',
|
||||
title: t('toast.workflowDeleted'),
|
||||
});
|
||||
onSuccess && onSuccess();
|
||||
} catch {
|
||||
toast({
|
||||
id: `AUTH_ERROR_TOAST_${workflowsApi.endpoints.deleteWorkflow.name}`,
|
||||
title: t('toast.problemDeletingWorkflow'),
|
||||
status: 'error',
|
||||
});
|
||||
onError && onError();
|
||||
}
|
||||
},
|
||||
[_deleteWorkflow, t, onSuccess, onError]
|
||||
);
|
||||
|
||||
return { deleteWorkflow, deleteWorkflowResult };
|
||||
};
|
||||
Reference in New Issue
Block a user