2023-08-01 20:14:03 +03:00
|
|
|
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
|
|
|
|
|
|
import { ErrorInfo } from '../components/BackendError';
|
2023-09-11 20:31:54 +03:00
|
|
|
import { matchLibraryItem } from '../models/library';
|
|
|
|
import { ILibraryItem } from '../models/library';
|
2023-11-01 13:41:32 +03:00
|
|
|
import { ILibraryFilter } from '../models/miscelanious';
|
2023-11-04 01:29:21 +03:00
|
|
|
import { IRSForm, IRSFormCreateData, IRSFormData, loadRSFormData } from '../models/rsform';
|
|
|
|
import { DataCallback, deleteLibraryItem, getLibrary, getRSFormDetails, getTemplates, postCloneLibraryItem, postNewRSForm } from '../utils/backendAPI';
|
2023-08-11 15:53:18 +03:00
|
|
|
import { useAuth } from './AuthContext';
|
2023-08-01 20:14:03 +03:00
|
|
|
|
|
|
|
interface ILibraryContext {
|
2023-08-25 22:51:20 +03:00
|
|
|
items: ILibraryItem[]
|
2023-11-01 13:41:32 +03:00
|
|
|
templates: ILibraryItem[]
|
2023-08-01 20:14:03 +03:00
|
|
|
loading: boolean
|
2023-08-09 17:19:12 +03:00
|
|
|
processing: boolean
|
2023-08-01 20:14:03 +03:00
|
|
|
error: ErrorInfo
|
|
|
|
setError: (error: ErrorInfo) => void
|
2023-11-04 01:29:21 +03:00
|
|
|
|
2023-11-01 13:41:32 +03:00
|
|
|
applyFilter: (params: ILibraryFilter) => ILibraryItem[]
|
2023-11-04 01:29:21 +03:00
|
|
|
retrieveTemplate: (templateID: number, callback: (schema: IRSForm) => void) => void
|
2023-11-01 13:41:32 +03:00
|
|
|
createItem: (data: IRSFormCreateData, callback?: DataCallback<ILibraryItem>) => void
|
|
|
|
cloneItem: (target: number, data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => void
|
|
|
|
destroyItem: (target: number, callback?: () => void) => void
|
2023-08-01 20:14:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const LibraryContext = createContext<ILibraryContext | null>(null)
|
|
|
|
export const useLibrary = (): ILibraryContext => {
|
|
|
|
const context = useContext(LibraryContext);
|
2023-08-22 20:29:07 +03:00
|
|
|
if (context === null) {
|
2023-08-01 20:14:03 +03:00
|
|
|
throw new Error(
|
|
|
|
'useLibrary has to be used within <LibraryState.Provider>'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface LibraryStateProps {
|
|
|
|
children: React.ReactNode
|
|
|
|
}
|
|
|
|
|
|
|
|
export const LibraryState = ({ children }: LibraryStateProps) => {
|
2023-11-04 01:29:21 +03:00
|
|
|
const [ items, setItems ] = useState<ILibraryItem[]>([]);
|
|
|
|
const [ templates, setTemplates ] = useState<ILibraryItem[]>([]);
|
2023-08-09 17:19:12 +03:00
|
|
|
const [ loading, setLoading ] = useState(false);
|
|
|
|
const [ processing, setProcessing ] = useState(false);
|
|
|
|
const [ error, setError ] = useState<ErrorInfo>(undefined);
|
2023-08-11 15:53:18 +03:00
|
|
|
const { user } = useAuth();
|
2023-08-01 20:14:03 +03:00
|
|
|
|
2023-11-04 01:29:21 +03:00
|
|
|
const [ cachedTemplates, setCachedTemplates ] = useState<IRSForm[]>([]);
|
|
|
|
|
2023-11-01 13:41:32 +03:00
|
|
|
const applyFilter = useCallback(
|
2023-08-01 20:14:03 +03:00
|
|
|
(params: ILibraryFilter) => {
|
|
|
|
let result = items;
|
2023-08-27 00:19:19 +03:00
|
|
|
if (params.is_owned) {
|
|
|
|
result = result.filter(item => item.owner === user?.id);
|
2023-08-01 20:14:03 +03:00
|
|
|
}
|
|
|
|
if (params.is_common !== undefined) {
|
2023-08-25 22:51:20 +03:00
|
|
|
result = result.filter(item => item.is_common === params.is_common);
|
2023-08-01 20:14:03 +03:00
|
|
|
}
|
2023-08-27 00:19:19 +03:00
|
|
|
if (params.is_canonical !== undefined) {
|
|
|
|
result = result.filter(item => item.is_canonical === params.is_canonical);
|
|
|
|
}
|
|
|
|
if (params.is_subscribed !== undefined) {
|
|
|
|
result = result.filter(item => user?.subscriptions.includes(item.id));
|
|
|
|
}
|
|
|
|
if (params.is_personal !== undefined) {
|
|
|
|
result = result.filter(item => user?.subscriptions.includes(item.id) || item.owner === user?.id);
|
|
|
|
}
|
|
|
|
if (params.query) {
|
|
|
|
result = result.filter(item => matchLibraryItem(params.query!, item));
|
2023-08-01 20:14:03 +03:00
|
|
|
}
|
|
|
|
return result;
|
2023-08-26 17:26:49 +03:00
|
|
|
}, [items, user]);
|
2023-08-01 20:14:03 +03:00
|
|
|
|
2023-11-04 01:29:21 +03:00
|
|
|
const retrieveTemplate = useCallback(
|
|
|
|
(templateID: number, callback: (schema: IRSForm) => void) => {
|
|
|
|
const cached = cachedTemplates.find(schema => schema.id == templateID);
|
|
|
|
if (cached) {
|
|
|
|
callback(cached);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setError(undefined);
|
|
|
|
getRSFormDetails(String(templateID), {
|
|
|
|
showError: true,
|
|
|
|
setLoading: setLoading,
|
|
|
|
onError: error => setError(error),
|
|
|
|
onSuccess: data => {
|
|
|
|
const schema = loadRSFormData(data);
|
|
|
|
setCachedTemplates(prev => ([...prev, schema]));
|
|
|
|
callback(schema);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}, [cachedTemplates]);
|
|
|
|
|
2023-08-01 20:14:03 +03:00
|
|
|
const reload = useCallback(
|
2023-08-11 15:53:18 +03:00
|
|
|
(callback?: () => void) => {
|
2023-08-01 20:14:03 +03:00
|
|
|
setItems([]);
|
|
|
|
setError(undefined);
|
|
|
|
getLibrary({
|
|
|
|
setLoading: setLoading,
|
|
|
|
showError: true,
|
2023-08-22 22:38:27 +03:00
|
|
|
onError: error => setError(error),
|
|
|
|
onSuccess: newData => {
|
2023-08-11 15:53:18 +03:00
|
|
|
setItems(newData);
|
|
|
|
if (callback) callback();
|
|
|
|
}
|
2023-08-01 20:14:03 +03:00
|
|
|
});
|
2023-11-01 13:41:32 +03:00
|
|
|
|
|
|
|
setTemplates([]);
|
|
|
|
getTemplates({
|
|
|
|
showError: true,
|
|
|
|
onSuccess: newData => setTemplates(newData)
|
|
|
|
});
|
2023-08-01 20:14:03 +03:00
|
|
|
}, []);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
reload();
|
2023-08-11 15:53:18 +03:00
|
|
|
}, [reload, user]);
|
2023-08-09 17:19:12 +03:00
|
|
|
|
2023-11-01 13:41:32 +03:00
|
|
|
const createItem = useCallback(
|
2023-08-25 22:51:20 +03:00
|
|
|
(data: IRSFormCreateData, callback?: DataCallback<ILibraryItem>) => {
|
2023-08-09 17:19:12 +03:00
|
|
|
setError(undefined);
|
|
|
|
postNewRSForm({
|
|
|
|
data: data,
|
|
|
|
showError: true,
|
|
|
|
setLoading: setProcessing,
|
2023-08-25 22:51:20 +03:00
|
|
|
onError: error => setError(error),
|
2023-08-27 15:39:49 +03:00
|
|
|
onSuccess: newSchema => reload(() => {
|
|
|
|
if (user && !user.subscriptions.includes(newSchema.id)) {
|
|
|
|
user.subscriptions.push(newSchema.id);
|
|
|
|
}
|
2023-08-09 17:19:12 +03:00
|
|
|
if (callback) callback(newSchema);
|
2023-08-27 15:39:49 +03:00
|
|
|
})
|
2023-08-09 17:19:12 +03:00
|
|
|
});
|
2023-08-27 15:39:49 +03:00
|
|
|
}, [reload, user]);
|
2023-08-01 20:14:03 +03:00
|
|
|
|
2023-11-01 13:41:32 +03:00
|
|
|
const destroyItem = useCallback(
|
2023-08-22 22:38:27 +03:00
|
|
|
(target: number, callback?: () => void) => {
|
2023-08-11 19:28:12 +03:00
|
|
|
setError(undefined)
|
2023-08-25 22:51:20 +03:00
|
|
|
deleteLibraryItem(String(target), {
|
2023-08-11 19:28:12 +03:00
|
|
|
showError: true,
|
|
|
|
setLoading: setProcessing,
|
|
|
|
onError: error => setError(error),
|
|
|
|
onSuccess: () => reload(() => {
|
2023-08-27 15:39:49 +03:00
|
|
|
if (user && user.subscriptions.includes(target)) {
|
|
|
|
user.subscriptions.splice(user.subscriptions.findIndex(item => item === target), 1);
|
|
|
|
}
|
2023-08-11 19:28:12 +03:00
|
|
|
if (callback) callback();
|
|
|
|
})
|
|
|
|
});
|
2023-08-27 15:39:49 +03:00
|
|
|
}, [setError, reload, user]);
|
2023-08-11 19:28:12 +03:00
|
|
|
|
2023-11-01 13:41:32 +03:00
|
|
|
const cloneItem = useCallback(
|
2023-08-22 22:38:27 +03:00
|
|
|
(target: number, data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => {
|
2023-08-11 19:28:12 +03:00
|
|
|
if (!user) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setError(undefined)
|
2023-08-25 22:51:20 +03:00
|
|
|
postCloneLibraryItem(String(target), {
|
2023-08-11 19:28:12 +03:00
|
|
|
data: data,
|
|
|
|
showError: true,
|
|
|
|
setLoading: setProcessing,
|
|
|
|
onError: error => setError(error),
|
|
|
|
onSuccess: newSchema => reload(() => {
|
2023-08-27 15:39:49 +03:00
|
|
|
if (user && !user.subscriptions.includes(newSchema.id)) {
|
|
|
|
user.subscriptions.push(newSchema.id);
|
|
|
|
}
|
2023-08-11 19:28:12 +03:00
|
|
|
if (callback) callback(newSchema);
|
|
|
|
})
|
|
|
|
});
|
|
|
|
}, [reload, setError, user]);
|
|
|
|
|
2023-08-01 20:14:03 +03:00
|
|
|
return (
|
|
|
|
<LibraryContext.Provider value={{
|
2023-11-01 13:41:32 +03:00
|
|
|
items, templates, loading, processing, error, setError,
|
2023-11-04 01:29:21 +03:00
|
|
|
applyFilter, createItem, cloneItem, destroyItem, retrieveTemplate
|
2023-08-01 20:14:03 +03:00
|
|
|
}}>
|
|
|
|
{ children }
|
|
|
|
</LibraryContext.Provider>
|
|
|
|
);
|
|
|
|
}
|