diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx index bed26baee4..9e66befd3e 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeHeader.tsx @@ -52,17 +52,15 @@ export const FormElementEditModeHeader = memo( {isContainerElement(element) && } {isNodeFieldElement(element) && } - {element.parentId && ( - } - variant="link" - size="sm" - alignSelf="stretch" - colorScheme="error" - /> - )} + } + variant="link" + size="sm" + alignSelf="stretch" + colorScheme="error" + /> ); }) diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeWrapper.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeWrapper.tsx index 33efa54e07..27f717f7c3 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeWrapper.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/FormElementEditModeWrapper.tsx @@ -64,7 +64,7 @@ export const FormElementEditModeWrapper = memo(({ element, children }: PropsWith data-layout={containerCtx?.layout} > - + {children} diff --git a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx index e07eb0fdfb..2a408b65f5 100644 --- a/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/sidePanel/builder/WorkflowBuilder.tsx @@ -1,6 +1,6 @@ import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine'; import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter'; -import { Button, ButtonGroup, Flex } from '@invoke-ai/ui-library'; +import { Button, ButtonGroup, Flex, Text } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent'; import { firefoxDndFix } from 'features/dnd/util'; @@ -24,7 +24,7 @@ export const WorkflowBuilder = memo(() => { return ( - + @@ -35,14 +35,43 @@ export const WorkflowBuilder = memo(() => { {rootElementId && } + {!rootElementId && } ); }); - WorkflowBuilder.displayName = 'WorkflowBuilder'; +const EmptyState = memo(() => { + const mode = useAppSelector(selectWorkflowFormMode); + const dispatch = useAppDispatch(); + + const toggleMode = useCallback(() => { + dispatch(formModeToggled()); + }, [dispatch]); + + const addContainer = useCallback(() => {}, []); + + if (mode === 'view') { + return ( + + + Click Edit to build a form for this workflow. + + + + ); + } + + + + No form elements added. Click a button above to add a form element. + + ; +}); +EmptyState.displayName = 'EmptyState'; + const ToggleModeButton = memo(() => { const dispatch = useAppDispatch(); const mode = useAppSelector(selectWorkflowFormMode); @@ -57,7 +86,8 @@ ToggleModeButton.displayName = 'ToggleModeButton'; const useAddFormElementDnd = ( type: Exclude | 'row' | 'column', - draggableRef: RefObject + draggableRef: RefObject, + isEnabled = true ) => { const [isDragging, setIsDragging] = useState(false); @@ -70,6 +100,7 @@ const useAddFormElementDnd = ( firefoxDndFix(draggableElement), draggable({ element: draggableElement, + canDrag: () => isEnabled, getInitialData: () => { if (type === 'row') { const element = buildContainer('row', []); @@ -101,17 +132,29 @@ const useAddFormElementDnd = ( }, }) ); - }, [draggableRef, type]); + }, [draggableRef, isEnabled, type]); return isDragging; }; const AddFormElementDndButton = ({ type }: { type: Parameters[0] }) => { - const draggableRef = useRef(null); + const draggableRef = useRef(null); + const rootElementId = useAppSelector(selectRootElementId); const isDragging = useAddFormElementDnd(type, draggableRef); return ( - ); diff --git a/invokeai/frontend/web/src/features/nodes/store/workflowSlice.ts b/invokeai/frontend/web/src/features/nodes/store/workflowSlice.ts index 2a29c5df79..abaf37c830 100644 --- a/invokeai/frontend/web/src/features/nodes/store/workflowSlice.ts +++ b/invokeai/frontend/web/src/features/nodes/store/workflowSlice.ts @@ -22,7 +22,6 @@ import type { WorkflowV3, } from 'features/nodes/types/workflow'; import { - buildContainer, isContainerElement, isHeadingElement, isNodeFieldElement, @@ -53,7 +52,6 @@ const formElementDataChangedReducer = ( }; const getBlankWorkflow = (): Omit => { - const rootElement = buildContainer('column', []); return { name: '', author: '', @@ -65,12 +63,7 @@ const getBlankWorkflow = (): Omit => { exposedFields: [], meta: { version: '3.0.0', category: 'user' }, id: undefined, - form: { - elements: { - [rootElement.id]: rootElement, - }, - rootElementId: rootElement.id, - }, + form: undefined, }; }; @@ -194,7 +187,11 @@ export const workflowSlice = createSlice({ return; } const { id } = action.payload; - recursivelyRemoveElement({ id, formState: state.form }); + if (id === state.form.rootElementId) { + state.form = undefined; + } else { + recursivelyRemoveElement({ id, formState: state.form }); + } }, formElementMoved: (state, action: PayloadAction<{ id: string; containerId: string; index?: number }>) => { if (!state.form) {