mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Merge branch 'main' into release/make-web-dist-startable
This commit is contained in:
commit
582f516fef
@ -8,8 +8,16 @@ import type { TypedStartListening, TypedAddListener } from '@reduxjs/toolkit';
|
||||
|
||||
import type { RootState, AppDispatch } from '../../store';
|
||||
import { addInitialImageSelectedListener } from './listeners/initialImageSelected';
|
||||
import { addImageUploadedListener } from './listeners/imageUploaded';
|
||||
import { addRequestedImageDeletionListener } from './listeners/imageDeleted';
|
||||
import {
|
||||
addImageUploadedFulfilledListener,
|
||||
addImageUploadedRejectedListener,
|
||||
} from './listeners/imageUploaded';
|
||||
import {
|
||||
addImageDeletedFulfilledListener,
|
||||
addImageDeletedPendingListener,
|
||||
addImageDeletedRejectedListener,
|
||||
addRequestedImageDeletionListener,
|
||||
} from './listeners/imageDeleted';
|
||||
import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas';
|
||||
import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
|
||||
import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
|
||||
@ -28,6 +36,37 @@ import { addSocketDisconnectedListener } from './listeners/socketio/socketDiscon
|
||||
import { addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
|
||||
import { addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
|
||||
import { addSessionReadyToInvokeListener } from './listeners/sessionReadyToInvoke';
|
||||
import {
|
||||
addImageMetadataReceivedFulfilledListener,
|
||||
addImageMetadataReceivedRejectedListener,
|
||||
} from './listeners/imageMetadataReceived';
|
||||
import {
|
||||
addImageUrlsReceivedFulfilledListener,
|
||||
addImageUrlsReceivedRejectedListener,
|
||||
} from './listeners/imageUrlsReceived';
|
||||
import {
|
||||
addSessionCreatedFulfilledListener,
|
||||
addSessionCreatedPendingListener,
|
||||
addSessionCreatedRejectedListener,
|
||||
} from './listeners/sessionCreated';
|
||||
import {
|
||||
addSessionInvokedFulfilledListener,
|
||||
addSessionInvokedPendingListener,
|
||||
addSessionInvokedRejectedListener,
|
||||
} from './listeners/sessionInvoked';
|
||||
import {
|
||||
addSessionCanceledFulfilledListener,
|
||||
addSessionCanceledPendingListener,
|
||||
addSessionCanceledRejectedListener,
|
||||
} from './listeners/sessionCanceled';
|
||||
import {
|
||||
addReceivedResultImagesPageFulfilledListener,
|
||||
addReceivedResultImagesPageRejectedListener,
|
||||
} from './listeners/receivedResultImagesPage';
|
||||
import {
|
||||
addReceivedUploadImagesPageFulfilledListener,
|
||||
addReceivedUploadImagesPageRejectedListener,
|
||||
} from './listeners/receivedUploadImagesPage';
|
||||
|
||||
export const listenerMiddleware = createListenerMiddleware();
|
||||
|
||||
@ -47,23 +86,40 @@ export type AppListenerEffect = ListenerEffect<
|
||||
AppDispatch
|
||||
>;
|
||||
|
||||
addImageUploadedListener();
|
||||
addInitialImageSelectedListener();
|
||||
addRequestedImageDeletionListener();
|
||||
// Image uploaded
|
||||
addImageUploadedFulfilledListener();
|
||||
addImageUploadedRejectedListener();
|
||||
|
||||
addInitialImageSelectedListener();
|
||||
|
||||
// Image deleted
|
||||
addRequestedImageDeletionListener();
|
||||
addImageDeletedPendingListener();
|
||||
addImageDeletedFulfilledListener();
|
||||
addImageDeletedRejectedListener();
|
||||
|
||||
// Image metadata
|
||||
addImageMetadataReceivedFulfilledListener();
|
||||
addImageMetadataReceivedRejectedListener();
|
||||
|
||||
// Image URLs
|
||||
addImageUrlsReceivedFulfilledListener();
|
||||
addImageUrlsReceivedRejectedListener();
|
||||
|
||||
// User Invoked
|
||||
addUserInvokedCanvasListener();
|
||||
addUserInvokedNodesListener();
|
||||
addUserInvokedTextToImageListener();
|
||||
addUserInvokedImageToImageListener();
|
||||
addSessionReadyToInvokeListener();
|
||||
|
||||
// Canvas actions
|
||||
addCanvasSavedToGalleryListener();
|
||||
addCanvasDownloadedAsImageListener();
|
||||
addCanvasCopiedToClipboardListener();
|
||||
addCanvasMergedListener();
|
||||
|
||||
// socketio
|
||||
|
||||
addGeneratorProgressListener();
|
||||
addGraphExecutionStateCompleteListener();
|
||||
addInvocationCompleteListener();
|
||||
@ -73,3 +129,24 @@ addSocketConnectedListener();
|
||||
addSocketDisconnectedListener();
|
||||
addSocketSubscribedListener();
|
||||
addSocketUnsubscribedListener();
|
||||
|
||||
// Session Created
|
||||
addSessionCreatedPendingListener();
|
||||
addSessionCreatedFulfilledListener();
|
||||
addSessionCreatedRejectedListener();
|
||||
|
||||
// Session Invoked
|
||||
addSessionInvokedPendingListener();
|
||||
addSessionInvokedFulfilledListener();
|
||||
addSessionInvokedRejectedListener();
|
||||
|
||||
// Session Canceled
|
||||
addSessionCanceledPendingListener();
|
||||
addSessionCanceledFulfilledListener();
|
||||
addSessionCanceledRejectedListener();
|
||||
|
||||
// Gallery pages
|
||||
addReceivedResultImagesPageFulfilledListener();
|
||||
addReceivedResultImagesPageRejectedListener();
|
||||
addReceivedUploadImagesPageFulfilledListener();
|
||||
addReceivedUploadImagesPageRejectedListener();
|
||||
|
@ -52,7 +52,6 @@ export const addCanvasMergedListener = () => {
|
||||
|
||||
dispatch(
|
||||
imageUploaded({
|
||||
imageType: 'intermediates',
|
||||
formData: {
|
||||
file: new File([blob], filename, { type: 'image/png' }),
|
||||
},
|
||||
@ -65,7 +64,7 @@ export const addCanvasMergedListener = () => {
|
||||
action.meta.arg.formData.file.name === filename
|
||||
);
|
||||
|
||||
const mergedCanvasImage = payload.response;
|
||||
const mergedCanvasImage = payload;
|
||||
|
||||
dispatch(
|
||||
setMergedCanvas({
|
||||
|
@ -29,7 +29,6 @@ export const addCanvasSavedToGalleryListener = () => {
|
||||
|
||||
dispatch(
|
||||
imageUploaded({
|
||||
imageType: 'results',
|
||||
formData: {
|
||||
file: new File([blob], 'mergedCanvas.png', { type: 'image/png' }),
|
||||
},
|
||||
|
@ -4,9 +4,14 @@ import { imageDeleted } from 'services/thunks/image';
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { clamp } from 'lodash-es';
|
||||
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||
import { uploadsAdapter } from 'features/gallery/store/uploadsSlice';
|
||||
import { resultsAdapter } from 'features/gallery/store/resultsSlice';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'addRequestedImageDeletionListener' });
|
||||
|
||||
/**
|
||||
* Called when the user requests an image deletion
|
||||
*/
|
||||
export const addRequestedImageDeletionListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: requestedImageDeletion,
|
||||
@ -19,11 +24,6 @@ export const addRequestedImageDeletionListener = () => {
|
||||
|
||||
const { image_name, image_type } = image;
|
||||
|
||||
if (image_type !== 'uploads' && image_type !== 'results') {
|
||||
moduleLog.warn({ data: image }, `Invalid image type ${image_type}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedImageName = getState().gallery.selectedImage?.image_name;
|
||||
|
||||
if (selectedImageName === image_name) {
|
||||
@ -57,3 +57,49 @@ export const addRequestedImageDeletionListener = () => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the actual delete request is sent to the server
|
||||
*/
|
||||
export const addImageDeletedPendingListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageDeleted.pending,
|
||||
effect: (action, { dispatch, getState }) => {
|
||||
const { imageName, imageType } = action.meta.arg;
|
||||
// Preemptively remove the image from the gallery
|
||||
if (imageType === 'uploads') {
|
||||
uploadsAdapter.removeOne(getState().uploads, imageName);
|
||||
}
|
||||
if (imageType === 'results') {
|
||||
resultsAdapter.removeOne(getState().results, imageName);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Called on successful delete
|
||||
*/
|
||||
export const addImageDeletedFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageDeleted.fulfilled,
|
||||
effect: (action, { dispatch, getState }) => {
|
||||
moduleLog.debug({ data: { image: action.meta.arg } }, 'Image deleted');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Called on failed delete
|
||||
*/
|
||||
export const addImageDeletedRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageDeleted.rejected,
|
||||
effect: (action, { dispatch, getState }) => {
|
||||
moduleLog.debug(
|
||||
{ data: { image: action.meta.arg } },
|
||||
'Unable to delete image'
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -0,0 +1,43 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { startAppListening } from '..';
|
||||
import { imageMetadataReceived } from 'services/thunks/image';
|
||||
import {
|
||||
ResultsImageDTO,
|
||||
resultUpserted,
|
||||
} from 'features/gallery/store/resultsSlice';
|
||||
import {
|
||||
UploadsImageDTO,
|
||||
uploadUpserted,
|
||||
} from 'features/gallery/store/uploadsSlice';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'image' });
|
||||
|
||||
export const addImageMetadataReceivedFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageMetadataReceived.fulfilled,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const image = action.payload;
|
||||
moduleLog.debug({ data: { image } }, 'Image metadata received');
|
||||
|
||||
if (image.image_type === 'results') {
|
||||
dispatch(resultUpserted(action.payload as ResultsImageDTO));
|
||||
}
|
||||
|
||||
if (image.image_type === 'uploads') {
|
||||
dispatch(uploadUpserted(action.payload as UploadsImageDTO));
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addImageMetadataReceivedRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageMetadataReceived.rejected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
moduleLog.debug(
|
||||
{ data: { image: action.meta.arg } },
|
||||
'Problem receiving image metadata'
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
@ -1,25 +1,31 @@
|
||||
import { startAppListening } from '..';
|
||||
import { uploadAdded } from 'features/gallery/store/uploadsSlice';
|
||||
import { uploadUpserted } from 'features/gallery/store/uploadsSlice';
|
||||
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||
import { imageUploaded } from 'services/thunks/image';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { initialImageSelected } from 'features/parameters/store/actions';
|
||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||
import { resultAdded } from 'features/gallery/store/resultsSlice';
|
||||
import { resultUpserted } from 'features/gallery/store/resultsSlice';
|
||||
import { isResultsImageDTO, isUploadsImageDTO } from 'services/types/guards';
|
||||
import { log } from 'app/logging/useLogger';
|
||||
|
||||
export const addImageUploadedListener = () => {
|
||||
const moduleLog = log.child({ namespace: 'image' });
|
||||
|
||||
export const addImageUploadedFulfilledListener = () => {
|
||||
startAppListening({
|
||||
predicate: (action): action is ReturnType<typeof imageUploaded.fulfilled> =>
|
||||
imageUploaded.fulfilled.match(action) &&
|
||||
action.payload.response.is_intermediate === false,
|
||||
action.payload.is_intermediate === false,
|
||||
effect: (action, { dispatch, getState }) => {
|
||||
const { response: image } = action.payload;
|
||||
const image = action.payload;
|
||||
|
||||
moduleLog.debug({ arg: '<Blob>', image }, 'Image uploaded');
|
||||
|
||||
const state = getState();
|
||||
|
||||
// Handle uploads
|
||||
if (isUploadsImageDTO(image)) {
|
||||
dispatch(uploadAdded(image));
|
||||
dispatch(uploadUpserted(image));
|
||||
|
||||
dispatch(addToast({ title: 'Image Uploaded', status: 'success' }));
|
||||
|
||||
@ -36,9 +42,26 @@ export const addImageUploadedListener = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle results
|
||||
// TODO: Can this ever happen? I don't think so...
|
||||
if (isResultsImageDTO(image)) {
|
||||
dispatch(resultAdded(image));
|
||||
dispatch(resultUpserted(image));
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addImageUploadedRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageUploaded.rejected,
|
||||
effect: (action, { dispatch }) => {
|
||||
dispatch(
|
||||
addToast({
|
||||
title: 'Image Upload Failed',
|
||||
description: action.error.message,
|
||||
status: 'error',
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -0,0 +1,51 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { startAppListening } from '..';
|
||||
import { imageUrlsReceived } from 'services/thunks/image';
|
||||
import { resultsAdapter } from 'features/gallery/store/resultsSlice';
|
||||
import { uploadsAdapter } from 'features/gallery/store/uploadsSlice';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'image' });
|
||||
|
||||
export const addImageUrlsReceivedFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageUrlsReceived.fulfilled,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const image = action.payload;
|
||||
moduleLog.debug({ data: { image } }, 'Image URLs received');
|
||||
|
||||
const { image_type, image_name, image_url, thumbnail_url } = image;
|
||||
|
||||
if (image_type === 'results') {
|
||||
resultsAdapter.updateOne(getState().results, {
|
||||
id: image_name,
|
||||
changes: {
|
||||
image_url,
|
||||
thumbnail_url,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (image_type === 'uploads') {
|
||||
uploadsAdapter.updateOne(getState().uploads, {
|
||||
id: image_name,
|
||||
changes: {
|
||||
image_url,
|
||||
thumbnail_url,
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addImageUrlsReceivedRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: imageUrlsReceived.rejected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
moduleLog.debug(
|
||||
{ data: { image: action.meta.arg } },
|
||||
'Problem getting image URLs'
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { startAppListening } from '..';
|
||||
import { receivedResultImagesPage } from 'services/thunks/gallery';
|
||||
import { serializeError } from 'serialize-error';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'gallery' });
|
||||
|
||||
export const addReceivedResultImagesPageFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: receivedResultImagesPage.fulfilled,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const page = action.payload;
|
||||
moduleLog.debug(
|
||||
{ data: { page } },
|
||||
`Received ${page.items.length} results`
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addReceivedResultImagesPageRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: receivedResultImagesPage.rejected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
if (action.payload) {
|
||||
moduleLog.debug(
|
||||
{ data: { error: serializeError(action.payload.error) } },
|
||||
'Problem receiving results'
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
@ -0,0 +1,33 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { startAppListening } from '..';
|
||||
import { receivedUploadImagesPage } from 'services/thunks/gallery';
|
||||
import { serializeError } from 'serialize-error';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'gallery' });
|
||||
|
||||
export const addReceivedUploadImagesPageFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: receivedUploadImagesPage.fulfilled,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const page = action.payload;
|
||||
moduleLog.debug(
|
||||
{ data: { page } },
|
||||
`Received ${page.items.length} uploads`
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addReceivedUploadImagesPageRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: receivedUploadImagesPage.rejected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
if (action.payload) {
|
||||
moduleLog.debug(
|
||||
{ data: { error: serializeError(action.payload.error) } },
|
||||
'Problem receiving uploads'
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
@ -0,0 +1,48 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { startAppListening } from '..';
|
||||
import { sessionCanceled } from 'services/thunks/session';
|
||||
import { serializeError } from 'serialize-error';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'session' });
|
||||
|
||||
export const addSessionCanceledPendingListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionCanceled.pending,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
//
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addSessionCanceledFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionCanceled.fulfilled,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const { sessionId } = action.meta.arg;
|
||||
moduleLog.debug(
|
||||
{ data: { sessionId } },
|
||||
`Session canceled (${sessionId})`
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addSessionCanceledRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionCanceled.rejected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
if (action.payload) {
|
||||
const { arg, error } = action.payload;
|
||||
moduleLog.error(
|
||||
{
|
||||
data: {
|
||||
arg,
|
||||
error: serializeError(error),
|
||||
},
|
||||
},
|
||||
`Problem canceling session`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
@ -0,0 +1,45 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { startAppListening } from '..';
|
||||
import { sessionCreated } from 'services/thunks/session';
|
||||
import { serializeError } from 'serialize-error';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'session' });
|
||||
|
||||
export const addSessionCreatedPendingListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionCreated.pending,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
//
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addSessionCreatedFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionCreated.fulfilled,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const session = action.payload;
|
||||
moduleLog.debug({ data: { session } }, `Session created (${session.id})`);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addSessionCreatedRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionCreated.rejected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
if (action.payload) {
|
||||
const { arg, error } = action.payload;
|
||||
moduleLog.error(
|
||||
{
|
||||
data: {
|
||||
arg,
|
||||
error: serializeError(error),
|
||||
},
|
||||
},
|
||||
`Problem creating session`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
@ -0,0 +1,48 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { startAppListening } from '..';
|
||||
import { sessionInvoked } from 'services/thunks/session';
|
||||
import { serializeError } from 'serialize-error';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'session' });
|
||||
|
||||
export const addSessionInvokedPendingListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionInvoked.pending,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
//
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addSessionInvokedFulfilledListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionInvoked.fulfilled,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const { sessionId } = action.meta.arg;
|
||||
moduleLog.debug(
|
||||
{ data: { sessionId } },
|
||||
`Session invoked (${sessionId})`
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const addSessionInvokedRejectedListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: sessionInvoked.rejected,
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
if (action.payload) {
|
||||
const { arg, error } = action.payload;
|
||||
moduleLog.error(
|
||||
{
|
||||
data: {
|
||||
arg,
|
||||
error: serializeError(error),
|
||||
},
|
||||
},
|
||||
`Problem invoking session`
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
@ -3,7 +3,7 @@ import { sessionInvoked } from 'services/thunks/session';
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { sessionReadyToInvoke } from 'features/system/store/actions';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'invoke' });
|
||||
const moduleLog = log.child({ namespace: 'session' });
|
||||
|
||||
export const addSessionReadyToInvokeListener = () => {
|
||||
startAppListening({
|
||||
@ -11,7 +11,10 @@ export const addSessionReadyToInvokeListener = () => {
|
||||
effect: (action, { getState, dispatch }) => {
|
||||
const { sessionId } = getState().system;
|
||||
if (sessionId) {
|
||||
moduleLog.info({ sessionId }, `Session invoked (${sessionId})})`);
|
||||
moduleLog.debug(
|
||||
{ sessionId },
|
||||
`Session ready to invoke (${sessionId})})`
|
||||
);
|
||||
dispatch(sessionInvoked({ sessionId }));
|
||||
}
|
||||
},
|
||||
|
@ -10,7 +10,7 @@ export const addGraphExecutionStateCompleteListener = () => {
|
||||
effect: (action, { dispatch, getState }) => {
|
||||
moduleLog.debug(
|
||||
action.payload,
|
||||
`Graph execution state complete (${action.payload.data.graph_execution_state_id})`
|
||||
`Session invocation complete (${action.payload.data.graph_execution_state_id})`
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -2,13 +2,11 @@ import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
||||
import { startAppListening } from '../..';
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { invocationComplete } from 'services/events/actions';
|
||||
import {
|
||||
imageMetadataReceived,
|
||||
imageUrlsReceived,
|
||||
} from 'services/thunks/image';
|
||||
import { imageMetadataReceived } from 'services/thunks/image';
|
||||
import { sessionCanceled } from 'services/thunks/session';
|
||||
import { isImageOutput } from 'services/types/guards';
|
||||
import { progressImageSet } from 'features/system/store/systemSlice';
|
||||
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||
|
||||
const moduleLog = log.child({ namespace: 'socketio' });
|
||||
const nodeDenylist = ['dataURL_image'];
|
||||
@ -17,7 +15,7 @@ export const addInvocationCompleteListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: invocationComplete,
|
||||
effect: async (action, { dispatch, getState, take }) => {
|
||||
moduleLog.info(
|
||||
moduleLog.debug(
|
||||
action.payload,
|
||||
`Invocation complete (${action.payload.data.node.type})`
|
||||
);
|
||||
@ -46,6 +44,14 @@ export const addInvocationCompleteListener = () => {
|
||||
})
|
||||
);
|
||||
|
||||
const [{ payload: imageDTO }] = await take(
|
||||
imageMetadataReceived.fulfilled.match
|
||||
);
|
||||
|
||||
if (getState().gallery.shouldAutoSwitchToNewImages) {
|
||||
dispatch(imageSelected(imageDTO));
|
||||
}
|
||||
|
||||
// Handle canvas image
|
||||
if (
|
||||
graph_execution_state_id ===
|
||||
|
@ -8,7 +8,7 @@ export const addInvocationErrorListener = () => {
|
||||
startAppListening({
|
||||
actionCreator: invocationError,
|
||||
effect: (action, { dispatch, getState }) => {
|
||||
moduleLog.debug(
|
||||
moduleLog.error(
|
||||
action.payload,
|
||||
`Invocation error (${action.payload.data.node.type})`
|
||||
);
|
||||
|
@ -19,7 +19,7 @@ export const addInvocationStartedListener = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
moduleLog.info(
|
||||
moduleLog.debug(
|
||||
action.payload,
|
||||
`Invocation started (${action.payload.data.node.type})`
|
||||
);
|
||||
|
@ -91,7 +91,7 @@ export const addUserInvokedCanvasListener = () => {
|
||||
|
||||
dispatch(canvasGraphBuilt(graph));
|
||||
|
||||
moduleLog({ data: graph }, 'Canvas graph built');
|
||||
moduleLog.debug({ data: graph }, 'Canvas graph built');
|
||||
|
||||
// If we are generating img2img or inpaint, we need to upload the init images
|
||||
if (baseNode.type === 'img2img' || baseNode.type === 'inpaint') {
|
||||
@ -106,19 +106,16 @@ export const addUserInvokedCanvasListener = () => {
|
||||
);
|
||||
|
||||
// Wait for the image to be uploaded
|
||||
const [{ payload: basePayload }] = await take(
|
||||
const [{ payload: baseImageDTO }] = await take(
|
||||
(action): action is ReturnType<typeof imageUploaded.fulfilled> =>
|
||||
imageUploaded.fulfilled.match(action) &&
|
||||
action.meta.arg.formData.file.name === baseFilename
|
||||
);
|
||||
|
||||
// Update the base node with the image name and type
|
||||
const { image_name: baseName, image_type: baseType } =
|
||||
basePayload.response;
|
||||
|
||||
baseNode.image = {
|
||||
image_name: baseName,
|
||||
image_type: baseType,
|
||||
image_name: baseImageDTO.image_name,
|
||||
image_type: baseImageDTO.image_type,
|
||||
};
|
||||
}
|
||||
|
||||
@ -135,19 +132,16 @@ export const addUserInvokedCanvasListener = () => {
|
||||
);
|
||||
|
||||
// Wait for the mask to be uploaded
|
||||
const [{ payload: maskPayload }] = await take(
|
||||
const [{ payload: maskImageDTO }] = await take(
|
||||
(action): action is ReturnType<typeof imageUploaded.fulfilled> =>
|
||||
imageUploaded.fulfilled.match(action) &&
|
||||
action.meta.arg.formData.file.name === maskFilename
|
||||
);
|
||||
|
||||
// Update the base node with the image name and type
|
||||
const { image_name: maskName, image_type: maskType } =
|
||||
maskPayload.response;
|
||||
|
||||
baseNode.mask = {
|
||||
image_name: maskName,
|
||||
image_type: maskType,
|
||||
image_name: maskImageDTO.image_name,
|
||||
image_type: maskImageDTO.image_type,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ export const addUserInvokedImageToImageListener = () => {
|
||||
|
||||
const graph = buildImageToImageGraph(state);
|
||||
dispatch(imageToImageGraphBuilt(graph));
|
||||
moduleLog({ data: graph }, 'Image to Image graph built');
|
||||
moduleLog.debug({ data: graph }, 'Image to Image graph built');
|
||||
|
||||
dispatch(sessionCreated({ graph }));
|
||||
|
||||
|
@ -17,7 +17,7 @@ export const addUserInvokedNodesListener = () => {
|
||||
|
||||
const graph = buildNodesGraph(state);
|
||||
dispatch(nodesGraphBuilt(graph));
|
||||
moduleLog({ data: graph }, 'Nodes graph built');
|
||||
moduleLog.debug({ data: graph }, 'Nodes graph built');
|
||||
|
||||
dispatch(sessionCreated({ graph }));
|
||||
|
||||
|
@ -19,7 +19,7 @@ export const addUserInvokedTextToImageListener = () => {
|
||||
|
||||
dispatch(textToImageGraphBuilt(graph));
|
||||
|
||||
moduleLog({ data: graph }, 'Text to Image graph built');
|
||||
moduleLog.debug({ data: graph }, 'Text to Image graph built');
|
||||
|
||||
dispatch(sessionCreated({ graph }));
|
||||
|
||||
|
@ -68,7 +68,6 @@ const ImageUploader = (props: ImageUploaderProps) => {
|
||||
async (file: File) => {
|
||||
dispatch(
|
||||
imageUploaded({
|
||||
imageType: 'uploads',
|
||||
formData: { file },
|
||||
activeTabName,
|
||||
})
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
|
||||
import {
|
||||
PayloadAction,
|
||||
createEntityAdapter,
|
||||
createSlice,
|
||||
} from '@reduxjs/toolkit';
|
||||
import { RootState } from 'app/store/store';
|
||||
import {
|
||||
receivedResultImagesPage,
|
||||
IMAGES_PER_PAGE,
|
||||
} from 'services/thunks/gallery';
|
||||
import {
|
||||
imageDeleted,
|
||||
imageMetadataReceived,
|
||||
imageUrlsReceived,
|
||||
} from 'services/thunks/image';
|
||||
import { ImageDTO } from 'services/api';
|
||||
import { dateComparator } from 'common/util/dateComparator';
|
||||
|
||||
@ -26,6 +25,7 @@ type AdditionalResultsState = {
|
||||
pages: number;
|
||||
isLoading: boolean;
|
||||
nextPage: number;
|
||||
upsertedImageCount: number;
|
||||
};
|
||||
|
||||
export const initialResultsState =
|
||||
@ -34,6 +34,7 @@ export const initialResultsState =
|
||||
pages: 0,
|
||||
isLoading: false,
|
||||
nextPage: 0,
|
||||
upsertedImageCount: 0,
|
||||
});
|
||||
|
||||
export type ResultsState = typeof initialResultsState;
|
||||
@ -42,7 +43,10 @@ const resultsSlice = createSlice({
|
||||
name: 'results',
|
||||
initialState: initialResultsState,
|
||||
reducers: {
|
||||
resultAdded: resultsAdapter.upsertOne,
|
||||
resultUpserted: (state, action: PayloadAction<ResultsImageDTO>) => {
|
||||
resultsAdapter.upsertOne(state, action.payload);
|
||||
state.upsertedImageCount += 1;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
/**
|
||||
@ -68,47 +72,6 @@ const resultsSlice = createSlice({
|
||||
state.nextPage = items.length < IMAGES_PER_PAGE ? page : page + 1;
|
||||
state.isLoading = false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Image Metadata Received - FULFILLED
|
||||
*/
|
||||
builder.addCase(imageMetadataReceived.fulfilled, (state, action) => {
|
||||
const { image_type } = action.payload;
|
||||
|
||||
if (image_type === 'results') {
|
||||
resultsAdapter.upsertOne(state, action.payload as ResultsImageDTO);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Image URLs Received - FULFILLED
|
||||
*/
|
||||
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
|
||||
const { image_name, image_type, image_url, thumbnail_url } =
|
||||
action.payload;
|
||||
|
||||
if (image_type === 'results') {
|
||||
resultsAdapter.updateOne(state, {
|
||||
id: image_name,
|
||||
changes: {
|
||||
image_url: image_url,
|
||||
thumbnail_url: thumbnail_url,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Delete Image - PENDING
|
||||
* Pre-emptively remove the image from the gallery
|
||||
*/
|
||||
builder.addCase(imageDeleted.pending, (state, action) => {
|
||||
const { imageType, imageName } = action.meta.arg;
|
||||
|
||||
if (imageType === 'results') {
|
||||
resultsAdapter.removeOne(state, imageName);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -120,6 +83,6 @@ export const {
|
||||
selectTotal: selectResultsTotal,
|
||||
} = resultsAdapter.getSelectors<RootState>((state) => state.results);
|
||||
|
||||
export const { resultAdded } = resultsSlice.actions;
|
||||
export const { resultUpserted } = resultsSlice.actions;
|
||||
|
||||
export default resultsSlice.reducer;
|
||||
|
@ -1,11 +1,14 @@
|
||||
import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
|
||||
import {
|
||||
PayloadAction,
|
||||
createEntityAdapter,
|
||||
createSlice,
|
||||
} from '@reduxjs/toolkit';
|
||||
|
||||
import { RootState } from 'app/store/store';
|
||||
import {
|
||||
receivedUploadImagesPage,
|
||||
IMAGES_PER_PAGE,
|
||||
} from 'services/thunks/gallery';
|
||||
import { imageDeleted, imageUrlsReceived } from 'services/thunks/image';
|
||||
import { ImageDTO } from 'services/api';
|
||||
import { dateComparator } from 'common/util/dateComparator';
|
||||
|
||||
@ -23,6 +26,7 @@ type AdditionalUploadsState = {
|
||||
pages: number;
|
||||
isLoading: boolean;
|
||||
nextPage: number;
|
||||
upsertedImageCount: number;
|
||||
};
|
||||
|
||||
export const initialUploadsState =
|
||||
@ -31,6 +35,7 @@ export const initialUploadsState =
|
||||
pages: 0,
|
||||
nextPage: 0,
|
||||
isLoading: false,
|
||||
upsertedImageCount: 0,
|
||||
});
|
||||
|
||||
export type UploadsState = typeof initialUploadsState;
|
||||
@ -39,7 +44,10 @@ const uploadsSlice = createSlice({
|
||||
name: 'uploads',
|
||||
initialState: initialUploadsState,
|
||||
reducers: {
|
||||
uploadAdded: uploadsAdapter.upsertOne,
|
||||
uploadUpserted: (state, action: PayloadAction<UploadsImageDTO>) => {
|
||||
uploadsAdapter.upsertOne(state, action.payload);
|
||||
state.upsertedImageCount += 1;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
/**
|
||||
@ -65,36 +73,6 @@ const uploadsSlice = createSlice({
|
||||
state.nextPage = items.length < IMAGES_PER_PAGE ? page : page + 1;
|
||||
state.isLoading = false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Image URLs Received - FULFILLED
|
||||
*/
|
||||
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
|
||||
const { image_name, image_type, image_url, thumbnail_url } =
|
||||
action.payload;
|
||||
|
||||
if (image_type === 'uploads') {
|
||||
uploadsAdapter.updateOne(state, {
|
||||
id: image_name,
|
||||
changes: {
|
||||
image_url: image_url,
|
||||
thumbnail_url: thumbnail_url,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Delete Image - pending
|
||||
* Pre-emptively remove the image from the gallery
|
||||
*/
|
||||
builder.addCase(imageDeleted.pending, (state, action) => {
|
||||
const { imageType, imageName } = action.meta.arg;
|
||||
|
||||
if (imageType === 'uploads') {
|
||||
uploadsAdapter.removeOne(state, imageName);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -106,6 +84,6 @@ export const {
|
||||
selectTotal: selectUploadsTotal,
|
||||
} = uploadsAdapter.getSelectors<RootState>((state) => state.uploads);
|
||||
|
||||
export const { uploadAdded } = uploadsSlice.actions;
|
||||
export const { uploadUpserted } = uploadsSlice.actions;
|
||||
|
||||
export default uploadsSlice.reducer;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { UseToastOptions } from '@chakra-ui/react';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { PayloadAction, isAnyOf } from '@reduxjs/toolkit';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import * as InvokeAI from 'app/types/invokeai';
|
||||
import {
|
||||
@ -16,7 +16,11 @@ import {
|
||||
|
||||
import { ProgressImage } from 'services/events/types';
|
||||
import { makeToast } from '../../../app/components/Toaster';
|
||||
import { sessionCanceled, sessionInvoked } from 'services/thunks/session';
|
||||
import {
|
||||
sessionCanceled,
|
||||
sessionCreated,
|
||||
sessionInvoked,
|
||||
} from 'services/thunks/session';
|
||||
import { receivedModels } from 'services/thunks/model';
|
||||
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
|
||||
import { LogLevelName } from 'roarr';
|
||||
@ -345,15 +349,8 @@ export const systemSlice = createSlice({
|
||||
state.statusTranslationKey = 'common.statusPreparing';
|
||||
});
|
||||
|
||||
builder.addCase(sessionInvoked.rejected, (state, action) => {
|
||||
const error = action.payload as string | undefined;
|
||||
state.toastQueue.push(
|
||||
makeToast({ title: error || t('toast.serverError'), status: 'error' })
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Session Canceled
|
||||
* Session Canceled - FULFILLED
|
||||
*/
|
||||
builder.addCase(sessionCanceled.fulfilled, (state, action) => {
|
||||
state.canceledSession = action.meta.arg.sessionId;
|
||||
@ -416,6 +413,26 @@ export const systemSlice = createSlice({
|
||||
builder.addCase(imageUploaded.fulfilled, (state) => {
|
||||
state.isUploading = false;
|
||||
});
|
||||
|
||||
// *** Matchers - must be after all cases ***
|
||||
|
||||
/**
|
||||
* Session Invoked - REJECTED
|
||||
* Session Created - REJECTED
|
||||
*/
|
||||
builder.addMatcher(isAnySessionRejected, (state, action) => {
|
||||
state.isProcessing = false;
|
||||
state.isCancelable = false;
|
||||
state.isCancelScheduled = false;
|
||||
state.currentStep = 0;
|
||||
state.totalSteps = 0;
|
||||
state.statusTranslationKey = 'common.statusConnected';
|
||||
state.progressImage = null;
|
||||
|
||||
state.toastQueue.push(
|
||||
makeToast({ title: t('toast.serverError'), status: 'error' })
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -444,3 +461,8 @@ export const {
|
||||
} = systemSlice.actions;
|
||||
|
||||
export default systemSlice.reducer;
|
||||
|
||||
const isAnySessionRejected = isAnyOf(
|
||||
sessionCreated.rejected,
|
||||
sessionInvoked.rejected
|
||||
);
|
||||
|
@ -8,11 +8,7 @@ import {
|
||||
import { socketSubscribed, socketUnsubscribed } from './actions';
|
||||
import { AppThunkDispatch, RootState } from 'app/store/store';
|
||||
import { getTimestamp } from 'common/util/getTimestamp';
|
||||
import {
|
||||
sessionInvoked,
|
||||
sessionCreated,
|
||||
sessionWithoutGraphCreated,
|
||||
} from 'services/thunks/session';
|
||||
import { sessionCreated } from 'services/thunks/session';
|
||||
import { OpenAPI } from 'services/api';
|
||||
import { setEventListeners } from 'services/events/util/setEventListeners';
|
||||
import { log } from 'app/logging/useLogger';
|
||||
@ -66,10 +62,7 @@ export const socketMiddleware = () => {
|
||||
socket.connect();
|
||||
}
|
||||
|
||||
if (
|
||||
sessionCreated.fulfilled.match(action) ||
|
||||
sessionWithoutGraphCreated.fulfilled.match(action)
|
||||
) {
|
||||
if (sessionCreated.fulfilled.match(action)) {
|
||||
const sessionId = action.payload.id;
|
||||
const oldSessionId = getState().system.sessionId;
|
||||
|
||||
|
@ -1,51 +1,64 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
||||
import { ImagesService } from 'services/api';
|
||||
import { ImagesService, PaginatedResults_ImageDTO_ } from 'services/api';
|
||||
|
||||
export const IMAGES_PER_PAGE = 20;
|
||||
|
||||
const galleryLog = log.child({ namespace: 'gallery' });
|
||||
type ReceivedResultImagesPageThunkConfig = {
|
||||
rejectValue: {
|
||||
error: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
export const receivedResultImagesPage = createAppAsyncThunk(
|
||||
export const receivedResultImagesPage = createAppAsyncThunk<
|
||||
PaginatedResults_ImageDTO_,
|
||||
void,
|
||||
ReceivedResultImagesPageThunkConfig
|
||||
>(
|
||||
'results/receivedResultImagesPage',
|
||||
async (_arg, { getState, rejectWithValue }) => {
|
||||
const { page, pages, nextPage } = getState().results;
|
||||
const { page, pages, nextPage, upsertedImageCount } = getState().results;
|
||||
|
||||
if (nextPage === page) {
|
||||
return rejectWithValue([]);
|
||||
}
|
||||
// If many images have been upserted, we need to offset the page number
|
||||
// TODO: add an offset param to the list images endpoint
|
||||
const pageOffset = Math.floor(upsertedImageCount / IMAGES_PER_PAGE);
|
||||
|
||||
const response = await ImagesService.listImagesWithMetadata({
|
||||
imageType: 'results',
|
||||
imageCategory: 'general',
|
||||
page: getState().results.nextPage,
|
||||
page: nextPage + pageOffset,
|
||||
perPage: IMAGES_PER_PAGE,
|
||||
});
|
||||
|
||||
galleryLog.info({ response }, `Received ${response.items.length} results`);
|
||||
|
||||
return response;
|
||||
}
|
||||
);
|
||||
|
||||
export const receivedUploadImagesPage = createAppAsyncThunk(
|
||||
type ReceivedUploadImagesPageThunkConfig = {
|
||||
rejectValue: {
|
||||
error: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
export const receivedUploadImagesPage = createAppAsyncThunk<
|
||||
PaginatedResults_ImageDTO_,
|
||||
void,
|
||||
ReceivedUploadImagesPageThunkConfig
|
||||
>(
|
||||
'uploads/receivedUploadImagesPage',
|
||||
async (_arg, { getState, rejectWithValue }) => {
|
||||
const { page, pages, nextPage } = getState().uploads;
|
||||
const { page, pages, nextPage, upsertedImageCount } = getState().uploads;
|
||||
|
||||
if (nextPage === page) {
|
||||
return rejectWithValue([]);
|
||||
}
|
||||
// If many images have been upserted, we need to offset the page number
|
||||
// TODO: add an offset param to the list images endpoint
|
||||
const pageOffset = Math.floor(upsertedImageCount / IMAGES_PER_PAGE);
|
||||
|
||||
const response = await ImagesService.listImagesWithMetadata({
|
||||
imageType: 'uploads',
|
||||
imageCategory: 'general',
|
||||
page: getState().uploads.nextPage,
|
||||
page: nextPage + pageOffset,
|
||||
perPage: IMAGES_PER_PAGE,
|
||||
});
|
||||
|
||||
galleryLog.info({ response }, `Received ${response.items.length} uploads`);
|
||||
|
||||
return response;
|
||||
}
|
||||
);
|
||||
|
@ -1,10 +1,6 @@
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import { ImagesService } from 'services/api';
|
||||
import { getHeaders } from 'services/util/getHeaders';
|
||||
|
||||
const imagesLog = log.child({ namespace: 'image' });
|
||||
|
||||
type imageUrlsReceivedArg = Parameters<
|
||||
(typeof ImagesService)['getImageUrls']
|
||||
@ -17,7 +13,6 @@ export const imageUrlsReceived = createAppAsyncThunk(
|
||||
'api/imageUrlsReceived',
|
||||
async (arg: imageUrlsReceivedArg) => {
|
||||
const response = await ImagesService.getImageUrls(arg);
|
||||
imagesLog.info({ arg, response }, 'Received image urls');
|
||||
return response;
|
||||
}
|
||||
);
|
||||
@ -33,7 +28,6 @@ export const imageMetadataReceived = createAppAsyncThunk(
|
||||
'api/imageMetadataReceived',
|
||||
async (arg: imageMetadataReceivedArg) => {
|
||||
const response = await ImagesService.getImageMetadata(arg);
|
||||
imagesLog.info({ arg, response }, 'Received image record');
|
||||
return response;
|
||||
}
|
||||
);
|
||||
@ -53,11 +47,7 @@ export const imageUploaded = createAppAsyncThunk(
|
||||
// strip out `activeTabName` from arg - the route does not need it
|
||||
const { activeTabName, ...rest } = arg;
|
||||
const response = await ImagesService.uploadImage(rest);
|
||||
const { location } = getHeaders(response);
|
||||
|
||||
imagesLog.debug({ arg: '<Blob>', response, location }, 'Image uploaded');
|
||||
|
||||
return { response, location };
|
||||
return response;
|
||||
}
|
||||
);
|
||||
|
||||
@ -70,9 +60,6 @@ export const imageDeleted = createAppAsyncThunk(
|
||||
'api/imageDeleted',
|
||||
async (arg: ImageDeletedArg) => {
|
||||
const response = await ImagesService.deleteImage(arg);
|
||||
|
||||
imagesLog.debug({ arg, response }, 'Image deleted');
|
||||
|
||||
return response;
|
||||
}
|
||||
);
|
||||
@ -80,15 +67,12 @@ export const imageDeleted = createAppAsyncThunk(
|
||||
type ImageUpdatedArg = Parameters<(typeof ImagesService)['updateImage']>[0];
|
||||
|
||||
/**
|
||||
* `ImagesService.deleteImage()` thunk
|
||||
* `ImagesService.updateImage()` thunk
|
||||
*/
|
||||
export const imageUpdated = createAppAsyncThunk(
|
||||
'api/imageUpdated',
|
||||
async (arg: ImageUpdatedArg) => {
|
||||
const response = await ImagesService.updateImage(arg);
|
||||
|
||||
imagesLog.debug({ arg, response }, 'Image updated');
|
||||
|
||||
return response;
|
||||
}
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
||||
import { SessionsService } from 'services/api';
|
||||
import { GraphExecutionState, SessionsService } from 'services/api';
|
||||
import { log } from 'app/logging/useLogger';
|
||||
import { serializeError } from 'serialize-error';
|
||||
import { isObject } from 'lodash-es';
|
||||
|
||||
const sessionLog = log.child({ namespace: 'session' });
|
||||
|
||||
@ -11,144 +11,89 @@ type SessionCreatedArg = {
|
||||
>[0]['requestBody'];
|
||||
};
|
||||
|
||||
type SessionCreatedThunkConfig = {
|
||||
rejectValue: { arg: SessionCreatedArg; error: unknown };
|
||||
};
|
||||
|
||||
/**
|
||||
* `SessionsService.createSession()` thunk
|
||||
*/
|
||||
export const sessionCreated = createAppAsyncThunk(
|
||||
'api/sessionCreated',
|
||||
async (arg: SessionCreatedArg, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await SessionsService.createSession({
|
||||
requestBody: arg.graph,
|
||||
});
|
||||
sessionLog.info({ arg, response }, `Session created (${response.id})`);
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
sessionLog.error(
|
||||
{
|
||||
error: serializeError(err),
|
||||
},
|
||||
'Problem creating session'
|
||||
);
|
||||
return rejectWithValue(err.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* `SessionsService.createSession()` without graph thunk
|
||||
*/
|
||||
export const sessionWithoutGraphCreated = createAppAsyncThunk(
|
||||
'api/sessionWithoutGraphCreated',
|
||||
async (_, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await SessionsService.createSession({});
|
||||
sessionLog.info({ response }, `Session created (${response.id})`);
|
||||
return response;
|
||||
} catch (err: any) {
|
||||
sessionLog.error(
|
||||
{
|
||||
error: serializeError(err),
|
||||
},
|
||||
'Problem creating session'
|
||||
);
|
||||
return rejectWithValue(err.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
type NodeAddedArg = Parameters<(typeof SessionsService)['addNode']>[0];
|
||||
|
||||
/**
|
||||
* `SessionsService.addNode()` thunk
|
||||
*/
|
||||
export const nodeAdded = createAppAsyncThunk(
|
||||
'api/nodeAdded',
|
||||
async (
|
||||
arg: { node: NodeAddedArg['requestBody']; sessionId: string },
|
||||
_thunkApi
|
||||
) => {
|
||||
const response = await SessionsService.addNode({
|
||||
requestBody: arg.node,
|
||||
sessionId: arg.sessionId,
|
||||
export const sessionCreated = createAppAsyncThunk<
|
||||
GraphExecutionState,
|
||||
SessionCreatedArg,
|
||||
SessionCreatedThunkConfig
|
||||
>('api/sessionCreated', async (arg, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await SessionsService.createSession({
|
||||
requestBody: arg.graph,
|
||||
});
|
||||
|
||||
sessionLog.info({ arg, response }, `Node added (${response})`);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
return rejectWithValue({ arg, error });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
type NodeUpdatedArg = Parameters<(typeof SessionsService)['updateNode']>[0];
|
||||
type SessionInvokedArg = { sessionId: string };
|
||||
|
||||
/**
|
||||
* `SessionsService.addNode()` thunk
|
||||
*/
|
||||
export const nodeUpdated = createAppAsyncThunk(
|
||||
'api/nodeUpdated',
|
||||
async (
|
||||
arg: { node: NodeUpdatedArg['requestBody']; sessionId: string },
|
||||
_thunkApi
|
||||
) => {
|
||||
const response = await SessionsService.updateNode({
|
||||
requestBody: arg.node,
|
||||
sessionId: arg.sessionId,
|
||||
nodePath: arg.node.id,
|
||||
});
|
||||
type SessionInvokedThunkConfig = {
|
||||
rejectValue: {
|
||||
arg: SessionInvokedArg;
|
||||
error: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
sessionLog.info({ arg, response }, `Node updated (${response})`);
|
||||
|
||||
return response;
|
||||
}
|
||||
);
|
||||
const isErrorWithStatus = (error: unknown): error is { status: number } =>
|
||||
isObject(error) && 'status' in error;
|
||||
|
||||
/**
|
||||
* `SessionsService.invokeSession()` thunk
|
||||
*/
|
||||
export const sessionInvoked = createAppAsyncThunk(
|
||||
'api/sessionInvoked',
|
||||
async (arg: { sessionId: string }, { rejectWithValue }) => {
|
||||
const { sessionId } = arg;
|
||||
export const sessionInvoked = createAppAsyncThunk<
|
||||
void,
|
||||
SessionInvokedArg,
|
||||
SessionInvokedThunkConfig
|
||||
>('api/sessionInvoked', async (arg, { rejectWithValue }) => {
|
||||
const { sessionId } = arg;
|
||||
|
||||
try {
|
||||
const response = await SessionsService.invokeSession({
|
||||
sessionId,
|
||||
all: true,
|
||||
});
|
||||
sessionLog.info({ arg, response }, `Session invoked (${sessionId})`);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
const err = error as any;
|
||||
if (err.status === 403) {
|
||||
return rejectWithValue(err.body.detail);
|
||||
}
|
||||
throw error;
|
||||
try {
|
||||
const response = await SessionsService.invokeSession({
|
||||
sessionId,
|
||||
all: true,
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
if (isErrorWithStatus(error) && error.status === 403) {
|
||||
return rejectWithValue({ arg, error: (error as any).body.detail });
|
||||
}
|
||||
return rejectWithValue({ arg, error });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
type SessionCanceledArg = Parameters<
|
||||
(typeof SessionsService)['cancelSessionInvoke']
|
||||
>[0];
|
||||
|
||||
type SessionCanceledThunkConfig = {
|
||||
rejectValue: {
|
||||
arg: SessionCanceledArg;
|
||||
error: unknown;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* `SessionsService.cancelSession()` thunk
|
||||
*/
|
||||
export const sessionCanceled = createAppAsyncThunk(
|
||||
'api/sessionCanceled',
|
||||
async (arg: SessionCanceledArg, _thunkApi) => {
|
||||
const { sessionId } = arg;
|
||||
export const sessionCanceled = createAppAsyncThunk<
|
||||
void,
|
||||
SessionCanceledArg,
|
||||
SessionCanceledThunkConfig
|
||||
>('api/sessionCanceled', async (arg: SessionCanceledArg, _thunkApi) => {
|
||||
const { sessionId } = arg;
|
||||
|
||||
const response = await SessionsService.cancelSessionInvoke({
|
||||
sessionId,
|
||||
});
|
||||
const response = await SessionsService.cancelSessionInvoke({
|
||||
sessionId,
|
||||
});
|
||||
|
||||
sessionLog.info({ arg, response }, `Session canceled (${sessionId})`);
|
||||
|
||||
return response;
|
||||
}
|
||||
);
|
||||
return response;
|
||||
});
|
||||
|
||||
type SessionsListedArg = Parameters<
|
||||
(typeof SessionsService)['listSessions']
|
||||
|
Loading…
Reference in New Issue
Block a user