Skip to content

Commit 2496ac1

Browse files
Attila Csehpsychedelicious
authored andcommitted
remove input field from form
1 parent e34ed19 commit 2496ac1

File tree

6 files changed

+71
-42
lines changed

6 files changed

+71
-42
lines changed

invokeai/frontend/web/public/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,7 @@
19501950
"zoomToNode": "Zoom to Node",
19511951
"nodeFieldTooltip": "To add a node field, click the small plus sign button on the field in the Workflow Editor, or drag the field by its name into the form.",
19521952
"addToForm": "Add to Form",
1953+
"removeFromForm": "Remove from Form",
19531954
"label": "Label",
19541955
"showDescription": "Show Description",
19551956
"showShuffle": "Show Shuffle",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { IconButton } from '@invoke-ai/ui-library';
2+
import { useAddRemoveFormElement } from 'features/nodes/components/sidePanel/builder/use-add-remove-form-element';
3+
import { memo, useCallback, useMemo } from 'react';
4+
import { useTranslation } from 'react-i18next';
5+
import { PiMinusBold, PiPlusBold } from 'react-icons/pi';
6+
7+
type Props = {
8+
nodeId: string;
9+
fieldName: string;
10+
};
11+
12+
export const InputFieldAddRemoveFormRoot = memo(({ nodeId, fieldName }: Props) => {
13+
const { t } = useTranslation();
14+
const { isAddedToRoot, addNodeFieldToRoot, removeNodeFieldFromRoot } = useAddRemoveFormElement(nodeId, fieldName);
15+
16+
const description = useMemo(() => {
17+
return isAddedToRoot ? t('workflows.builder.removeFromForm') : t('workflows.builder.addToForm');
18+
}, [isAddedToRoot, t]);
19+
20+
const icon = useMemo(() => {
21+
return isAddedToRoot ? <PiMinusBold /> : <PiPlusBold />;
22+
}, [isAddedToRoot]);
23+
24+
const onClick = useCallback(() => {
25+
return isAddedToRoot ? removeNodeFieldFromRoot() : addNodeFieldToRoot();
26+
}, [isAddedToRoot, addNodeFieldToRoot, removeNodeFieldFromRoot]);
27+
28+
return (
29+
<IconButton
30+
variant="ghost"
31+
tooltip={description}
32+
aria-label={description}
33+
icon={icon}
34+
pointerEvents="auto"
35+
size="xs"
36+
onClick={onClick}
37+
/>
38+
);
39+
});
40+
41+
InputFieldAddRemoveFormRoot.displayName = 'InputFieldAddRemoveFormRoot';

invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/InputFieldAddToFormRoot.tsx

Lines changed: 0 additions & 30 deletions
This file was deleted.

invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/InputFieldEditModeNodes.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { SystemStyleObject } from '@invoke-ai/ui-library';
22
import { Flex, Spacer } from '@invoke-ai/ui-library';
3-
import { InputFieldAddToFormRoot } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldAddToFormRoot';
43
import { InputFieldDescriptionPopover } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldDescriptionPopover';
54
import { InputFieldHandle } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldHandle';
65
import { InputFieldResetToDefaultValueIconButton } from 'features/nodes/components/flow/nodes/Invocation/fields/InputFieldResetToDefaultValueIconButton';
@@ -12,6 +11,7 @@ import { NO_DRAG_CLASS } from 'features/nodes/types/constants';
1211
import type { FieldInputTemplate } from 'features/nodes/types/field';
1312
import { memo, useRef } from 'react';
1413

14+
import { InputFieldAddRemoveFormRoot } from './InputFieldAddRemoveFormRoot';
1515
import { InputFieldRenderer } from './InputFieldRenderer';
1616
import { InputFieldTitle } from './InputFieldTitle';
1717
import { InputFieldWrapper } from './InputFieldWrapper';
@@ -113,7 +113,7 @@ const DirectField = memo(({ nodeId, fieldName, isInvalid, isConnected, fieldTemp
113113
<Flex className="direct-field-action-buttons">
114114
<InputFieldDescriptionPopover nodeId={nodeId} fieldName={fieldName} />
115115
<InputFieldResetToDefaultValueIconButton nodeId={nodeId} fieldName={fieldName} />
116-
<InputFieldAddToFormRoot nodeId={nodeId} fieldName={fieldName} />
116+
<InputFieldAddRemoveFormRoot nodeId={nodeId} fieldName={fieldName} />
117117
</Flex>
118118
</Flex>
119119
<InputFieldRenderer nodeId={nodeId} fieldName={fieldName} />
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
22
import { useInputFieldInstance } from 'features/nodes/hooks/useInputFieldInstance';
33
import { useInputFieldTemplateOrThrow } from 'features/nodes/hooks/useInputFieldTemplateOrThrow';
4-
import { formElementAdded } from 'features/nodes/store/nodesSlice';
5-
import { buildSelectWorkflowFormNodeExists, selectFormRootElementId } from 'features/nodes/store/selectors';
4+
import { formElementAdded, formElementRemoved } from 'features/nodes/store/nodesSlice';
5+
import { buildSelectWorkflowFormNodeElement, selectFormRootElementId } from 'features/nodes/store/selectors';
66
import { buildNodeFieldElement } from 'features/nodes/types/workflow';
77
import { useCallback, useMemo } from 'react';
88

9-
export const useAddNodeFieldToRoot = (nodeId: string, fieldName: string) => {
9+
export const useAddRemoveFormElement = (nodeId: string, fieldName: string) => {
1010
const dispatch = useAppDispatch();
1111
const rootElementId = useAppSelector(selectFormRootElementId);
1212
const fieldTemplate = useInputFieldTemplateOrThrow(fieldName);
1313
const field = useInputFieldInstance(fieldName);
14-
const selectWorkflowFormNodeExists = useMemo(
15-
() => buildSelectWorkflowFormNodeExists(nodeId, fieldName),
14+
const selectWorkflowFormNodeElement = useMemo(
15+
() => buildSelectWorkflowFormNodeElement(nodeId, fieldName),
1616
[nodeId, fieldName]
1717
);
18-
const isAddedToRoot = useAppSelector(selectWorkflowFormNodeExists);
18+
const workflowFormNodeElement = useAppSelector(selectWorkflowFormNodeElement);
19+
const isAddedToRoot = useMemo(() => {
20+
return !!workflowFormNodeElement;
21+
}, [workflowFormNodeElement]);
1922

2023
const addNodeFieldToRoot = useCallback(() => {
2124
const element = buildNodeFieldElement(nodeId, fieldName, fieldTemplate.type);
@@ -28,5 +31,16 @@ export const useAddNodeFieldToRoot = (nodeId: string, fieldName: string) => {
2831
);
2932
}, [nodeId, fieldName, fieldTemplate.type, dispatch, rootElementId, field.value]);
3033

31-
return { isAddedToRoot, addNodeFieldToRoot };
34+
const removeNodeFieldFromRoot = useCallback(() => {
35+
if (!workflowFormNodeElement) {
36+
return;
37+
}
38+
dispatch(
39+
formElementRemoved({
40+
id: workflowFormNodeElement.id,
41+
})
42+
);
43+
}, [workflowFormNodeElement, dispatch]);
44+
45+
return { isAddedToRoot, addNodeFieldToRoot, removeNodeFieldFromRoot };
3246
};

invokeai/frontend/web/src/features/nodes/store/selectors.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ export const selectWorkflowFormNodeFieldFieldIdentifiersDeduped = createSelector
103103
);
104104

105105
export const buildSelectElement = (id: string) => createNodesSelector((workflow) => workflow.form?.elements[id]);
106-
export const buildSelectWorkflowFormNodeExists = (nodeId: string, fieldName: string) =>
107-
createSelector(selectWorkflowFormNodeFieldFieldIdentifiersDeduped, (identifiers) =>
108-
identifiers.some((identifier) => identifier.nodeId === nodeId && identifier.fieldName === fieldName)
106+
export const buildSelectWorkflowFormNodeElement = (nodeId: string, fieldName: string) =>
107+
createSelector(selectNodeFieldElements, (elements) =>
108+
elements.find(
109+
(element) =>
110+
element.data.fieldIdentifier.nodeId === nodeId && element.data.fieldIdentifier.fieldName === fieldName
111+
)
109112
);

0 commit comments

Comments
 (0)