mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): fix workflow loading
- Different handling for loading from library vs external - Fix bug where only nodes and edges loaded
This commit is contained in:
parent
4b2e3aa54d
commit
3863bd9da3
@ -1,7 +1,7 @@
|
|||||||
import { logger } from 'app/logging/logger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { parseify } from 'common/util/serialize';
|
import { parseify } from 'common/util/serialize';
|
||||||
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
import { workflowLoadRequested } from 'features/nodes/store/actions';
|
||||||
import { workflowLoaded } from 'features/nodes/store/nodesSlice';
|
import { workflowLoaded } from 'features/nodes/store/workflowSlice';
|
||||||
import { $flow } from 'features/nodes/store/reactFlowInstance';
|
import { $flow } from 'features/nodes/store/reactFlowInstance';
|
||||||
import {
|
import {
|
||||||
WorkflowMigrationError,
|
WorkflowMigrationError,
|
||||||
@ -21,7 +21,7 @@ export const addWorkflowLoadRequestedListener = () => {
|
|||||||
actionCreator: workflowLoadRequested,
|
actionCreator: workflowLoadRequested,
|
||||||
effect: (action, { dispatch, getState }) => {
|
effect: (action, { dispatch, getState }) => {
|
||||||
const log = logger('nodes');
|
const log = logger('nodes');
|
||||||
const workflow = action.payload;
|
const { workflow, asCopy } = action.payload;
|
||||||
const nodeTemplates = getState().nodes.nodeTemplates;
|
const nodeTemplates = getState().nodes.nodeTemplates;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -29,6 +29,12 @@ export const addWorkflowLoadRequestedListener = () => {
|
|||||||
workflow,
|
workflow,
|
||||||
nodeTemplates
|
nodeTemplates
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (asCopy) {
|
||||||
|
// If we're loading a copy, we need to remove the ID so that the backend will create a new workflow
|
||||||
|
delete validatedWorkflow.id;
|
||||||
|
}
|
||||||
|
|
||||||
dispatch(workflowLoaded(validatedWorkflow));
|
dispatch(workflowLoaded(validatedWorkflow));
|
||||||
if (!warnings.length) {
|
if (!warnings.length) {
|
||||||
dispatch(
|
dispatch(
|
||||||
|
@ -17,9 +17,10 @@ export const isAnyGraphBuilt = isAnyOf(
|
|||||||
nodesGraphBuilt
|
nodesGraphBuilt
|
||||||
);
|
);
|
||||||
|
|
||||||
export const workflowLoadRequested = createAction<unknown>(
|
export const workflowLoadRequested = createAction<{
|
||||||
'nodes/workflowLoadRequested'
|
workflow: unknown;
|
||||||
);
|
asCopy: boolean;
|
||||||
|
}>('nodes/workflowLoadRequested');
|
||||||
|
|
||||||
export const updateAllNodesRequested = createAction(
|
export const updateAllNodesRequested = createAction(
|
||||||
'nodes/updateAllNodesRequested'
|
'nodes/updateAllNodesRequested'
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||||
|
import { workflowLoaded } from 'features/nodes/store/workflowSlice';
|
||||||
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
import { SHARED_NODE_PROPERTIES } from 'features/nodes/types/constants';
|
||||||
import {
|
import {
|
||||||
BoardFieldValue,
|
BoardFieldValue,
|
||||||
@ -28,7 +29,6 @@ import {
|
|||||||
NodeExecutionState,
|
NodeExecutionState,
|
||||||
zNodeStatus,
|
zNodeStatus,
|
||||||
} from 'features/nodes/types/invocation';
|
} from 'features/nodes/types/invocation';
|
||||||
import { WorkflowV2 } from 'features/nodes/types/workflow';
|
|
||||||
import { cloneDeep, forEach } from 'lodash-es';
|
import { cloneDeep, forEach } from 'lodash-es';
|
||||||
import {
|
import {
|
||||||
addEdge,
|
addEdge,
|
||||||
@ -654,30 +654,6 @@ const nodesSlice = createSlice({
|
|||||||
nodeOpacityChanged: (state, action: PayloadAction<number>) => {
|
nodeOpacityChanged: (state, action: PayloadAction<number>) => {
|
||||||
state.nodeOpacity = action.payload;
|
state.nodeOpacity = action.payload;
|
||||||
},
|
},
|
||||||
workflowLoaded: (state, action: PayloadAction<WorkflowV2>) => {
|
|
||||||
const { nodes, edges } = action.payload;
|
|
||||||
state.nodes = applyNodeChanges(
|
|
||||||
nodes.map((node) => ({
|
|
||||||
item: { ...node, ...SHARED_NODE_PROPERTIES },
|
|
||||||
type: 'add',
|
|
||||||
})),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
state.edges = applyEdgeChanges(
|
|
||||||
edges.map((edge) => ({ item: edge, type: 'add' })),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
state.nodeExecutionStates = nodes.reduce<
|
|
||||||
Record<string, NodeExecutionState>
|
|
||||||
>((acc, node) => {
|
|
||||||
acc[node.id] = {
|
|
||||||
nodeId: node.id,
|
|
||||||
...initialNodeExecutionState,
|
|
||||||
};
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
},
|
|
||||||
viewportChanged: (state, action: PayloadAction<Viewport>) => {
|
viewportChanged: (state, action: PayloadAction<Viewport>) => {
|
||||||
state.viewport = action.payload;
|
state.viewport = action.payload;
|
||||||
},
|
},
|
||||||
@ -823,6 +799,32 @@ const nodesSlice = createSlice({
|
|||||||
builder.addCase(receivedOpenAPISchema.pending, (state) => {
|
builder.addCase(receivedOpenAPISchema.pending, (state) => {
|
||||||
state.isReady = false;
|
state.isReady = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.addCase(workflowLoaded, (state, action) => {
|
||||||
|
const { nodes, edges } = action.payload;
|
||||||
|
state.nodes = applyNodeChanges(
|
||||||
|
nodes.map((node) => ({
|
||||||
|
item: { ...node, ...SHARED_NODE_PROPERTIES },
|
||||||
|
type: 'add',
|
||||||
|
})),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
state.edges = applyEdgeChanges(
|
||||||
|
edges.map((edge) => ({ item: edge, type: 'add' })),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
state.nodeExecutionStates = nodes.reduce<
|
||||||
|
Record<string, NodeExecutionState>
|
||||||
|
>((acc, node) => {
|
||||||
|
acc[node.id] = {
|
||||||
|
nodeId: node.id,
|
||||||
|
...initialNodeExecutionState,
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
});
|
||||||
|
|
||||||
builder.addCase(appSocketInvocationStarted, (state, action) => {
|
builder.addCase(appSocketInvocationStarted, (state, action) => {
|
||||||
const { source_node_id } = action.payload.data;
|
const { source_node_id } = action.payload.data;
|
||||||
const node = state.nodeExecutionStates[source_node_id];
|
const node = state.nodeExecutionStates[source_node_id];
|
||||||
@ -931,7 +933,6 @@ export const {
|
|||||||
shouldSnapToGridChanged,
|
shouldSnapToGridChanged,
|
||||||
shouldValidateGraphChanged,
|
shouldValidateGraphChanged,
|
||||||
viewportChanged,
|
viewportChanged,
|
||||||
workflowLoaded,
|
|
||||||
edgeAdded,
|
edgeAdded,
|
||||||
} = nodesSlice.actions;
|
} = nodesSlice.actions;
|
||||||
|
|
||||||
|
@ -34,7 +34,9 @@ export const useGetAndLoadEmbeddedWorkflow: UseGetAndLoadEmbeddedWorkflow = ({
|
|||||||
async (imageName: string) => {
|
async (imageName: string) => {
|
||||||
try {
|
try {
|
||||||
const workflow = await _getAndLoadEmbeddedWorkflow(imageName);
|
const workflow = await _getAndLoadEmbeddedWorkflow(imageName);
|
||||||
dispatch(workflowLoadRequested(workflow.data));
|
dispatch(
|
||||||
|
workflowLoadRequested({ workflow: workflow.data, asCopy: true })
|
||||||
|
);
|
||||||
// No toast - the listener for this action does that after the workflow is loaded
|
// No toast - the listener for this action does that after the workflow is loaded
|
||||||
onSuccess && onSuccess();
|
onSuccess && onSuccess();
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -32,7 +32,9 @@ export const useGetAndLoadLibraryWorkflow: UseGetAndLoadLibraryWorkflow = ({
|
|||||||
async (workflow_id: string) => {
|
async (workflow_id: string) => {
|
||||||
try {
|
try {
|
||||||
const data = await _getAndLoadWorkflow(workflow_id).unwrap();
|
const data = await _getAndLoadWorkflow(workflow_id).unwrap();
|
||||||
dispatch(workflowLoadRequested(data.workflow));
|
dispatch(
|
||||||
|
workflowLoadRequested({ workflow: data.workflow, asCopy: false })
|
||||||
|
);
|
||||||
// No toast - the listener for this action does that after the workflow is loaded
|
// No toast - the listener for this action does that after the workflow is loaded
|
||||||
onSuccess && onSuccess();
|
onSuccess && onSuccess();
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -31,7 +31,9 @@ export const useLoadWorkflowFromFile: UseLoadWorkflowFromFile = ({
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const parsedJSON = JSON.parse(String(rawJSON));
|
const parsedJSON = JSON.parse(String(rawJSON));
|
||||||
dispatch(workflowLoadRequested(parsedJSON));
|
dispatch(
|
||||||
|
workflowLoadRequested({ workflow: parsedJSON, asCopy: true })
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// There was a problem reading the file
|
// There was a problem reading the file
|
||||||
logger.error(t('nodes.unableToLoadWorkflow'));
|
logger.error(t('nodes.unableToLoadWorkflow'));
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useAppToaster } from 'app/components/Toaster';
|
import { useAppToaster } from 'app/components/Toaster';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { useWorkflow } from 'features/nodes/hooks/useWorkflow';
|
import { useWorkflow } from 'features/nodes/hooks/useWorkflow';
|
||||||
import { workflowLoaded } from 'features/nodes/store/nodesSlice';
|
import { workflowLoaded } from 'features/nodes/store/workflowSlice';
|
||||||
import { zWorkflowV2 } from 'features/nodes/types/workflow';
|
import { zWorkflowV2 } from 'features/nodes/types/workflow';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useAppToaster } from 'app/components/Toaster';
|
import { useAppToaster } from 'app/components/Toaster';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
import { useWorkflow } from 'features/nodes/hooks/useWorkflow';
|
import { useWorkflow } from 'features/nodes/hooks/useWorkflow';
|
||||||
import { workflowLoaded } from 'features/nodes/store/nodesSlice';
|
import { workflowLoaded } from 'features/nodes/store/workflowSlice';
|
||||||
import { zWorkflowV2 } from 'features/nodes/types/workflow';
|
import { zWorkflowV2 } from 'features/nodes/types/workflow';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user