mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui): change reset button to menu
This commit is contained in:
@@ -1709,7 +1709,8 @@
|
||||
"delete": "Delete",
|
||||
"openLibrary": "Open Library",
|
||||
"builder": {
|
||||
"resetForm": "Reset Form",
|
||||
"deleteAllElements": "Delete All Form Elements",
|
||||
"resetAllNodeFields": "Reset All Node Fields",
|
||||
"builder": "Form Builder",
|
||||
"layout": "Layout",
|
||||
"row": "Row",
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
||||
import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
||||
import { Button, ButtonGroup, Flex, Spacer } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import { firefoxDndFix } from 'features/dnd/util';
|
||||
import { FormElementComponent } from 'features/nodes/components/sidePanel/builder/ContainerElementComponent';
|
||||
import { buildFormElementDndData, useBuilderDndMonitor } from 'features/nodes/components/sidePanel/builder/dnd-hooks';
|
||||
import { formReset, selectFormRootElementId } from 'features/nodes/store/workflowSlice';
|
||||
import { WorkflowBuilderEditMenu } from 'features/nodes/components/sidePanel/builder/WorkflowBuilderMenu';
|
||||
import { selectFormRootElementId } from 'features/nodes/store/workflowSlice';
|
||||
import type { FormElement } from 'features/nodes/types/workflow';
|
||||
import { buildContainer, buildDivider, buildHeading, buildText } from 'features/nodes/types/workflow';
|
||||
import { startCase } from 'lodash-es';
|
||||
import type { RefObject } from 'react';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiArrowCounterClockwiseBold } from 'react-icons/pi';
|
||||
import { memo, useEffect, useRef, useState } from 'react';
|
||||
import { assert } from 'tsafe';
|
||||
|
||||
export const WorkflowBuilder = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const rootElementId = useAppSelector(selectFormRootElementId);
|
||||
useBuilderDndMonitor();
|
||||
|
||||
const resetForm = useCallback(() => {
|
||||
dispatch(formReset());
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<Flex justifyContent="center" w="full" h="full">
|
||||
<Flex flexDir="column" w="full" maxW="768px" gap={2}>
|
||||
@@ -35,9 +28,7 @@ export const WorkflowBuilder = memo(() => {
|
||||
<AddFormElementDndButton type="heading" />
|
||||
<AddFormElementDndButton type="text" />
|
||||
<Spacer />
|
||||
<Button onClick={resetForm} variant="ghost" leftIcon={<PiArrowCounterClockwiseBold />}>
|
||||
{t('workflows.builder.resetForm')}
|
||||
</Button>
|
||||
<WorkflowBuilderEditMenu />
|
||||
</ButtonGroup>
|
||||
<ScrollableContent>
|
||||
<Flex>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { IconButton, Menu, MenuButton, MenuItem, MenuList } from '@invoke-ai/ui-library';
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { useResetAllNodeFields } from 'features/nodes/components/sidePanel/builder/use-reset-all-node-fields';
|
||||
import { formReset } from 'features/nodes/store/workflowSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiArrowCounterClockwiseBold, PiDotsThreeBold, PiTrashBold } from 'react-icons/pi';
|
||||
|
||||
export const WorkflowBuilderEditMenu = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const store = useAppStore();
|
||||
const resetAllNodeFields = useResetAllNodeFields();
|
||||
const deleteAllElements = useCallback(() => {
|
||||
store.dispatch(formReset());
|
||||
}, [store]);
|
||||
return (
|
||||
<Menu placement="bottom-end">
|
||||
<MenuButton as={IconButton} icon={<PiDotsThreeBold />} variant="ghost" />
|
||||
<MenuList>
|
||||
<MenuItem icon={<PiArrowCounterClockwiseBold />} onClick={resetAllNodeFields}>
|
||||
{t('workflows.builder.resetAllNodeFields')}
|
||||
</MenuItem>
|
||||
<MenuItem isDestructive icon={<PiTrashBold />} onClick={deleteAllElements}>
|
||||
{t('workflows.builder.deleteAllElements')}
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
);
|
||||
});
|
||||
WorkflowBuilderEditMenu.displayName = 'WorkflowBuilderEditMenu';
|
||||
@@ -0,0 +1,20 @@
|
||||
import { useAppStore } from 'app/store/nanostores/store';
|
||||
import { fieldValueReset } from 'features/nodes/store/nodesSlice';
|
||||
import { selectFormInitialValues, selectNodeFieldElements } from 'features/nodes/store/workflowSlice';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export const useResetAllNodeFields = () => {
|
||||
const store = useAppStore();
|
||||
const resetAllNodeValuesToDefaults = useCallback(() => {
|
||||
const allInitialValues = selectFormInitialValues(store.getState());
|
||||
const nodeFieldElements = selectNodeFieldElements(store.getState());
|
||||
for (const element of nodeFieldElements) {
|
||||
if (!(element.id in allInitialValues)) {
|
||||
continue;
|
||||
}
|
||||
const { nodeId, fieldName } = element.data.fieldIdentifier;
|
||||
store.dispatch(fieldValueReset({ nodeId, fieldName, value: allInitialValues[element.id] }));
|
||||
}
|
||||
}, [store]);
|
||||
return resetAllNodeValuesToDefaults;
|
||||
};
|
||||
@@ -369,6 +369,10 @@ export const selectIsFormEmpty = createWorkflowSelector((workflow) => {
|
||||
}
|
||||
return rootElement.data.children.length === 0;
|
||||
});
|
||||
export const selectFormInitialValues = createWorkflowSelector((workflow) => workflow.formFieldInitialValues);
|
||||
export const selectNodeFieldElements = createWorkflowSelector((workflow) =>
|
||||
Object.values(workflow.form.elements).filter(isNodeFieldElement)
|
||||
);
|
||||
const buildSelectElement = (id: string) => createWorkflowSelector((workflow) => workflow.form?.elements[id]);
|
||||
export const useElement = (id: string): FormElement | undefined => {
|
||||
const selector = useMemo(() => buildSelectElement(id), [id]);
|
||||
|
||||
Reference in New Issue
Block a user