Merge branch 'main' into pr-labeler

This commit is contained in:
Brandon 2024-01-25 20:36:12 -05:00 committed by GitHub
commit 03ac93bfc7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 97 additions and 38 deletions

View File

@ -45,7 +45,7 @@ export const useSocketIO = () => {
const socketOptions = useMemo(() => {
const options: Partial<ManagerOptions & SocketOptions> = {
timeout: 60000,
path: '/ws/socket.io',
path: `${window.location.pathname}ws/socket.io`,
autoConnect: false, // achtung! removing this breaks the dynamic middleware
forceNew: true,
};

View File

@ -24,6 +24,7 @@ const workflowKeys = [
'notes',
'exposedFields',
'meta',
'id',
] satisfies (keyof WorkflowV2)[];
export type BuildWorkflowFunction = (arg: BuildWorkflowArg) => WorkflowV2;

View File

@ -61,13 +61,21 @@ const WorkflowLibraryList = () => {
const [category, setCategory] = useState<WorkflowCategory>('user');
const [page, setPage] = useState(0);
const [query, setQuery] = useState('');
const [order_by, setOrderBy] = useState<WorkflowRecordOrderBy>('opened_at');
const projectId = useStore($projectId);
const orderByOptions = useMemo(() => {
return projectId
? ORDER_BY_OPTIONS.filter((option) => option.value !== 'opened_at')
: ORDER_BY_OPTIONS;
}, [projectId]);
const [order_by, setOrderBy] = useState<WorkflowRecordOrderBy>(
orderByOptions[0]?.value as WorkflowRecordOrderBy
);
const [direction, setDirection] = useState<SQLiteDirection>('ASC');
const [debouncedQuery] = useDebounce(query, 500);
const projectId = useStore($projectId);
const queryArg = useMemo<Parameters<typeof useListWorkflowsQuery>[0]>(() => {
if (category === 'user') {
if (category !== 'default') {
return {
page,
per_page: PER_PAGE,
@ -101,8 +109,8 @@ const WorkflowLibraryList = () => {
[order_by]
);
const valueOrderBy = useMemo(
() => ORDER_BY_OPTIONS.find((o) => o.value === order_by),
[order_by]
() => orderByOptions.find((o) => o.value === order_by),
[order_by, orderByOptions]
);
const onChangeDirection = useCallback<ComboboxOnChange>(
@ -186,7 +194,7 @@ const WorkflowLibraryList = () => {
<FormLabel>{t('common.orderBy')}</FormLabel>
<Combobox
value={valueOrderBy}
options={ORDER_BY_OPTIONS}
options={orderByOptions}
onChange={onChangeOrderBy}
/>
</FormControl>

View File

@ -1,7 +1,11 @@
import { useToast } from '@invoke-ai/ui';
import { useAppToaster } from 'app/components/Toaster';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useDeleteWorkflowMutation } from 'services/api/endpoints/workflows';
import {
useDeleteWorkflowMutation,
workflowsApi,
} from 'services/api/endpoints/workflows';
type UseDeleteLibraryWorkflowOptions = {
onSuccess?: () => void;
@ -22,6 +26,7 @@ export const useDeleteLibraryWorkflow: UseDeleteLibraryWorkflow = ({
onError,
}) => {
const toaster = useAppToaster();
const toast = useToast();
const { t } = useTranslation();
const [_deleteWorkflow, deleteWorkflowResult] = useDeleteWorkflowMutation();
@ -34,14 +39,20 @@ export const useDeleteLibraryWorkflow: UseDeleteLibraryWorkflow = ({
});
onSuccess && onSuccess();
} catch {
toaster({
title: t('toast.problemDeletingWorkflow'),
status: 'error',
});
if (
!toast.isActive(
`auth-error-toast-${workflowsApi.endpoints.deleteWorkflow.name}`
)
) {
toaster({
title: t('toast.problemDeletingWorkflow'),
status: 'error',
});
}
onError && onError();
}
},
[_deleteWorkflow, toaster, t, onSuccess, onError]
[_deleteWorkflow, toaster, t, onSuccess, onError, toast]
);
return { deleteWorkflow, deleteWorkflowResult };

View File

@ -1,9 +1,13 @@
import { useToast } from '@invoke-ai/ui';
import { useAppToaster } from 'app/components/Toaster';
import { useAppDispatch } from 'app/store/storeHooks';
import { workflowLoadRequested } from 'features/nodes/store/actions';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useLazyGetWorkflowQuery } from 'services/api/endpoints/workflows';
import {
useLazyGetWorkflowQuery,
workflowsApi,
} from 'services/api/endpoints/workflows';
type UseGetAndLoadLibraryWorkflowOptions = {
onSuccess?: () => void;
@ -25,6 +29,7 @@ export const useGetAndLoadLibraryWorkflow: UseGetAndLoadLibraryWorkflow = ({
}) => {
const dispatch = useAppDispatch();
const toaster = useAppToaster();
const toast = useToast();
const { t } = useTranslation();
const [_getAndLoadWorkflow, getAndLoadWorkflowResult] =
useLazyGetWorkflowQuery();
@ -38,14 +43,20 @@ export const useGetAndLoadLibraryWorkflow: UseGetAndLoadLibraryWorkflow = ({
// No toast - the listener for this action does that after the workflow is loaded
onSuccess && onSuccess();
} catch {
toaster({
title: t('toast.problemRetrievingWorkflow'),
status: 'error',
});
if (
!toast.isActive(
`auth-error-toast-${workflowsApi.endpoints.getWorkflow.name}`
)
) {
toaster({
title: t('toast.problemRetrievingWorkflow'),
status: 'error',
});
}
onError && onError();
}
},
[_getAndLoadWorkflow, dispatch, onSuccess, toaster, t, onError]
[_getAndLoadWorkflow, dispatch, onSuccess, toaster, t, onError, toast]
);
return { getAndLoadWorkflow, getAndLoadWorkflowResult };

View File

@ -12,6 +12,7 @@ import { useTranslation } from 'react-i18next';
import {
useCreateWorkflowMutation,
useUpdateWorkflowMutation,
workflowsApi,
} from 'services/api/endpoints/workflows';
import type { O } from 'ts-toolbelt';
@ -60,12 +61,23 @@ export const useSaveLibraryWorkflow: UseSaveLibraryWorkflow = () => {
isClosable: true,
});
} catch (e) {
toast.update(toastRef.current, {
title: t('workflows.problemSavingWorkflow'),
status: 'error',
duration: 1000,
isClosable: true,
});
if (
!toast.isActive(
`auth-error-toast-${workflowsApi.endpoints.createWorkflow.name}`
) &&
!toast.isActive(
`auth-error-toast-${workflowsApi.endpoints.updateWorkflow.name}`
)
) {
toast.update(toastRef.current, {
title: t('workflows.problemSavingWorkflow'),
status: 'error',
duration: 1000,
isClosable: true,
});
} else {
toast.close(toastRef.current);
}
}
}, [updateWorkflow, dispatch, toast, t, createWorkflow]);
return {

View File

@ -9,7 +9,10 @@ import {
} from 'features/nodes/store/workflowSlice';
import { useCallback, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useCreateWorkflowMutation } from 'services/api/endpoints/workflows';
import {
useCreateWorkflowMutation,
workflowsApi,
} from 'services/api/endpoints/workflows';
type SaveWorkflowAsArg = {
name: string;
@ -59,12 +62,20 @@ export const useSaveWorkflowAs: UseSaveWorkflowAs = () => {
});
} catch (e) {
onError && onError();
toast.update(toastRef.current, {
title: t('workflows.problemSavingWorkflow'),
status: 'error',
duration: 1000,
isClosable: true,
});
if (
!toast.isActive(
`auth-error-toast-${workflowsApi.endpoints.createWorkflow.name}`
)
) {
toast.update(toastRef.current, {
title: t('workflows.problemSavingWorkflow'),
status: 'error',
duration: 1000,
isClosable: true,
});
} else {
toast.close(toastRef.current);
}
}
},
[toast, createWorkflow, dispatch, t]

View File

@ -32,7 +32,7 @@ if (import.meta.env.MODE === 'package') {
fallbackLng: 'en',
debug: false,
backend: {
loadPath: '/locales/{{lng}}.json',
loadPath: `${window.location.href.replace(/\/$/, '')}/locales/{{lng}}.json`,
},
interpolation: {
escapeValue: false,

View File

@ -27,7 +27,8 @@ export const authToastMiddleware: Middleware =
if (isRejectedWithValue(action)) {
try {
const parsed = zRejectedForbiddenAction.parse(action);
if (parsed.meta?.arg?.endpointName === 'getImageDTO') {
const endpointName = parsed.meta?.arg?.endpointName;
if (endpointName === 'getImageDTO') {
// do not show toast if problem is image access
return;
}
@ -39,6 +40,7 @@ export const authToastMiddleware: Middleware =
: undefined;
dispatch(
addToast({
id: `auth-error-toast-${endpointName}`,
title: t('common.somethingWentWrong'),
status: 'error',
description: customMessage,

View File

@ -57,7 +57,9 @@ const dynamicBaseQuery: BaseQueryFn<
const projectId = $projectId.get();
const rawBaseQuery = fetchBaseQuery({
baseUrl: `${baseUrl ?? ''}/api/v1`,
baseUrl: baseUrl
? `${baseUrl}/api/v1`
: `${window.location.href.replace(/\/$/, '')}/api/v1`,
prepareHeaders: (headers) => {
if (authToken) {
headers.set('Authorization', `Bearer ${authToken}`);

View File

@ -26,8 +26,9 @@ export const receivedOpenAPISchema = createAsyncThunk(
'nodes/receivedOpenAPISchema',
async (_, { rejectWithValue }) => {
try {
const url = [window.location.origin, 'openapi.json'].join('/');
const response = await fetch(url);
const response = await fetch(
`${window.location.href.replace(/\/$/, '')}/openapi.json`
);
const openAPISchema = await response.json();
const schemaJSON = JSON.parse(

View File

@ -1 +1 @@
__version__ = "3.6.1"
__version__ = "3.6.2"