B: Fix cache invalidation and error handling
This commit is contained in:
parent
4f8cef5092
commit
283edcce86
|
@ -1,16 +1,29 @@
|
|||
import { Suspense } from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { Outlet } from 'react-router';
|
||||
|
||||
import ConceptToaster from '@/app/ConceptToaster';
|
||||
import Footer from '@/app/Footer';
|
||||
import Navigation from '@/app/Navigation';
|
||||
import { NavigationState } from '@/app/Navigation/NavigationContext';
|
||||
import Loader from '@/components/ui/Loader';
|
||||
import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
import ErrorFallback from './ErrorFallback';
|
||||
import { GlobalDialogs } from './GlobalDialogs';
|
||||
import { GlobalTooltips } from './GlobalTooltips';
|
||||
import { NavigationState } from './Navigation/NavigationContext';
|
||||
|
||||
const resetState = () => {
|
||||
console.log('Resetting state after error fallback');
|
||||
};
|
||||
|
||||
const logError = (error: Error, info: { componentStack?: string | null | undefined }) => {
|
||||
console.log('Error fallback: ' + error.message);
|
||||
if (info.componentStack) {
|
||||
console.log('Component stack: ' + info.componentStack);
|
||||
}
|
||||
};
|
||||
|
||||
function ApplicationLayout() {
|
||||
const mainHeight = useMainHeight();
|
||||
|
@ -23,6 +36,7 @@ function ApplicationLayout() {
|
|||
// TODO: prefetch data
|
||||
|
||||
return (
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback} onError={logError} onReset={resetState}>
|
||||
<NavigationState>
|
||||
<div className='min-w-[20rem] antialiased h-full max-w-[120rem] mx-auto'>
|
||||
<ConceptToaster
|
||||
|
@ -54,6 +68,7 @@ function ApplicationLayout() {
|
|||
</div>
|
||||
</div>
|
||||
</NavigationState>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import Button from '@/components/ui/Button';
|
|||
|
||||
function ErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
|
||||
return (
|
||||
<div className='flex flex-col gap-3 items-center antialiased' role='alert'>
|
||||
<h1>Что-то пошло не так!</h1>
|
||||
<div className='flex flex-col gap-3 my-3 items-center antialiased' role='alert'>
|
||||
<h1 className='my-2'>Что-то пошло не так!</h1>
|
||||
<Button onClick={resetErrorBoundary} text='Попробовать еще раз' />
|
||||
<InfoError error={error as Error} />
|
||||
</div>
|
||||
|
|
|
@ -2,32 +2,13 @@
|
|||
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
|
||||
import { queryClient } from '@/backend/queryClient';
|
||||
|
||||
import ErrorFallback from './ErrorFallback';
|
||||
|
||||
const resetState = () => {
|
||||
console.log('Resetting state after error fallback');
|
||||
};
|
||||
|
||||
const logError = (error: Error, info: { componentStack?: string | null | undefined }) => {
|
||||
console.log('Error fallback: ' + error.message);
|
||||
if (info.componentStack) {
|
||||
console.log('Component stack: ' + info.componentStack);
|
||||
}
|
||||
};
|
||||
|
||||
// prettier-ignore
|
||||
function GlobalProviders({ children }: React.PropsWithChildren) {
|
||||
return (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={ErrorFallback}
|
||||
onReset={resetState}
|
||||
onError={logError}
|
||||
>
|
||||
<IntlProvider locale='ru' defaultLocale='ru'>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
|
||||
|
@ -35,8 +16,7 @@ function GlobalProviders({ children }: React.PropsWithChildren) {
|
|||
{children}
|
||||
|
||||
</QueryClientProvider>
|
||||
</IntlProvider>
|
||||
</ErrorBoundary>);
|
||||
</IntlProvider>);
|
||||
}
|
||||
|
||||
export default GlobalProviders;
|
||||
|
|
|
@ -7,7 +7,7 @@ export const useChangePassword = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: ['change-password'],
|
||||
mutationFn: authApi.changePassword,
|
||||
onSettled: async () => await client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
onSettled: () => client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
});
|
||||
return {
|
||||
changePassword: (
|
||||
|
|
|
@ -7,7 +7,7 @@ export const useLogin = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: ['login'],
|
||||
mutationFn: authApi.login,
|
||||
onSettled: async () => await client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
onSettled: () => client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
});
|
||||
return {
|
||||
login: (
|
||||
|
|
|
@ -7,7 +7,7 @@ export const useLogout = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: ['logout'],
|
||||
mutationFn: authApi.logout,
|
||||
onSettled: async () => await client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
onSettled: () => client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
});
|
||||
return { logout: (onSuccess?: () => void) => mutation.mutate(undefined, { onSuccess }) };
|
||||
};
|
||||
|
|
|
@ -7,12 +7,12 @@ export const useResetPassword = () => {
|
|||
const validateMutation = useMutation({
|
||||
mutationKey: ['reset-password'],
|
||||
mutationFn: authApi.validatePasswordToken,
|
||||
onSuccess: async () => await client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
onSuccess: () => client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
});
|
||||
const resetMutation = useMutation({
|
||||
mutationKey: ['reset-password'],
|
||||
mutationFn: authApi.resetPassword,
|
||||
onSuccess: async () => await client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
onSuccess: () => client.invalidateQueries({ queryKey: [authApi.baseKey] })
|
||||
});
|
||||
return {
|
||||
validateToken: (
|
||||
|
|
|
@ -2,6 +2,8 @@ import { queryOptions } from '@tanstack/react-query';
|
|||
|
||||
import { axiosDelete, axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||
import { DELAYS } from '@/backend/configuration';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import {
|
||||
AccessPolicy,
|
||||
ILibraryItem,
|
||||
|
@ -15,9 +17,6 @@ import { ConstituentaID, IRSFormData } from '@/models/rsform';
|
|||
import { UserID } from '@/models/user';
|
||||
import { information } from '@/utils/labels';
|
||||
|
||||
import { ossApi } from '../oss/api';
|
||||
import { rsformsApi } from '../rsform/api';
|
||||
|
||||
/**
|
||||
* Represents update data for renaming Location.
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,7 @@ export const useCloneItem = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [libraryApi.baseKey, 'clone-item'],
|
||||
mutationFn: libraryApi.cloneItem,
|
||||
onSuccess: async () => await client.invalidateQueries({ queryKey: [libraryApi.baseKey] })
|
||||
onSuccess: () => client.invalidateQueries({ queryKey: [libraryApi.baseKey] })
|
||||
});
|
||||
return {
|
||||
cloneItem: (
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { ILibraryItem, LibraryItemID } from '@/models/library';
|
||||
|
||||
import { libraryApi } from './api';
|
||||
|
@ -9,11 +11,14 @@ export const useDeleteItem = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [libraryApi.baseKey, 'delete-item'],
|
||||
mutationFn: libraryApi.deleteItem,
|
||||
onSuccess: async (_, variables) => {
|
||||
await client.cancelQueries({ queryKey: [libraryApi.libraryListKey] });
|
||||
onSuccess: (_, variables) => {
|
||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
prev?.filter(item => item.id !== variables)
|
||||
);
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({ queryKey: rsformsApi.getRSFormQueryOptions({ itemID: variables }).queryKey })
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { ILibraryItemVersioned, LibraryItemID, LibraryItemType } from '@/models/library';
|
||||
|
||||
import { ossApi } from '../oss/api';
|
||||
import { rsformsApi } from '../rsform/api';
|
||||
|
||||
export function useLibraryItem({ itemID, itemType }: { itemID: LibraryItemID; itemType: LibraryItemType }) {
|
||||
const { data: rsForm } = useQuery({
|
||||
...rsformsApi.getRSFormQueryOptions({ itemID }),
|
||||
enabled: itemType === LibraryItemType.RSFORM
|
||||
});
|
||||
const { data: oss } = useQuery({
|
||||
...ossApi.getOssQueryOptions({ itemID }),
|
||||
enabled: itemType === LibraryItemType.OSS
|
||||
});
|
||||
return {
|
||||
item:
|
||||
itemType === LibraryItemType.RSFORM
|
||||
? (rsForm as ILibraryItemVersioned | undefined)
|
||||
: (oss as ILibraryItemVersioned | undefined)
|
||||
};
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
import { useIsMutating } from '@tanstack/react-query';
|
||||
|
||||
import { ossApi } from '../oss/api';
|
||||
import { rsformsApi } from '../rsform/api';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
|
||||
import { libraryApi } from './api';
|
||||
|
||||
export const useIsProcessingLibrary = () => {
|
||||
export const useMutatingLibrary = () => {
|
||||
const countMutations = useIsMutating({ mutationKey: [libraryApi.baseKey] });
|
||||
const countOss = useIsMutating({ mutationKey: [ossApi.baseKey] });
|
||||
const countRSForm = useIsMutating({ mutationKey: [rsformsApi.baseKey] });
|
|
@ -1,5 +1,8 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
|
||||
import { IRenameLocationDTO, libraryApi } from './api';
|
||||
|
||||
export const useRenameLocation = () => {
|
||||
|
@ -7,7 +10,12 @@ export const useRenameLocation = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [libraryApi.baseKey, 'rename-location'],
|
||||
mutationFn: libraryApi.renameLocation,
|
||||
onSuccess: () => client.invalidateQueries({ queryKey: [libraryApi.baseKey] })
|
||||
onSuccess: () =>
|
||||
Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [libraryApi.baseKey] }),
|
||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] }),
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] })
|
||||
])
|
||||
});
|
||||
return {
|
||||
renameLocation: (
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { AccessPolicy, ILibraryItem, LibraryItemID, LibraryItemType } from '@/models/library';
|
||||
import { AccessPolicy, ILibraryItem, LibraryItemID } from '@/models/library';
|
||||
import { IOperationSchemaData } from '@/models/oss';
|
||||
|
||||
import { libraryApi } from './api';
|
||||
|
||||
|
@ -11,21 +13,29 @@ export const useSetAccessPolicy = () => {
|
|||
mutationKey: [libraryApi.baseKey, 'set-location'],
|
||||
mutationFn: libraryApi.setAccessPolicy,
|
||||
onSuccess: (_, variables) => {
|
||||
const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
const ossData: IOperationSchemaData | undefined = client.getQueryData(ossKey);
|
||||
if (ossData) {
|
||||
client.setQueryData(ossKey, { ...ossData, access_policy: variables.policy });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
...ossData.items
|
||||
.map(item => {
|
||||
if (!item.result) {
|
||||
return;
|
||||
}
|
||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
||||
return client.invalidateQueries({ queryKey: itemKey });
|
||||
})
|
||||
.filter(item => !!item)
|
||||
]);
|
||||
}
|
||||
|
||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, access_policy: variables.policy }));
|
||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
prev?.map(item => (item.id === variables.itemID ? { ...item, access_policy: variables.policy } : item))
|
||||
);
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey, prev => {
|
||||
if (!prev) {
|
||||
return undefined;
|
||||
}
|
||||
if (prev.item_type === LibraryItemType.OSS) {
|
||||
client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] }).catch(console.error);
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
access_policy: variables.policy
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { UserID } from '@/models/user';
|
||||
|
||||
import { ossApi } from '../oss/api';
|
||||
import { libraryApi } from './api';
|
||||
|
||||
export const useSetEditors = () => {
|
||||
|
@ -17,20 +17,22 @@ export const useSetEditors = () => {
|
|||
const ossData = client.getQueryData(ossKey);
|
||||
if (ossData) {
|
||||
client.setQueryData(ossKey, { ...ossData, editors: variables.editors });
|
||||
Promise.allSettled([
|
||||
...ossData.items.map(item => {
|
||||
return Promise.allSettled(
|
||||
ossData.items
|
||||
.map(item => {
|
||||
if (!item.result) {
|
||||
return;
|
||||
}
|
||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
||||
return client.invalidateQueries({ queryKey: itemKey });
|
||||
})
|
||||
]).catch(console.error);
|
||||
} else {
|
||||
.filter(item => !!item)
|
||||
);
|
||||
}
|
||||
|
||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, editors: variables.editors }));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { ILibraryItem, LibraryItemID, LibraryItemType } from '@/models/library';
|
||||
import { ILibraryItem, LibraryItemID } from '@/models/library';
|
||||
import { IOperationSchemaData } from '@/models/oss';
|
||||
|
||||
import { libraryApi } from './api';
|
||||
|
||||
|
@ -11,43 +13,29 @@ export const useSetLocation = () => {
|
|||
mutationKey: [libraryApi.baseKey, 'set-location'],
|
||||
mutationFn: libraryApi.setLocation,
|
||||
onSuccess: (_, variables) => {
|
||||
// const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
// const ossData = client.getQueryData(ossKey);
|
||||
// if (ossData) {
|
||||
// client.setQueryData(ossKey, { ...ossData, editors: variables.editors });
|
||||
// Promise.allSettled([
|
||||
// client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
// ...ossData.items.map(item => {
|
||||
// if (!item.result) {
|
||||
// return;
|
||||
// }
|
||||
// const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
||||
// return client.invalidateQueries({ queryKey: itemKey });
|
||||
// })
|
||||
// ]).catch(console.error);
|
||||
// } else {
|
||||
// const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
// client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, editors: variables.editors }));
|
||||
// client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
// prev?.map(item => (item.id === variables.itemID ? { ...item, editors: variables.editors } : item))
|
||||
// );
|
||||
// }
|
||||
const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
const ossData: IOperationSchemaData | undefined = client.getQueryData(ossKey);
|
||||
if (ossData) {
|
||||
client.setQueryData(ossKey, { ...ossData, location: variables.location });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
...ossData.items
|
||||
.map(item => {
|
||||
if (!item.result) {
|
||||
return;
|
||||
}
|
||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
||||
return client.invalidateQueries({ queryKey: itemKey });
|
||||
})
|
||||
.filter(item => !!item)
|
||||
]);
|
||||
}
|
||||
|
||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, location: variables.location }));
|
||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
prev?.map(item => (item.id === variables.itemID ? { ...item, location: variables.location } : item))
|
||||
);
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey, prev => {
|
||||
if (!prev) {
|
||||
return undefined;
|
||||
}
|
||||
if (prev.item_type === LibraryItemType.OSS) {
|
||||
client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] }).catch(console.error);
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
location: variables.location
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { ILibraryItem, LibraryItemID, LibraryItemType } from '@/models/library';
|
||||
import { ILibraryItem, LibraryItemID } from '@/models/library';
|
||||
import { IOperationSchemaData } from '@/models/oss';
|
||||
import { UserID } from '@/models/user';
|
||||
|
||||
import { libraryApi } from './api';
|
||||
|
@ -12,21 +14,29 @@ export const useSetOwner = () => {
|
|||
mutationKey: [libraryApi.baseKey, 'set-owner'],
|
||||
mutationFn: libraryApi.setOwner,
|
||||
onSuccess: (_, variables) => {
|
||||
const ossKey = ossApi.getOssQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
const ossData: IOperationSchemaData | undefined = client.getQueryData(ossKey);
|
||||
if (ossData) {
|
||||
client.setQueryData(ossKey, { ...ossData, owner: variables.owner });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
...ossData.items
|
||||
.map(item => {
|
||||
if (!item.result) {
|
||||
return;
|
||||
}
|
||||
const itemKey = rsformsApi.getRSFormQueryOptions({ itemID: item.result }).queryKey;
|
||||
return client.invalidateQueries({ queryKey: itemKey });
|
||||
})
|
||||
.filter(item => !!item)
|
||||
]);
|
||||
}
|
||||
|
||||
const rsKey = rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey;
|
||||
client.setQueryData(rsKey, prev => (!prev ? undefined : { ...prev, owner: variables.owner }));
|
||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
prev?.map(item => (item.id === variables.itemID ? { ...item, owner: variables.owner } : item))
|
||||
);
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey, prev => {
|
||||
if (!prev) {
|
||||
return undefined;
|
||||
}
|
||||
if (prev.item_type === LibraryItemType.OSS) {
|
||||
client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] }).catch(console.error);
|
||||
}
|
||||
return {
|
||||
...prev,
|
||||
owner: variables.owner
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { ILibraryItem } from '@/models/library';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { ILibraryItem, LibraryItemType } from '@/models/library';
|
||||
import { IOperationSchemaData } from '@/models/oss';
|
||||
import { IRSFormData } from '@/models/rsform';
|
||||
|
||||
import { ILibraryUpdateDTO, libraryApi } from './api';
|
||||
|
||||
|
@ -11,17 +13,23 @@ export const useUpdateItem = () => {
|
|||
mutationKey: [libraryApi.baseKey, 'update-item'],
|
||||
mutationFn: libraryApi.updateItem,
|
||||
onSuccess: (data: ILibraryItem) => {
|
||||
client
|
||||
.cancelQueries({ queryKey: libraryApi.libraryListKey })
|
||||
.then(async () => {
|
||||
const itemKey = libraryApi.getItemQueryOptions({ itemID: data.id, itemType: data.item_type }).queryKey;
|
||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
prev?.map(item => (item.id === data.id ? data : item))
|
||||
);
|
||||
await client.invalidateQueries({
|
||||
queryKey: [rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey]
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
||||
client.setQueryData(itemKey, (prev: IRSFormData | IOperationSchemaData | undefined) =>
|
||||
!prev ? undefined : { ...prev, ...data }
|
||||
);
|
||||
if (data.item_type === LibraryItemType.RSFORM) {
|
||||
const schema: IRSFormData | undefined = client.getQueryData(itemKey);
|
||||
if (schema) {
|
||||
return Promise.allSettled(
|
||||
schema.oss.map(item =>
|
||||
client.invalidateQueries({ queryKey: ossApi.getOssQueryOptions({ itemID: item.id }).queryKey })
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { VersionID } from '@/models/library';
|
||||
|
||||
|
@ -8,13 +7,12 @@ import { libraryApi } from './api';
|
|||
|
||||
export const useVersionRestore = () => {
|
||||
const client = useQueryClient();
|
||||
const { updateTimestamp } = useUpdateTimestamp();
|
||||
const mutation = useMutation({
|
||||
mutationKey: [libraryApi.baseKey, 'restore-version'],
|
||||
mutationFn: libraryApi.versionRestore,
|
||||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
updateTimestamp(data.id);
|
||||
return client.invalidateQueries({ queryKey: [libraryApi.baseKey] });
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|||
|
||||
import { DataCallback } from '@/backend/apiTransport';
|
||||
import { libraryApi } from '@/backend/library/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { ILibraryItem, LibraryItemID } from '@/models/library';
|
||||
|
||||
import { ITargetOperation, ossApi } from './api';
|
||||
|
@ -11,9 +12,12 @@ export const useInputCreate = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [ossApi.baseKey, 'input-create'],
|
||||
mutationFn: ossApi.inputCreate,
|
||||
onSuccess: async data => {
|
||||
onSuccess: data => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.oss.id }).queryKey, data.oss);
|
||||
await client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { libraryApi } from '@/backend/library/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
|
||||
import { IInputUpdateDTO, ossApi } from './api';
|
||||
|
@ -10,9 +11,12 @@ export const useInputUpdate = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [ossApi.baseKey, 'input-update'],
|
||||
mutationFn: ossApi.inputUpdate,
|
||||
onSuccess: async data => {
|
||||
onSuccess: data => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
await client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { libraryApi } from '@/backend/library/api';
|
|||
|
||||
import { ossApi } from './api';
|
||||
|
||||
export const useIsProcessingOss = () => {
|
||||
export const useMutatingOss = () => {
|
||||
const countLibrary = useIsMutating({ mutationKey: [libraryApi.baseKey] });
|
||||
const countOss = useIsMutating({ mutationKey: [ossApi.baseKey] });
|
||||
return countLibrary + countOss !== 0;
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { libraryApi } from '@/backend/library/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
|
||||
import { IOperationDeleteDTO, ossApi } from './api';
|
||||
|
@ -10,9 +11,12 @@ export const useOperationDelete = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [ossApi.baseKey, 'operation-delete'],
|
||||
mutationFn: ossApi.operationDelete,
|
||||
onSuccess: async data => {
|
||||
onSuccess: data => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
await client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { libraryApi } from '@/backend/library/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
|
||||
import { ITargetOperation, ossApi } from './api';
|
||||
|
@ -10,9 +11,12 @@ export const useOperationExecute = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [ossApi.baseKey, 'operation-execute'],
|
||||
mutationFn: ossApi.operationExecute,
|
||||
onSuccess: async data => {
|
||||
onSuccess: data => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
await client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { libraryApi } from '@/backend/library/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { ILibraryItem, LibraryItemID } from '@/models/library';
|
||||
|
||||
import { IOperationUpdateDTO, ossApi } from './api';
|
||||
|
||||
|
@ -10,9 +11,22 @@ export const useOperationUpdate = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [ossApi.baseKey, 'operation-update'],
|
||||
mutationFn: ossApi.operationUpdate,
|
||||
onSuccess: async data => {
|
||||
onSuccess: (data, variables) => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
await client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] });
|
||||
const schemaID = data.items.find(item => item.id === variables.data.target)?.result;
|
||||
if (!schemaID) {
|
||||
return;
|
||||
}
|
||||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
!prev
|
||||
? undefined
|
||||
: prev.map(item =>
|
||||
item.id === schemaID ? { ...item, ...variables.data.item_data, time_update: Date() } : item
|
||||
)
|
||||
);
|
||||
return client.invalidateQueries({
|
||||
queryKey: rsformsApi.getRSFormQueryOptions({ itemID: schemaID }).queryKey
|
||||
});
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { libraryApi } from '@/backend/library/api';
|
||||
import { rsformsApi } from '@/backend/rsform/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
|
||||
import { ICstRelocateDTO, ossApi } from './api';
|
||||
|
@ -10,9 +11,12 @@ export const useRelocateConstituents = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [ossApi.baseKey, 'relocate-constituents'],
|
||||
mutationFn: ossApi.relocateConstituents,
|
||||
onSuccess: async data => {
|
||||
onSuccess: data => {
|
||||
client.setQueryData(ossApi.getOssQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
await client.invalidateQueries({ queryKey: [libraryApi.libraryListKey] });
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: libraryApi.libraryListKey }),
|
||||
client.invalidateQueries({ queryKey: [rsformsApi.baseKey] })
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -14,7 +14,7 @@ export const queryClient = new QueryClient({
|
|||
queries: {
|
||||
staleTime: DELAYS.staleDefault,
|
||||
gcTime: DELAYS.garbageCollection,
|
||||
retry: 3,
|
||||
retry: false,
|
||||
refetchOnWindowFocus: true,
|
||||
refetchOnMount: true,
|
||||
refetchOnReconnect: true
|
||||
|
|
|
@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|||
|
||||
import { DataCallback } from '@/backend/apiTransport';
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { IConstituentaMeta } from '@/models/rsform';
|
||||
|
||||
|
@ -16,7 +17,14 @@ export const useCstCreate = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.schema.id }).queryKey, data.schema);
|
||||
updateTimestamp(data.schema.id);
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { IConstituentaList } from '@/models/rsform';
|
||||
|
||||
|
@ -15,7 +16,14 @@ export const useCstDelete = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
updateTimestamp(data.id);
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -14,7 +14,6 @@ export const useCstMove = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
updateTimestamp(data.id);
|
||||
// TODO: invalidate OSS?
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
|
||||
import { ICstRenameDTO, rsformsApi } from './api';
|
||||
|
@ -14,7 +15,14 @@ export const useCstRename = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.schema.id }).queryKey, data.schema);
|
||||
updateTimestamp(data.schema.id);
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { ICstSubstitutions } from '@/models/oss';
|
||||
|
||||
|
@ -15,7 +16,14 @@ export const useCstSubstitute = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
updateTimestamp(data.id);
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
|
||||
import { ICstUpdateDTO, rsformsApi } from './api';
|
||||
|
@ -11,12 +12,24 @@ export const useCstUpdate = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: [rsformsApi.baseKey, 'update-cst'],
|
||||
mutationFn: rsformsApi.cstUpdate,
|
||||
onSuccess: async (_, variables) => {
|
||||
onSuccess: (newCst, variables) => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey, prev =>
|
||||
!prev
|
||||
? undefined
|
||||
: {
|
||||
...prev,
|
||||
items: prev.items.map(item => (item.id === newCst.id ? { ...item, ...newCst } : item))
|
||||
}
|
||||
);
|
||||
updateTimestamp(variables.itemID);
|
||||
await client.invalidateQueries({
|
||||
queryKey: [rsformsApi.getRSFormQueryOptions({ itemID: variables.itemID }).queryKey]
|
||||
});
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== variables.itemID
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|||
|
||||
import { DataCallback } from '@/backend/apiTransport';
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { IRSFormData } from '@/models/rsform';
|
||||
|
||||
|
@ -16,7 +17,14 @@ export const useInlineSynthesis = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
updateTimestamp(data.id);
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -4,7 +4,7 @@ import { libraryApi } from '@/backend/library/api';
|
|||
|
||||
import { rsformsApi } from './api';
|
||||
|
||||
export const useIsProcessingRSForm = () => {
|
||||
export const useMutatingRSForm = () => {
|
||||
const countLibrary = useIsMutating({ mutationKey: [libraryApi.baseKey] });
|
||||
const countRsform = useIsMutating({ mutationKey: [rsformsApi.baseKey] });
|
||||
return countLibrary + countRsform !== 0;
|
|
@ -2,6 +2,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|||
|
||||
import { DataCallback } from '@/backend/apiTransport';
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
import { ConstituentaID, ITargetCst } from '@/models/rsform';
|
||||
|
||||
|
@ -16,7 +17,14 @@ export const useProduceStructure = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.schema.id }).queryKey, data.schema);
|
||||
updateTimestamp(data.schema.id);
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.schema.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { useUpdateTimestamp } from '@/backend/library/useUpdateTimestamp';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { LibraryItemID } from '@/models/library';
|
||||
|
||||
import { rsformsApi } from './api';
|
||||
|
@ -14,7 +15,14 @@ export const useResetAliases = () => {
|
|||
onSuccess: data => {
|
||||
client.setQueryData(rsformsApi.getRSFormQueryOptions({ itemID: data.id }).queryKey, data);
|
||||
updateTimestamp(data.id);
|
||||
// TODO: invalidate OSS?
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
import { libraryApi } from '@/backend/library/api';
|
||||
import { ossApi } from '@/backend/oss/api';
|
||||
import { ILibraryItem } from '@/models/library';
|
||||
|
||||
import { IRSFormUploadDTO, rsformsApi } from './api';
|
||||
|
@ -15,6 +16,14 @@ export const useUploadTRS = () => {
|
|||
client.setQueryData(libraryApi.libraryListKey, (prev: ILibraryItem[] | undefined) =>
|
||||
prev?.map(item => (item.id === data.id ? data : item))
|
||||
);
|
||||
|
||||
return Promise.allSettled([
|
||||
client.invalidateQueries({ queryKey: [ossApi.baseKey] }),
|
||||
client.invalidateQueries({
|
||||
queryKey: [rsformsApi.baseKey],
|
||||
predicate: query => query.queryKey.length > 2 && query.queryKey[2] !== data.id
|
||||
})
|
||||
]);
|
||||
}
|
||||
});
|
||||
return {
|
||||
|
|
|
@ -9,7 +9,7 @@ export const useSignup = () => {
|
|||
const mutation = useMutation({
|
||||
mutationKey: ['signup'],
|
||||
mutationFn: usersApi.signup,
|
||||
onSuccess: async () => await client.invalidateQueries({ queryKey: [usersApi.baseKey] })
|
||||
onSuccess: () => client.invalidateQueries({ queryKey: usersApi.getUsersQueryOptions().queryKey })
|
||||
});
|
||||
return {
|
||||
signup: (
|
||||
|
|
|
@ -2,14 +2,15 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|||
|
||||
import { IUpdateProfileDTO, usersApi } from './api';
|
||||
|
||||
// TODO: reload users / optimistic update
|
||||
|
||||
export const useUpdateProfile = () => {
|
||||
const client = useQueryClient();
|
||||
const mutation = useMutation({
|
||||
mutationKey: ['update-profile'],
|
||||
mutationFn: usersApi.updateProfile,
|
||||
onSuccess: async () => await client.invalidateQueries({ queryKey: [usersApi.baseKey] })
|
||||
onSuccess: data => {
|
||||
client.setQueryData(usersApi.getProfileQueryOptions().queryKey, data);
|
||||
return client.invalidateQueries({ queryKey: usersApi.getUsersQueryOptions().queryKey });
|
||||
}
|
||||
});
|
||||
return {
|
||||
updateProfile: (data: IUpdateProfileDTO) => mutation.mutate(data),
|
||||
|
|
|
@ -16,7 +16,28 @@ function DescribeError({ error }: { error: ErrorData }) {
|
|||
} else if (typeof error === 'string') {
|
||||
return <p>{error}</p>;
|
||||
} else if (!axios.isAxiosError(error)) {
|
||||
return <PrettyJson data={error} />;
|
||||
return (
|
||||
<div className='mt-6'>
|
||||
<p>
|
||||
<b>Error:</b> {error.name}
|
||||
</p>
|
||||
<p>
|
||||
<b>Message:</b> {error.message}
|
||||
</p>
|
||||
{error.stack && (
|
||||
<pre
|
||||
style={{
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordWrap: 'break-word',
|
||||
padding: '6px',
|
||||
overflowX: 'auto'
|
||||
}}
|
||||
>
|
||||
{error.stack}
|
||||
</pre>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (!error?.response) {
|
||||
return <p>Нет ответа от сервера</p>;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { useIsProcessingLibrary } from '@/backend/library/useIsProcessingLibrary';
|
||||
import { useMutatingLibrary } from '@/backend/library/useMutatingLibrary';
|
||||
import { useVersionDelete } from '@/backend/library/useVersionDelete';
|
||||
import { useVersionUpdate } from '@/backend/library/useVersionUpdate';
|
||||
import { IconReset, IconSave } from '@/components/Icons';
|
||||
|
@ -22,7 +22,7 @@ export interface DlgEditVersionsProps {
|
|||
|
||||
function DlgEditVersions() {
|
||||
const { item, afterDelete } = useDialogsStore(state => state.props as DlgEditVersionsProps);
|
||||
const processing = useIsProcessingLibrary();
|
||||
const processing = useMutatingLibrary();
|
||||
const { versionDelete } = useVersionDelete();
|
||||
const { versionUpdate } = useVersionUpdate();
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import FlexColumn from '@/components/ui/FlexColumn';
|
||||
import { LibraryItemType } from '@/models/library';
|
||||
import EditorLibraryItem from '@/pages/RSFormPage/EditorRSFormCard/EditorLibraryItem';
|
||||
import ToolbarRSFormCard from '@/pages/RSFormPage/EditorRSFormCard/ToolbarRSFormCard';
|
||||
import { useModificationStore } from '@/stores/modification';
|
||||
|
@ -47,7 +46,7 @@ function EditorOssCard() {
|
|||
>
|
||||
<FlexColumn className='px-3'>
|
||||
<FormOSS id={globals.library_item_editor} />
|
||||
<EditorLibraryItem itemID={controller.schema.id} itemType={LibraryItemType.OSS} controller={controller} />
|
||||
<EditorLibraryItem controller={controller} />
|
||||
</FlexColumn>
|
||||
|
||||
{controller.schema ? <OssStats stats={controller.schema.stats} /> : null}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useEffect, useState } from 'react';
|
|||
|
||||
import { ILibraryUpdateDTO } from '@/backend/library/api';
|
||||
import { useUpdateItem } from '@/backend/library/useUpdateItem';
|
||||
import { useIsProcessingOss } from '@/backend/oss/useIsProcessingOss';
|
||||
import { useMutatingOss } from '@/backend/oss/useMutatingOss';
|
||||
import { IconSave } from '@/components/Icons';
|
||||
import SubmitButton from '@/components/ui/SubmitButton';
|
||||
import TextArea from '@/components/ui/TextArea';
|
||||
|
@ -24,7 +24,7 @@ function FormOSS({ id }: FormOSSProps) {
|
|||
const { updateItem: update } = useUpdateItem();
|
||||
const controller = useOssEdit();
|
||||
const { isModified, setIsModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingOss();
|
||||
const isProcessing = useMutatingOss();
|
||||
const schema = controller.schema;
|
||||
|
||||
const [title, setTitle] = useState(schema.title);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useIsProcessingOss } from '@/backend/oss/useIsProcessingOss';
|
||||
import { useMutatingOss } from '@/backend/oss/useMutatingOss';
|
||||
import {
|
||||
IconChild,
|
||||
IconConnect,
|
||||
|
@ -50,7 +50,7 @@ function NodeContextMenu({
|
|||
onRelocateConstituents
|
||||
}: NodeContextMenuProps) {
|
||||
const controller = useOssEdit();
|
||||
const isProcessing = useIsProcessingOss();
|
||||
const isProcessing = useMutatingOss();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
|
|
@ -20,7 +20,7 @@ import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
|||
import { urls } from '@/app/urls';
|
||||
import { useLibrary } from '@/backend/library/useLibrary';
|
||||
import { useInputCreate } from '@/backend/oss/useInputCreate';
|
||||
import { useIsProcessingOss } from '@/backend/oss/useIsProcessingOss';
|
||||
import { useMutatingOss } from '@/backend/oss/useMutatingOss';
|
||||
import { useOperationExecute } from '@/backend/oss/useOperationExecute';
|
||||
import { useUpdatePositions } from '@/backend/oss/useUpdatePositions';
|
||||
import { CProps } from '@/components/props';
|
||||
|
@ -50,7 +50,7 @@ function OssFlow() {
|
|||
const flow = useReactFlow();
|
||||
const { setIsModified } = useModificationStore();
|
||||
|
||||
const isProcessing = useIsProcessingOss();
|
||||
const isProcessing = useMutatingOss();
|
||||
|
||||
const showGrid = useOSSGraphStore(state => state.showGrid);
|
||||
const edgeAnimate = useOSSGraphStore(state => state.edgeAnimate);
|
||||
|
@ -118,7 +118,7 @@ function OssFlow() {
|
|||
}
|
||||
|
||||
function handleNodesChange(changes: NodeChange[]) {
|
||||
if (changes.some(change => change.type === 'position' && change.position)) {
|
||||
if (controller.isMutable && changes.some(change => change.type === 'position' && change.position)) {
|
||||
setIsModified(true);
|
||||
}
|
||||
onNodesChange(changes);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import clsx from 'clsx';
|
||||
|
||||
import { useIsProcessingOss } from '@/backend/oss/useIsProcessingOss';
|
||||
import { useMutatingOss } from '@/backend/oss/useMutatingOss';
|
||||
import {
|
||||
IconAnimation,
|
||||
IconAnimationOff,
|
||||
|
@ -52,7 +52,7 @@ function ToolbarOssGraph({
|
|||
}: ToolbarOssGraphProps) {
|
||||
const controller = useOssEdit();
|
||||
const { isModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingOss();
|
||||
const isProcessing = useMutatingOss();
|
||||
const selectedOperation = controller.schema.operationByID.get(controller.selected[0]);
|
||||
|
||||
const showGrid = useOSSGraphStore(state => state.showGrid);
|
||||
|
@ -89,7 +89,6 @@ function ToolbarOssGraph({
|
|||
<MiniButton
|
||||
title='Сбросить изменения'
|
||||
icon={<IconReset size='1.25rem' className='icon-primary' />}
|
||||
disabled={!isModified}
|
||||
onClick={onResetPositions}
|
||||
/>
|
||||
<MiniButton
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { useAuthSuspense } from '@/backend/auth/useAuth';
|
||||
import { useIsProcessingOss } from '@/backend/oss/useIsProcessingOss';
|
||||
import { useMutatingOss } from '@/backend/oss/useMutatingOss';
|
||||
import {
|
||||
IconAdmin,
|
||||
IconAlert,
|
||||
|
@ -35,7 +35,7 @@ function MenuOssTabs() {
|
|||
const router = useConceptNavigation();
|
||||
const { user, isAnonymous } = useAuthSuspense();
|
||||
|
||||
const isProcessing = useIsProcessingOss();
|
||||
const isProcessing = useMutatingOss();
|
||||
|
||||
const role = useRoleStore(state => state.role);
|
||||
const setRole = useRoleStore(state => state.setRole);
|
||||
|
|
|
@ -86,11 +86,9 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren<OssEd
|
|||
const { schema } = useOssSuspense({ itemID: itemID });
|
||||
|
||||
const isOwned = !!user.id && user.id === schema.owner;
|
||||
|
||||
const isMutable = role > UserRole.READER && !schema.read_only;
|
||||
|
||||
const [showTooltip, setShowTooltip] = useState(true);
|
||||
|
||||
const [selected, setSelected] = useState<OperationID[]>([]);
|
||||
|
||||
const showEditInput = useDialogsStore(state => state.showChangeInputSchema);
|
||||
|
|
|
@ -21,13 +21,6 @@ function OssPage() {
|
|||
const { isModified } = useModificationStore();
|
||||
useBlockNavigation(isModified);
|
||||
|
||||
// useBlockNavigation(
|
||||
// isModified &&
|
||||
// schema !== undefined &&
|
||||
// !!user &&
|
||||
// (user.is_staff || user.id == schema.owner || schema.editors.includes(user.id))
|
||||
// );
|
||||
|
||||
if (!itemID) {
|
||||
router.replace(urls.page404);
|
||||
return null;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { useEffect, useState } from 'react';
|
|||
|
||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { IPasswordTokenDTO, IResetPasswordDTO } from '@/backend/auth/api';
|
||||
import { IResetPasswordDTO } from '@/backend/auth/api';
|
||||
import { useResetPassword } from '@/backend/auth/useResetPassword';
|
||||
import InfoError, { ErrorData } from '@/components/info/InfoError';
|
||||
import SubmitButton from '@/components/ui/SubmitButton';
|
||||
|
@ -48,10 +48,7 @@ function PasswordChangePage() {
|
|||
}, [newPassword, newPasswordRepeat, reset]);
|
||||
|
||||
useEffect(() => {
|
||||
const data: IPasswordTokenDTO = {
|
||||
token: token ?? ''
|
||||
};
|
||||
validateToken(data, () => setIsTokenValid(true));
|
||||
validateToken({ token: token ?? '' }, () => setIsTokenValid(true));
|
||||
}, [token, validateToken]);
|
||||
|
||||
return (
|
||||
|
|
|
@ -4,7 +4,7 @@ import clsx from 'clsx';
|
|||
import { useState } from 'react';
|
||||
|
||||
import { useCstUpdate } from '@/backend/rsform/useCstUpdate';
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import useWindowSize from '@/hooks/useWindowSize';
|
||||
import { useMainHeight } from '@/stores/appLayout';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
|
@ -33,7 +33,7 @@ function EditorConstituenta() {
|
|||
|
||||
const [toggleReset, setToggleReset] = useState(false);
|
||||
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
const disabled = !controller.activeCst || !controller.isContentEditable || isProcessing;
|
||||
const isNarrow = !!windowSize.width && windowSize.width <= SIDELIST_LAYOUT_THRESHOLD;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import clsx from 'clsx';
|
|||
|
||||
import { ICstRenameDTO } from '@/backend/rsform/api';
|
||||
import { useCstRename } from '@/backend/rsform/useCstRename';
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { IconEdit } from '@/components/Icons';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
import Overlay from '@/components/ui/Overlay';
|
||||
|
@ -23,7 +23,7 @@ interface EditorControlsProps {
|
|||
function EditorControls({ constituenta, disabled, onEditTerm }: EditorControlsProps) {
|
||||
const { schema } = useRSEdit();
|
||||
const { isModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
const showRenameCst = useDialogsStore(state => state.showRenameCst);
|
||||
const { cstRename } = useCstRename();
|
||||
|
|
|
@ -6,7 +6,7 @@ import { toast } from 'react-toastify';
|
|||
|
||||
import { ICstUpdateDTO } from '@/backend/rsform/api';
|
||||
import { useCstUpdate } from '@/backend/rsform/useCstUpdate';
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { IconChild, IconPredecessor, IconSave } from '@/components/Icons';
|
||||
import { CProps } from '@/components/props';
|
||||
import RefsInput from '@/components/RefsInput';
|
||||
|
@ -45,7 +45,7 @@ function FormConstituenta({
|
|||
const { cstUpdate } = useCstUpdate();
|
||||
const { schema, activeCst } = useRSEdit();
|
||||
const { isModified, setIsModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
const [term, setTerm] = useState(activeCst?.term_raw ?? '');
|
||||
const [textDefinition, setTextDefinition] = useState(activeCst?.definition_raw ?? '');
|
||||
|
|
|
@ -5,7 +5,7 @@ import clsx from 'clsx';
|
|||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { useFindPredecessor } from '@/backend/oss/useFindPredecessor';
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import {
|
||||
IconClone,
|
||||
IconDestroy,
|
||||
|
@ -53,7 +53,7 @@ function ToolbarConstituenta({
|
|||
const showList = usePreferencesStore(state => state.showCstSideList);
|
||||
const toggleList = usePreferencesStore(state => state.toggleShowCstSideList);
|
||||
const { isModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
function viewPredecessor(target: ConstituentaID) {
|
||||
findPredecessor({ target: target }, reference =>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { toast } from 'react-toastify';
|
|||
import { DataCallback } from '@/backend/apiTransport';
|
||||
import { ICheckConstituentaDTO } from '@/backend/rsform/api';
|
||||
import { useCheckConstituenta } from '@/backend/rsform/useCheckConstituenta';
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||
import { CProps } from '@/components/props';
|
||||
import RSInput from '@/components/RSInput';
|
||||
|
@ -65,7 +65,7 @@ function EditorRSExpression({
|
|||
const rsInput = useRef<ReactCodeMirrorRef>(null);
|
||||
const [parseData, setParseData] = useState<IExpressionParse | undefined>(undefined);
|
||||
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
const showControls = usePreferencesStore(state => state.showExpressionControls);
|
||||
const showAST = useDialogsStore(state => state.showShowAST);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { IconControls, IconTree, IconTypeGraph } from '@/components/Icons';
|
||||
import { CProps } from '@/components/props';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
|
@ -12,7 +12,7 @@ interface ToolbarRSExpressionProps {
|
|||
}
|
||||
|
||||
function ToolbarRSExpression({ disabled, showTypeGraph, showAST }: ToolbarRSExpressionProps) {
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
const showControls = usePreferencesStore(state => state.showExpressionControls);
|
||||
const toggleControls = usePreferencesStore(state => state.toggleShowExpressionControls);
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@ import { useIntl } from 'react-intl';
|
|||
|
||||
import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import { useIsProcessingLibrary } from '@/backend/library/useIsProcessingLibrary';
|
||||
import { useLibraryItem } from '@/backend/library/useLibraryItem';
|
||||
import { useMutatingLibrary } from '@/backend/library/useMutatingLibrary';
|
||||
import { useSetEditors } from '@/backend/library/useSetEditors';
|
||||
import { useSetLocation } from '@/backend/library/useSetLocation';
|
||||
import { useSetOwner } from '@/backend/library/useSetOwner';
|
||||
|
@ -26,7 +25,7 @@ import Overlay from '@/components/ui/Overlay';
|
|||
import Tooltip from '@/components/ui/Tooltip';
|
||||
import ValueIcon from '@/components/ui/ValueIcon';
|
||||
import useDropdown from '@/hooks/useDropdown';
|
||||
import { ILibraryItemEditor, LibraryItemID, LibraryItemType } from '@/models/library';
|
||||
import { ILibraryItemEditor } from '@/models/library';
|
||||
import { UserID, UserRole } from '@/models/user';
|
||||
import { useDialogsStore } from '@/stores/dialogs';
|
||||
import { useLibrarySearchStore } from '@/stores/librarySearch';
|
||||
|
@ -36,20 +35,17 @@ import { prefixes } from '@/utils/constants';
|
|||
import { prompts } from '@/utils/labels';
|
||||
|
||||
interface EditorLibraryItemProps {
|
||||
itemID: LibraryItemID;
|
||||
itemType: LibraryItemType;
|
||||
controller: ILibraryItemEditor;
|
||||
}
|
||||
|
||||
function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemProps) {
|
||||
function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
|
||||
const getUserLabel = useLabelUser();
|
||||
const role = useRoleStore(state => state.role);
|
||||
const intl = useIntl();
|
||||
const router = useConceptNavigation();
|
||||
const setGlobalLocation = useLibrarySearchStore(state => state.setLocation);
|
||||
|
||||
const { item } = useLibraryItem({ itemID, itemType });
|
||||
const isProcessing = useIsProcessingLibrary();
|
||||
const isProcessing = useMutatingLibrary();
|
||||
const { isModified } = useModificationStore();
|
||||
|
||||
const { setOwner } = useSetOwner();
|
||||
|
@ -62,47 +58,34 @@ function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemPr
|
|||
const ownerSelector = useDropdown();
|
||||
const onSelectUser = function (newValue: UserID) {
|
||||
ownerSelector.hide();
|
||||
if (newValue === item?.owner) {
|
||||
if (newValue === controller.schema.owner) {
|
||||
return;
|
||||
}
|
||||
if (!window.confirm(prompts.ownerChange)) {
|
||||
return;
|
||||
}
|
||||
setOwner({ itemID: itemID, owner: newValue });
|
||||
setOwner({ itemID: controller.schema.id, owner: newValue });
|
||||
};
|
||||
|
||||
function handleOpenLibrary(event: CProps.EventMouse) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
setGlobalLocation(item.location);
|
||||
setGlobalLocation(controller.schema.location);
|
||||
router.push(urls.library, event.ctrlKey || event.metaKey);
|
||||
}
|
||||
|
||||
function handleEditLocation() {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
showEditLocation({
|
||||
initial: item.location,
|
||||
onChangeLocation: newLocation => setLocation({ itemID: itemID, location: newLocation })
|
||||
initial: controller.schema.location,
|
||||
onChangeLocation: newLocation => setLocation({ itemID: controller.schema.id, location: newLocation })
|
||||
});
|
||||
}
|
||||
|
||||
function handleEditEditors() {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
showEditEditors({
|
||||
editors: item.editors,
|
||||
onChangeEditors: newEditors => setEditors({ itemID: itemID, editors: newEditors })
|
||||
editors: controller.schema.editors,
|
||||
onChangeEditors: newEditors => setEditors({ itemID: controller.schema.id, editors: newEditors })
|
||||
});
|
||||
}
|
||||
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex flex-col'>
|
||||
<div className='flex justify-stretch sm:mb-1 max-w-[30rem] gap-3'>
|
||||
|
@ -116,7 +99,7 @@ function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemPr
|
|||
<ValueIcon
|
||||
className='text-ellipsis flex-grow'
|
||||
icon={<IconFolderEdit size='1.25rem' className='icon-primary' />}
|
||||
value={item.location}
|
||||
value={controller.schema.location}
|
||||
title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
|
||||
onClick={handleEditLocation}
|
||||
disabled={isModified || isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER}
|
||||
|
@ -128,7 +111,7 @@ function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemPr
|
|||
{ownerSelector.isOpen ? (
|
||||
<SelectUser
|
||||
className='w-[25rem] sm:w-[26rem] text-sm'
|
||||
value={item.owner ?? undefined}
|
||||
value={controller.schema.owner ?? undefined}
|
||||
onSelectValue={onSelectUser}
|
||||
/>
|
||||
) : null}
|
||||
|
@ -137,7 +120,7 @@ function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemPr
|
|||
<ValueIcon
|
||||
className='sm:mb-1'
|
||||
icon={<IconOwner size='1.25rem' className='icon-primary' />}
|
||||
value={getUserLabel(item.owner)}
|
||||
value={getUserLabel(controller.schema.owner)}
|
||||
title={controller.isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Владелец'}
|
||||
onClick={ownerSelector.toggle}
|
||||
disabled={isModified || isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER}
|
||||
|
@ -148,13 +131,13 @@ function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemPr
|
|||
id='editor_stats'
|
||||
dense
|
||||
icon={<IconEditor size='1.25rem' className='icon-primary' />}
|
||||
value={item.editors.length}
|
||||
value={controller.schema.editors.length}
|
||||
onClick={handleEditEditors}
|
||||
disabled={isModified || isProcessing || role < UserRole.OWNER}
|
||||
/>
|
||||
<Tooltip anchorSelect='#editor_stats' layer='z-modalTooltip'>
|
||||
<Suspense fallback={<Loader scale={2} />}>
|
||||
<InfoUsers items={item?.editors ?? []} prefix={prefixes.user_editors} header='Редакторы' />
|
||||
<InfoUsers items={controller.schema.editors} prefix={prefixes.user_editors} header='Редакторы' />
|
||||
</Suspense>
|
||||
</Tooltip>
|
||||
|
||||
|
@ -162,7 +145,7 @@ function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemPr
|
|||
dense
|
||||
disabled
|
||||
icon={<IconDateUpdate size='1.25rem' className='text-ok-600' />}
|
||||
value={new Date(item.time_update).toLocaleString(intl.locale)}
|
||||
value={new Date(controller.schema.time_update).toLocaleString(intl.locale)}
|
||||
title='Дата обновления'
|
||||
/>
|
||||
|
||||
|
@ -170,7 +153,7 @@ function EditorLibraryItem({ itemID, itemType, controller }: EditorLibraryItemPr
|
|||
dense
|
||||
disabled
|
||||
icon={<IconDateCreate size='1.25rem' className='text-ok-600' />}
|
||||
value={new Date(item.time_create).toLocaleString(intl.locale, {
|
||||
value={new Date(controller.schema.time_create).toLocaleString(intl.locale, {
|
||||
year: '2-digit',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import FlexColumn from '@/components/ui/FlexColumn';
|
||||
import { LibraryItemType } from '@/models/library';
|
||||
import { useModificationStore } from '@/stores/modification';
|
||||
import { globals } from '@/utils/constants';
|
||||
|
||||
|
@ -46,7 +45,7 @@ function EditorRSFormCard() {
|
|||
>
|
||||
<FlexColumn className='flex-shrink'>
|
||||
<FormRSForm id={globals.library_item_editor} />
|
||||
<EditorLibraryItem itemID={controller.schema.id} itemType={LibraryItemType.RSFORM} controller={controller} />
|
||||
<EditorLibraryItem controller={controller} />
|
||||
</FlexColumn>
|
||||
|
||||
{controller.schema ? <RSFormStats stats={controller.schema.stats} isArchive={controller.isArchive} /> : null}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
|||
import { urls } from '@/app/urls';
|
||||
import { ILibraryUpdateDTO } from '@/backend/library/api';
|
||||
import { useUpdateItem } from '@/backend/library/useUpdateItem';
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { IconSave } from '@/components/Icons';
|
||||
import SelectVersion from '@/components/select/SelectVersion';
|
||||
import Label from '@/components/ui/Label';
|
||||
|
@ -31,7 +31,7 @@ function FormRSForm({ id }: FormRSFormProps) {
|
|||
const schema = controller.schema;
|
||||
const { updateItem: update } = useUpdateItem();
|
||||
const { isModified, setIsModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
const [title, setTitle] = useState(schema.title);
|
||||
const [alias, setAlias] = useState(schema.alias);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useIsProcessingLibrary } from '@/backend/library/useIsProcessingLibrary';
|
||||
import { useMutatingLibrary } from '@/backend/library/useMutatingLibrary';
|
||||
import { useSetAccessPolicy } from '@/backend/library/useSetAccessPolicy';
|
||||
import { VisibilityIcon } from '@/components/DomainIcons';
|
||||
import { IconImmutable, IconMutable } from '@/components/Icons';
|
||||
|
@ -23,7 +23,7 @@ interface ToolbarItemAccessProps {
|
|||
|
||||
function ToolbarItemAccess({ visible, toggleVisible, readOnly, toggleReadOnly, controller }: ToolbarItemAccessProps) {
|
||||
const role = useRoleStore(state => state.role);
|
||||
const isProcessing = useIsProcessingLibrary();
|
||||
const isProcessing = useMutatingLibrary();
|
||||
const policy = controller.schema.access_policy;
|
||||
const { setAccessPolicy } = useSetAccessPolicy();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useIsProcessingLibrary } from '@/backend/library/useIsProcessingLibrary';
|
||||
import { useMutatingLibrary } from '@/backend/library/useMutatingLibrary';
|
||||
import { IconDestroy, IconSave, IconShare } from '@/components/Icons';
|
||||
import BadgeHelp from '@/components/info/BadgeHelp';
|
||||
import MiniSelectorOSS from '@/components/select/MiniSelectorOSS';
|
||||
|
@ -26,7 +26,7 @@ interface ToolbarRSFormCardProps {
|
|||
function ToolbarRSFormCard({ controller, onSubmit }: ToolbarRSFormCardProps) {
|
||||
const role = useRoleStore(state => state.role);
|
||||
const { isModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingLibrary();
|
||||
const isProcessing = useMutatingLibrary();
|
||||
const canSave = isModified && !isProcessing;
|
||||
|
||||
const ossSelector = (() => {
|
||||
|
|
|
@ -4,7 +4,7 @@ import fileDownload from 'js-file-download';
|
|||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { IconCSV } from '@/components/Icons';
|
||||
import { type RowSelectionState } from '@/components/ui/DataTable';
|
||||
import MiniButton from '@/components/ui/MiniButton';
|
||||
|
@ -24,7 +24,7 @@ import ToolbarRSList from './ToolbarRSList';
|
|||
function EditorRSList() {
|
||||
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
|
||||
const controller = useRSEdit();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
const [filtered, setFiltered] = useState<IConstituenta[]>(controller.schema.items);
|
||||
const [filterText, setFilterText] = useState('');
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { CstTypeIcon } from '@/components/DomainIcons';
|
||||
import {
|
||||
IconClone,
|
||||
|
@ -25,7 +25,7 @@ import { useRSEdit } from '../RSEditContext';
|
|||
|
||||
function ToolbarRSList() {
|
||||
const controller = useRSEdit();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
const insertMenu = useDropdown();
|
||||
|
||||
return (
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
import { useStoreApi } from 'reactflow';
|
||||
import { useDebounce } from 'use-debounce';
|
||||
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import InfoConstituenta from '@/components/info/InfoConstituenta';
|
||||
import SelectedCounter from '@/components/info/SelectedCounter';
|
||||
import { CProps } from '@/components/props';
|
||||
|
@ -54,7 +54,7 @@ function TGFlow() {
|
|||
const flow = useReactFlow();
|
||||
const store = useStoreApi();
|
||||
const { addSelectedNodes } = store.getState();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
const showParams = useDialogsStore(state => state.showGraphParams);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import clsx from 'clsx';
|
||||
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import {
|
||||
IconClustering,
|
||||
IconClusteringOff,
|
||||
|
@ -48,7 +48,7 @@ function ToolbarTermGraph({
|
|||
onSaveImage
|
||||
}: ToolbarTermGraphProps) {
|
||||
const controller = useRSEdit();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
const showTypeGraph = useDialogsStore(state => state.showShowTypeGraph);
|
||||
|
||||
function handleShowTypeGraph() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { useAuthSuspense } from '@/backend/auth/useAuth';
|
|||
import { useCstSubstitute } from '@/backend/rsform/useCstSubstitute';
|
||||
import { useDownloadRSForm } from '@/backend/rsform/useDownloadRSForm';
|
||||
import { useInlineSynthesis } from '@/backend/rsform/useInlineSynthesis';
|
||||
import { useIsProcessingRSForm } from '@/backend/rsform/useIsProcessingRSForm';
|
||||
import { useMutatingRSForm } from '@/backend/rsform/useMutatingRSForm';
|
||||
import { useProduceStructure } from '@/backend/rsform/useProduceStructure';
|
||||
import { useResetAliases } from '@/backend/rsform/useResetAliases';
|
||||
import { useRestoreOrder } from '@/backend/rsform/useRestoreOrder';
|
||||
|
@ -63,7 +63,7 @@ function MenuRSTabs() {
|
|||
const role = useRoleStore(state => state.role);
|
||||
const setRole = useRoleStore(state => state.setRole);
|
||||
const { isModified } = useModificationStore();
|
||||
const isProcessing = useIsProcessingRSForm();
|
||||
const isProcessing = useMutatingRSForm();
|
||||
|
||||
const { resetAliases } = useResetAliases();
|
||||
const { restoreOrder } = useRestoreOrder();
|
||||
|
|
|
@ -6,7 +6,7 @@ import { useParams } from 'react-router';
|
|||
|
||||
import { useBlockNavigation, useConceptNavigation } from '@/app/Navigation/NavigationContext';
|
||||
import { urls } from '@/app/urls';
|
||||
import InfoError, { ErrorData } from '@/components/info/InfoError';
|
||||
import { ErrorData } from '@/components/info/InfoError';
|
||||
import Divider from '@/components/ui/Divider';
|
||||
import TextURL from '@/components/ui/TextURL';
|
||||
import useQueryStrings from '@/hooks/useQueryStrings';
|
||||
|
@ -33,6 +33,7 @@ function RSFormPage() {
|
|||
}
|
||||
return (
|
||||
<ErrorBoundary
|
||||
onError={filterErrors}
|
||||
FallbackComponent={({ error }) => (
|
||||
<ProcessError error={error as ErrorData} isArchive={!!version} itemID={itemID} />
|
||||
)}
|
||||
|
@ -47,6 +48,13 @@ function RSFormPage() {
|
|||
export default RSFormPage;
|
||||
|
||||
// ====== Internals =========
|
||||
const filterErrors = (error: Error) => {
|
||||
if (axios.isAxiosError(error) && error.response && (error.response.status === 404 || error.response.status === 403)) {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
};
|
||||
|
||||
function ProcessError({
|
||||
error,
|
||||
isArchive,
|
||||
|
@ -55,7 +63,7 @@ function ProcessError({
|
|||
error: ErrorData;
|
||||
isArchive: boolean;
|
||||
itemID?: LibraryItemID;
|
||||
}): React.ReactElement {
|
||||
}): React.ReactElement | null {
|
||||
if (axios.isAxiosError(error) && error.response) {
|
||||
if (error.response.status === 404) {
|
||||
return (
|
||||
|
@ -77,5 +85,5 @@ function ProcessError({
|
|||
);
|
||||
}
|
||||
}
|
||||
return <InfoError error={error} />;
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user