Add Clear nodes Button (#3747)

Adds a Clear Nodes Button with Confirmation Dialog, I think I Did it
right 😃

I am sure there is a way to make the Confirmation look better and have
Yes/No instead of OK/Cancel
This commit is contained in:
blessedcoolant 2023-07-13 20:35:40 +12:00 committed by GitHub
commit fde9fa2fe4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 103 additions and 3 deletions

View File

@ -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"
}
}

View File

@ -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 = () => {
<ReloadSchemaButton />
<SaveNodesButton />
<LoadNodesButton />
<ClearNodesButton />
</HStack>
</Panel>
);

View File

@ -0,0 +1,86 @@
import {
AlertDialog,
AlertDialogBody,
AlertDialogContent,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogOverlay,
Button,
Text,
useDisclosure,
} from '@chakra-ui/react';
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, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { FaTrash } from 'react-icons/fa';
const ClearNodesButton = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const { isOpen, onOpen, onClose } = useDisclosure();
const cancelRef = useRef<HTMLButtonElement | null>(null);
const nodes = useAppSelector((state: RootState) => state.nodes.nodes);
const handleConfirmClear = () => {
dispatch(clearNodes());
dispatch(
addToast(
makeToast({
title: t('toast.nodesCleared'),
status: 'success',
})
)
);
onClose();
};
return (
<>
<IAIIconButton
icon={<FaTrash />}
tooltip={t('nodes.clearNodes')}
aria-label={t('nodes.clearNodes')}
onClick={onOpen}
isDisabled={nodes.length === 0}
/>
<AlertDialog
isOpen={isOpen}
onClose={onClose}
leastDestructiveRef={cancelRef}
isCentered
>
<AlertDialogOverlay />
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
{t('nodes.clearNodes')}
</AlertDialogHeader>
<AlertDialogBody>
<Text>{t('common.clearNodes')}</Text>
</AlertDialogBody>
<AlertDialogFooter>
<Button ref={cancelRef} onClick={onClose}>
{t('common.cancel')}
</Button>
<Button colorScheme="red" ml={3} onClick={handleConfirmClear}>
{t('common.accept')}
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
);
};
export default memo(ClearNodesButton);

View File

@ -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}
/>
);
};

View File

@ -133,6 +133,10 @@ const nodesSlice = createSlice({
loadFileEdges: (state, action: PayloadAction<Edge[]>) => {
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;