Portal/rsconcept/frontend/src/context/RSFormContext.tsx

593 lines
17 KiB
TypeScript
Raw Normal View History

2024-06-07 20:17:03 +03:00
'use client';
import { createContext, useCallback, useContext, useMemo, useState } from 'react';
import { DataCallback } from '@/backend/apiTransport';
2024-06-07 20:17:03 +03:00
import {
patchLibraryItem,
patchSetAccessPolicy,
patchSetEditors,
patchSetLocation,
patchSetOwner,
postCreateVersion
} from '@/backend/library';
import { postFindPredecessor } from '@/backend/oss';
import {
2024-06-07 20:17:03 +03:00
getTRSFile,
patchDeleteConstituenta,
2024-07-31 14:01:39 +03:00
patchInlineSynthesis,
2024-06-07 20:17:03 +03:00
patchMoveConstituenta,
patchProduceStructure,
patchRenameConstituenta,
patchResetAliases,
patchRestoreOrder,
patchSubstituteConstituents,
2024-07-31 14:01:39 +03:00
patchUpdateConstituenta,
2024-06-07 20:17:03 +03:00
patchUploadTRS,
postCreateConstituenta
} from '@/backend/rsforms';
import { deleteVersion, patchRestoreVersion, patchVersion } from '@/backend/versions';
2024-06-07 20:17:03 +03:00
import { type ErrorData } from '@/components/info/InfoError';
import useRSFormDetails from '@/hooks/useRSFormDetails';
import { AccessPolicy, ILibraryItem, IVersionData, VersionID } from '@/models/library';
import { ILibraryUpdateData } from '@/models/library';
2024-07-20 18:26:32 +03:00
import { ICstSubstituteData } from '@/models/oss';
2024-06-07 20:17:03 +03:00
import {
ConstituentaID,
IConstituentaList,
IConstituentaMeta,
IConstituentaReference,
2024-06-07 20:17:03 +03:00
ICstCreateData,
ICstMovetoData,
ICstRenameData,
ICstUpdateData,
IInlineSynthesisData,
IRSForm,
IRSFormData,
IRSFormUploadData,
ITargetCst
} from '@/models/rsform';
import { UserID } from '@/models/user';
import { contextOutsideScope } from '@/utils/labels';
import { useAuth } from './AuthContext';
import { useGlobalOss } from './GlobalOssContext';
2024-06-07 20:17:03 +03:00
import { useLibrary } from './LibraryContext';
interface IRSFormContext {
schema?: IRSForm;
itemID: string;
versionID?: string;
loading: boolean;
errorLoading: ErrorData;
processing: boolean;
processingError: ErrorData;
isArchive: boolean;
isOwned: boolean;
update: (data: ILibraryUpdateData, callback?: DataCallback<ILibraryItem>) => void;
download: (callback: DataCallback<Blob>) => void;
upload: (data: IRSFormUploadData, callback: () => void) => void;
setOwner: (newOwner: UserID, callback?: () => void) => void;
setAccessPolicy: (newPolicy: AccessPolicy, callback?: () => void) => void;
setLocation: (newLocation: string, callback?: () => void) => void;
setEditors: (newEditors: UserID[], callback?: () => void) => void;
resetAliases: (callback: () => void) => void;
restoreOrder: (callback: () => void) => void;
produceStructure: (data: ITargetCst, callback?: DataCallback<ConstituentaID[]>) => void;
inlineSynthesis: (data: IInlineSynthesisData, callback?: DataCallback<IRSFormData>) => void;
cstCreate: (data: ICstCreateData, callback?: DataCallback<IConstituentaMeta>) => void;
cstRename: (data: ICstRenameData, callback?: DataCallback<IConstituentaMeta>) => void;
cstSubstitute: (data: ICstSubstituteData, callback?: () => void) => void;
cstUpdate: (data: ICstUpdateData, callback?: DataCallback<IConstituentaMeta>) => void;
cstDelete: (data: IConstituentaList, callback?: () => void) => void;
cstMoveTo: (data: ICstMovetoData, callback?: () => void) => void;
findPredecessor: (data: ITargetCst, callback: (reference: IConstituentaReference) => void) => void;
2024-06-07 20:17:03 +03:00
versionCreate: (data: IVersionData, callback?: (version: VersionID) => void) => void;
versionUpdate: (target: VersionID, data: IVersionData, callback?: () => void) => void;
versionDelete: (target: VersionID, callback?: () => void) => void;
versionRestore: (target: string, callback?: () => void) => void;
}
const RSFormContext = createContext<IRSFormContext | null>(null);
export const useRSForm = () => {
const context = useContext(RSFormContext);
if (context === null) {
throw new Error(contextOutsideScope('useRSForm', 'RSFormState'));
}
return context;
};
interface RSFormStateProps {
itemID: string;
versionID?: string;
}
2024-09-19 17:48:48 +03:00
export const RSFormState = ({ itemID, versionID, children }: React.PropsWithChildren<RSFormStateProps>) => {
2024-06-07 20:17:03 +03:00
const library = useLibrary();
const oss = useGlobalOss();
2024-06-07 20:17:03 +03:00
const { user } = useAuth();
const rsData = useRSFormDetails({ target: itemID, version: versionID });
2024-06-07 20:17:03 +03:00
const [processing, setProcessing] = useState(false);
const [processingError, setProcessingError] = useState<ErrorData>(undefined);
const isOwned = useMemo(() => {
return user?.id === rsData.schema?.owner || false;
}, [user, rsData.schema?.owner]);
2024-06-07 20:17:03 +03:00
const isArchive = useMemo(() => !!versionID, [versionID]);
const update = useCallback(
(data: ILibraryUpdateData, callback?: DataCallback<ILibraryItem>) => {
if (!rsData.schema) {
2024-06-07 20:17:03 +03:00
return;
}
setProcessingError(undefined);
patchLibraryItem(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(Object.assign(rsData.schema!, newData));
2024-06-07 20:17:03 +03:00
library.localUpdateItem(newData);
oss.invalidateItem(newData.id);
2024-12-04 22:52:45 +03:00
callback?.(newData);
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library, oss]
2024-06-07 20:17:03 +03:00
);
const upload = useCallback(
(data: IRSFormUploadData, callback?: () => void) => {
if (!rsData.schema) {
2024-06-07 20:17:03 +03:00
return;
}
setProcessingError(undefined);
patchUploadTRS(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData);
2024-06-07 20:17:03 +03:00
library.localUpdateItem(newData);
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library]
2024-06-07 20:17:03 +03:00
);
const setOwner = useCallback(
(newOwner: UserID, callback?: () => void) => {
setProcessingError(undefined);
patchSetOwner(itemID, {
data: {
user: newOwner
},
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: () => {
rsData.partialUpdate({ owner: newOwner });
library.localUpdateItem({ id: Number(itemID), owner: newOwner });
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library]
2024-06-07 20:17:03 +03:00
);
const setAccessPolicy = useCallback(
(newPolicy: AccessPolicy, callback?: () => void) => {
if (!rsData.schema) {
2024-06-07 20:17:03 +03:00
return;
}
setProcessingError(undefined);
patchSetAccessPolicy(itemID, {
data: {
access_policy: newPolicy
},
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: () => {
rsData.partialUpdate({ access_policy: newPolicy });
library.localUpdateItem({ id: Number(itemID), access_policy: newPolicy });
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library]
2024-06-07 20:17:03 +03:00
);
const setLocation = useCallback(
(newLocation: string, callback?: () => void) => {
if (!rsData.schema) {
2024-06-07 20:17:03 +03:00
return;
}
setProcessingError(undefined);
patchSetLocation(itemID, {
data: {
location: newLocation
},
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: () => {
rsData.partialUpdate({ location: newLocation });
library.localUpdateItem({ id: Number(itemID), location: newLocation });
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library]
2024-06-07 20:17:03 +03:00
);
const setEditors = useCallback(
(newEditors: UserID[], callback?: () => void) => {
if (!rsData.schema) {
2024-06-07 20:17:03 +03:00
return;
}
setProcessingError(undefined);
patchSetEditors(itemID, {
2024-06-07 20:17:03 +03:00
data: {
users: newEditors
},
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: () => {
rsData.partialUpdate({ editors: newEditors });
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData]
2024-06-07 20:17:03 +03:00
);
const resetAliases = useCallback(
(callback?: () => void) => {
if (!rsData.schema || !user) {
2024-06-07 20:17:03 +03:00
return;
}
setProcessingError(undefined);
patchResetAliases(itemID, {
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(newData.id);
oss.invalidateItem(newData.id);
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, user, library, oss]
2024-06-07 20:17:03 +03:00
);
const restoreOrder = useCallback(
(callback?: () => void) => {
if (!rsData.schema || !user) {
2024-06-07 20:17:03 +03:00
return;
}
setProcessingError(undefined);
patchRestoreOrder(itemID, {
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(newData.id);
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, user, library]
2024-06-07 20:17:03 +03:00
);
const produceStructure = useCallback(
(data: ITargetCst, callback?: DataCallback<ConstituentaID[]>) => {
setProcessingError(undefined);
patchProduceStructure(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData.schema);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(newData.schema.id);
oss.invalidateItem(newData.schema.id);
2024-12-04 22:52:45 +03:00
callback?.(newData.cst_list);
2024-06-07 20:17:03 +03:00
}
});
},
[rsData, itemID, library, oss]
2024-06-07 20:17:03 +03:00
);
const download = useCallback(
(callback: DataCallback<Blob>) => {
setProcessingError(undefined);
getTRSFile(itemID, String(rsData.schema?.version ?? ''), {
2024-06-07 20:17:03 +03:00
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: callback
});
},
[itemID, rsData]
2024-06-07 20:17:03 +03:00
);
const cstCreate = useCallback(
(data: ICstCreateData, callback?: DataCallback<IConstituentaMeta>) => {
setProcessingError(undefined);
2024-07-20 18:26:32 +03:00
postCreateConstituenta(itemID, {
2024-06-07 20:17:03 +03:00
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData.schema);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(newData.schema.id);
oss.invalidateItem(newData.schema.id);
2024-12-04 22:52:45 +03:00
callback?.(newData.new_cst);
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library, oss]
2024-06-07 20:17:03 +03:00
);
const cstDelete = useCallback(
(data: IConstituentaList, callback?: () => void) => {
setProcessingError(undefined);
patchDeleteConstituenta(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(newData.id);
oss.invalidateItem(newData.id);
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library, oss]
2024-06-07 20:17:03 +03:00
);
const cstUpdate = useCallback(
(data: ICstUpdateData, callback?: DataCallback<IConstituentaMeta>) => {
setProcessingError(undefined);
2024-07-31 14:01:39 +03:00
patchUpdateConstituenta(itemID, {
2024-06-07 20:17:03 +03:00
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData =>
rsData.reload(setProcessing, () => {
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(Number(itemID));
oss.invalidateItem(Number(itemID));
2024-12-04 22:52:45 +03:00
callback?.(newData);
2024-06-07 20:17:03 +03:00
})
});
},
[itemID, rsData, library, oss]
2024-06-07 20:17:03 +03:00
);
const cstRename = useCallback(
(data: ICstRenameData, callback?: DataCallback<IConstituentaMeta>) => {
setProcessingError(undefined);
patchRenameConstituenta(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData.schema);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(newData.schema.id);
oss.invalidateItem(newData.schema.id);
2024-12-04 22:52:45 +03:00
callback?.(newData.new_cst);
2024-06-07 20:17:03 +03:00
}
});
},
[rsData, itemID, library, oss]
2024-06-07 20:17:03 +03:00
);
const cstSubstitute = useCallback(
(data: ICstSubstituteData, callback?: () => void) => {
setProcessingError(undefined);
patchSubstituteConstituents(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(newData.id);
oss.invalidateItem(newData.id);
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[rsData, itemID, library, oss]
2024-06-07 20:17:03 +03:00
);
const cstMoveTo = useCallback(
(data: ICstMovetoData, callback?: () => void) => {
setProcessingError(undefined);
patchMoveConstituenta(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(Number(itemID));
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library]
2024-06-07 20:17:03 +03:00
);
const versionCreate = useCallback(
(data: IVersionData, callback?: (version: number) => void) => {
setProcessingError(undefined);
postCreateVersion(itemID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData.schema);
2024-06-07 20:17:03 +03:00
library.localUpdateTimestamp(Number(itemID));
2024-12-04 22:52:45 +03:00
callback?.(newData.version);
2024-06-07 20:17:03 +03:00
}
});
},
[itemID, rsData, library]
2024-06-07 20:17:03 +03:00
);
const findPredecessor = useCallback((data: ITargetCst, callback: (reference: IConstituentaReference) => void) => {
setProcessingError(undefined);
postFindPredecessor({
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: callback
});
}, []);
2024-06-07 20:17:03 +03:00
const versionUpdate = useCallback(
(target: number, data: IVersionData, callback?: () => void) => {
setProcessingError(undefined);
patchVersion(String(target), {
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: () => {
const newVersions = rsData.schema!.versions.map(prev => {
2024-06-07 20:17:03 +03:00
if (prev.id === target) {
prev.description = data.description;
prev.version = data.version;
return prev;
} else {
return prev;
}
});
rsData.partialUpdate({ versions: newVersions });
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[rsData]
2024-06-07 20:17:03 +03:00
);
const versionDelete = useCallback(
(target: number, callback?: () => void) => {
setProcessingError(undefined);
deleteVersion(String(target), {
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: () => {
const newVersions = rsData.schema!.versions.filter(prev => prev.id !== target);
rsData.partialUpdate({ versions: newVersions });
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[rsData]
2024-06-07 20:17:03 +03:00
);
const versionRestore = useCallback(
(target: string, callback?: () => void) => {
setProcessingError(undefined);
patchRestoreVersion(target, {
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
2024-06-16 15:59:42 +03:00
onSuccess: newData => {
rsData.setSchema(newData);
2024-06-16 15:59:42 +03:00
library.localUpdateItem(newData);
2024-12-04 22:52:45 +03:00
callback?.();
2024-06-07 20:17:03 +03:00
}
});
},
[rsData, library]
2024-06-07 20:17:03 +03:00
);
const inlineSynthesis = useCallback(
(data: IInlineSynthesisData, callback?: DataCallback<IRSFormData>) => {
setProcessingError(undefined);
patchInlineSynthesis({
data: data,
showError: true,
setLoading: setProcessing,
onError: setProcessingError,
onSuccess: newData => {
rsData.setSchema(newData);
library.localUpdateTimestamp(newData.id);
oss.invalidateItem(newData.id);
2024-12-04 22:52:45 +03:00
callback?.(newData);
2024-06-07 20:17:03 +03:00
}
});
},
[rsData, library, oss]
2024-06-07 20:17:03 +03:00
);
return (
<RSFormContext.Provider
value={{
schema: rsData.schema,
2024-06-07 20:17:03 +03:00
itemID,
versionID,
loading: rsData.loading,
errorLoading: rsData.error,
2024-06-07 20:17:03 +03:00
processing,
processingError,
isOwned,
isArchive,
update,
download,
upload,
restoreOrder,
resetAliases,
produceStructure,
inlineSynthesis,
setOwner,
setEditors,
setAccessPolicy,
setLocation,
cstUpdate,
cstCreate,
cstRename,
cstSubstitute,
cstDelete,
cstMoveTo,
findPredecessor,
2024-06-07 20:17:03 +03:00
versionCreate,
versionUpdate,
versionDelete,
versionRestore
}}
>
{children}
</RSFormContext.Provider>
);
};