From c7dcf1f4a00e8491f6cf2f9be0a9330b5c8e32b0 Mon Sep 17 00:00:00 2001
From: mickr777 <115216705+mickr777@users.noreply.github.com>
Date: Thu, 13 Jul 2023 14:40:09 +1000
Subject: [PATCH 1/7] Create ClearNodesButton.tsx
---
.../nodes/components/ui/ClearNodesButton.tsx | 41 +++++++++++++++++++
1 file changed, 41 insertions(+)
create mode 100644 invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
new file mode 100644
index 0000000000..f9824268b9
--- /dev/null
+++ b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
@@ -0,0 +1,41 @@
+import { useAppDispatch } from 'app/store/storeHooks';
+import { clearNodes } from 'features/nodes/store/nodesSlice';
+import { makeToast } from 'app/components/Toaster';
+import { addToast } from 'features/system/store/systemSlice';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { FaTrash } from 'react-icons/fa';
+import IAIIconButton from 'common/components/IAIIconButton';
+
+const ClearNodesButton = () => {
+ const { t } = useTranslation();
+ const dispatch = useAppDispatch();
+
+ const handleClearNodes = () => {
+ const confirmed = window.confirm(t('common.clearNodes'));
+
+ if (confirmed) {
+ dispatch(clearNodes());
+
+ dispatch(
+ addToast(
+ makeToast({
+ title: t('toast.nodesCleared'),
+ status: 'success',
+ })
+ )
+ );
+ }
+ };
+
+ return (
+ }
+ tooltip={t('nodes.clearNodes')}
+ aria-label={t('nodes.clearNodes')}
+ onClick={handleClearNodes}
+ />
+ );
+};
+
+export default memo(ClearNodesButton);
From 99c1d5c044d542a7b7c980f954be1af05c75b75c Mon Sep 17 00:00:00 2001
From: mickr777 <115216705+mickr777@users.noreply.github.com>
Date: Thu, 13 Jul 2023 14:40:33 +1000
Subject: [PATCH 2/7] Update nodesSlice.ts
---
invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts
index 094a43b944..b2825db783 100644
--- a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts
+++ b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts
@@ -133,6 +133,10 @@ const nodesSlice = createSlice({
loadFileEdges: (state, action: PayloadAction) => {
state.edges = action.payload;
},
+ clearNodes: (state) => {
+ state.nodes = [];
+ state.edges = [];
+ },
},
extraReducers: (builder) => {
builder.addCase(receivedOpenAPISchema.fulfilled, (state, action) => {
@@ -156,6 +160,7 @@ export const {
setEditorInstance,
loadFileNodes,
loadFileEdges,
+ clearNodes,
} = nodesSlice.actions;
export default nodesSlice.reducer;
From 90441c425709bb327fa5d22a684e602fec506db5 Mon Sep 17 00:00:00 2001
From: mickr777 <115216705+mickr777@users.noreply.github.com>
Date: Thu, 13 Jul 2023 14:41:00 +1000
Subject: [PATCH 3/7] Update TopCenterPanel.tsx
---
.../web/src/features/nodes/components/panels/TopCenterPanel.tsx | 2 ++
1 file changed, 2 insertions(+)
diff --git a/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx b/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx
index 10e59f2af9..90f8039285 100644
--- a/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/panels/TopCenterPanel.tsx
@@ -6,6 +6,7 @@ import LoadNodesButton from '../ui/LoadNodesButton';
import NodeInvokeButton from '../ui/NodeInvokeButton';
import ReloadSchemaButton from '../ui/ReloadSchemaButton';
import SaveNodesButton from '../ui/SaveNodesButton';
+import ClearNodesButton from '../ui/ClearNodesButton';
const TopCenterPanel = () => {
return (
@@ -16,6 +17,7 @@ const TopCenterPanel = () => {
+
);
From 8a25e22fb0b60e651f8b7463270c3d51a7fc1a08 Mon Sep 17 00:00:00 2001
From: mickr777 <115216705+mickr777@users.noreply.github.com>
Date: Thu, 13 Jul 2023 14:42:09 +1000
Subject: [PATCH 4/7] Update en.json
---
invokeai/frontend/web/public/locales/en.json | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index b198f27160..a6a516c380 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -102,7 +102,8 @@
"openInNewTab": "Open in New Tab",
"dontAskMeAgain": "Don't ask me again",
"areYouSure": "Are you sure?",
- "imagePrompt": "Image Prompt"
+ "imagePrompt": "Image Prompt",
+ "clearNodes": "Are you sure you want to clear all nodes?"
},
"gallery": {
"generations": "Generations",
@@ -596,7 +597,9 @@
"initialImageNotSetDesc": "Could not load initial image",
"nodesSaved": "Nodes Saved",
"nodesLoaded": "Nodes Loaded",
- "nodesLoadedFailed": "Failed To Load Nodes"
+ "nodesLoadedFailed": "Failed To Load Nodes",
+ "nodesCleared": "Nodes Cleared"
+
},
"tooltip": {
"feature": {
@@ -681,6 +684,7 @@
"nodes": {
"reloadSchema": "Reload Schema",
"saveNodes": "Save Nodes",
- "loadNodes": "Load Nodes"
+ "loadNodes": "Load Nodes",
+ "clearNodes": "Clear Nodes"
}
}
From d1ac50b0619a58b269430a7423b3b6d3e0681a1e Mon Sep 17 00:00:00 2001
From: mickr777 <115216705+mickr777@users.noreply.github.com>
Date: Thu, 13 Jul 2023 17:19:59 +1000
Subject: [PATCH 5/7] Change Confirmation Dialog
Changed Confirmation Dialog to use chakra-ui alert dialog
---
.../nodes/components/ui/ClearNodesButton.tsx | 85 +++++++++++++++----
1 file changed, 67 insertions(+), 18 deletions(-)
diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
index f9824268b9..29e8ca3a20 100644
--- a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
@@ -1,3 +1,15 @@
+import { useState } from 'react';
+import {
+ AlertDialog,
+ AlertDialogBody,
+ AlertDialogContent,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogOverlay,
+ Divider,
+ Text,
+ Button,
+} from '@chakra-ui/react';
import { useAppDispatch } from 'app/store/storeHooks';
import { clearNodes } from 'features/nodes/store/nodesSlice';
import { makeToast } from 'app/components/Toaster';
@@ -10,31 +22,68 @@ import IAIIconButton from 'common/components/IAIIconButton';
const ClearNodesButton = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
const handleClearNodes = () => {
- const confirmed = window.confirm(t('common.clearNodes'));
+ setIsDialogOpen(true);
+ };
- if (confirmed) {
- dispatch(clearNodes());
+ const handleConfirmClear = () => {
+ dispatch(clearNodes());
- dispatch(
- addToast(
- makeToast({
- title: t('toast.nodesCleared'),
- status: 'success',
- })
- )
- );
- }
+ dispatch(
+ addToast(
+ makeToast({
+ title: t('toast.nodesCleared'),
+ status: 'success',
+ })
+ )
+ );
+
+ setIsDialogOpen(false);
+ };
+
+ const handleCancelClear = () => {
+ setIsDialogOpen(false);
};
return (
- }
- tooltip={t('nodes.clearNodes')}
- aria-label={t('nodes.clearNodes')}
- onClick={handleClearNodes}
- />
+ <>
+ }
+ tooltip={t('nodes.clearNodes')}
+ aria-label={t('nodes.clearNodes')}
+ onClick={handleClearNodes}
+ />
+
+
+
+
+
+
+ {t('nodes.clearNodes')}
+
+
+
+ {t('common.clearNodes')}
+
+
+
+
+
+
+
+
+
+
+ >
);
};
From 91c4e4c9b98ed9a3f765987ab58b25451ae3a1d9 Mon Sep 17 00:00:00 2001
From: mickr777 <115216705+mickr777@users.noreply.github.com>
Date: Thu, 13 Jul 2023 18:08:30 +1000
Subject: [PATCH 6/7] useDisclosure instead of useState.
---
.../nodes/components/ui/ClearNodesButton.tsx | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
index 29e8ca3a20..78f3e2af2b 100644
--- a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useDisclosure } from '@chakra-ui/react';
import {
AlertDialog,
AlertDialogBody,
@@ -22,10 +22,10 @@ import IAIIconButton from 'common/components/IAIIconButton';
const ClearNodesButton = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
- const [isDialogOpen, setIsDialogOpen] = useState(false);
+ const { isOpen, onOpen, onClose } = useDisclosure();
const handleClearNodes = () => {
- setIsDialogOpen(true);
+ onOpen();
};
const handleConfirmClear = () => {
@@ -40,11 +40,11 @@ const ClearNodesButton = () => {
)
);
- setIsDialogOpen(false);
+ onClose();
};
const handleCancelClear = () => {
- setIsDialogOpen(false);
+ onClose();
};
return (
@@ -56,12 +56,7 @@ const ClearNodesButton = () => {
onClick={handleClearNodes}
/>
-
+
From 686149969714296196c692e79d36a86be07556d5 Mon Sep 17 00:00:00 2001
From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com>
Date: Thu, 13 Jul 2023 20:34:23 +1200
Subject: [PATCH 7/7] fix: Simplify modal code
---
.../nodes/components/ui/ClearNodesButton.tsx | 39 ++++++++++---------
.../nodes/components/ui/SaveNodesButton.tsx | 3 ++
2 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
index 78f3e2af2b..22845dd362 100644
--- a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx
@@ -1,4 +1,3 @@
-import { useDisclosure } from '@chakra-ui/react';
import {
AlertDialog,
AlertDialogBody,
@@ -6,27 +5,27 @@ import {
AlertDialogFooter,
AlertDialogHeader,
AlertDialogOverlay,
- Divider,
- Text,
Button,
+ Text,
+ useDisclosure,
} from '@chakra-ui/react';
-import { useAppDispatch } from 'app/store/storeHooks';
-import { clearNodes } from 'features/nodes/store/nodesSlice';
import { makeToast } from 'app/components/Toaster';
+import { RootState } from 'app/store/store';
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import IAIIconButton from 'common/components/IAIIconButton';
+import { clearNodes } from 'features/nodes/store/nodesSlice';
import { addToast } from 'features/system/store/systemSlice';
-import { memo } from 'react';
+import { memo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { FaTrash } from 'react-icons/fa';
-import IAIIconButton from 'common/components/IAIIconButton';
const ClearNodesButton = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const { isOpen, onOpen, onClose } = useDisclosure();
+ const cancelRef = useRef(null);
- const handleClearNodes = () => {
- onOpen();
- };
+ const nodes = useAppSelector((state: RootState) => state.nodes.nodes);
const handleConfirmClear = () => {
dispatch(clearNodes());
@@ -43,20 +42,22 @@ const ClearNodesButton = () => {
onClose();
};
- const handleCancelClear = () => {
- onClose();
- };
-
return (
<>
}
tooltip={t('nodes.clearNodes')}
aria-label={t('nodes.clearNodes')}
- onClick={handleClearNodes}
+ onClick={onOpen}
+ isDisabled={nodes.length === 0}
/>
-
+
@@ -68,10 +69,10 @@ const ClearNodesButton = () => {
{t('common.clearNodes')}
-
-
-
+
diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/SaveNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/SaveNodesButton.tsx
index 14bf0a1ce8..5833182456 100644
--- a/invokeai/frontend/web/src/features/nodes/components/ui/SaveNodesButton.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/ui/SaveNodesButton.tsx
@@ -12,6 +12,8 @@ const SaveNodesButton = () => {
(state: RootState) => state.nodes.editorInstance
);
+ const nodes = useAppSelector((state: RootState) => state.nodes.nodes);
+
const saveEditorToJSON = useCallback(() => {
if (editorInstance) {
const editorState = editorInstance.toObject();
@@ -38,6 +40,7 @@ const SaveNodesButton = () => {
tooltip={t('nodes.saveNodes')}
aria-label={t('nodes.saveNodes')}
onClick={saveEditorToJSON}
+ isDisabled={nodes.length === 0}
/>
);
};