Refactor contexts. Do not share reload in interface

This commit is contained in:
IRBorisov 2023-08-11 19:28:12 +03:00
parent b9d0dd4c20
commit 83e08ca7fc
8 changed files with 91 additions and 91 deletions

View File

@ -11,7 +11,6 @@ interface IAuthContext {
logout: (callback?: DataCallback) => void
signup: (data: IUserSignupData, callback?: DataCallback<IUserProfile>) => void
updatePassword: (data: IUserUpdatePassword, callback?: () => void) => void
reload: (callback?: () => void) => void
loading: boolean
error: ErrorInfo
setError: (error: ErrorInfo) => void
@ -40,7 +39,7 @@ export const AuthState = ({ children }: AuthStateProps) => {
const reload = useCallback(
(callback?: () => void) => {
getAuth({
onError: () => { setUser(undefined); },
onError: () => setUser(undefined),
onSuccess: currentUser => {
if (currentUser.id) {
setUser(currentUser);
@ -58,7 +57,7 @@ export const AuthState = ({ children }: AuthStateProps) => {
data: data,
showError: true,
setLoading: setLoading,
onError: error => { setError(error); },
onError: error => setError(error),
onSuccess: newData => reload(() => {
if (callback) callback(newData);
})
@ -81,8 +80,10 @@ export const AuthState = ({ children }: AuthStateProps) => {
data: data,
showError: true,
setLoading: setLoading,
onError: error => { setError(error); },
onSuccess: newData => reload(() => { if (callback) callback(newData); })
onError: error => setError(error),
onSuccess: newData => reload(() => {
if (callback) callback(newData);
})
});
}
@ -93,13 +94,12 @@ export const AuthState = ({ children }: AuthStateProps) => {
data: data,
showError: true,
setLoading: setLoading,
onError: error => { setError(error); },
onSuccess: () => {
setUser(undefined);
reload();
onError: error => setError(error),
onSuccess: () => reload(() => {
if (callback) callback();
}});
}, [setUser, reload]);
})
});
}, [reload]);
useLayoutEffect(() => {
reload();
@ -107,7 +107,7 @@ export const AuthState = ({ children }: AuthStateProps) => {
return (
<AuthContext.Provider
value={{ user, login, logout, signup, loading, error, reload, setError, updatePassword }}
value={{ user, login, logout, signup, loading, error, setError, updatePassword }}
>
{children}
</AuthContext.Provider>

View File

@ -1,8 +1,8 @@
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { ErrorInfo } from '../components/BackendError';
import { DataCallback, getLibrary, postNewRSForm } from '../utils/backendAPI';
import { ILibraryFilter, IRSFormCreateData, IRSFormMeta, matchRSFormMeta } from '../utils/models';
import { DataCallback, deleteRSForm, getLibrary, postCloneRSForm, postNewRSForm } from '../utils/backendAPI';
import { ILibraryFilter, IRSFormCreateData, IRSFormData, IRSFormMeta, matchRSFormMeta } from '../utils/models';
import { useAuth } from './AuthContext';
interface ILibraryContext {
@ -12,9 +12,10 @@ interface ILibraryContext {
error: ErrorInfo
setError: (error: ErrorInfo) => void
reload: (callback?: () => void) => void
filter: (params: ILibraryFilter) => IRSFormMeta[]
createSchema: (data: IRSFormCreateData, callback?: DataCallback<IRSFormMeta>) => void
cloneSchema: (target:number, data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => void
destroySchema: (target: number, callback?: () => void) => void
}
const LibraryContext = createContext<ILibraryContext | null>(null)
@ -88,10 +89,40 @@ export const LibraryState = ({ children }: LibraryStateProps) => {
});
}, [reload]);
const destroySchema = useCallback(
(target: number, callback?: () => void) => {
setError(undefined)
deleteRSForm(String(target), {
showError: true,
setLoading: setProcessing,
onError: error => setError(error),
onSuccess: () => reload(() => {
if (callback) callback();
})
});
}, [setError, reload]);
const cloneSchema = useCallback(
(target: number, data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => {
if (!user) {
return;
}
setError(undefined)
postCloneRSForm(String(target), {
data: data,
showError: true,
setLoading: setProcessing,
onError: error => setError(error),
onSuccess: newSchema => reload(() => {
if (callback) callback(newSchema);
})
});
}, [reload, setError, user]);
return (
<LibraryContext.Provider value={{
items, loading, processing, error, setError,
reload, filter, createSchema
filter, createSchema, cloneSchema, destroySchema
}}>
{ children }
</LibraryContext.Provider>

View File

@ -4,18 +4,17 @@ import { toast } from 'react-toastify'
import { type ErrorInfo } from '../components/BackendError'
import { useRSFormDetails } from '../hooks/useRSFormDetails'
import {
type DataCallback, deleteRSForm, getTRSFile,
type DataCallback, getTRSFile,
patchConstituenta, patchDeleteConstituenta,
patchMoveConstituenta, patchResetAliases, patchRSForm,
patchUploadTRS, postClaimRSForm, postCloneRSForm, postNewConstituenta
patchUploadTRS, postClaimRSForm, postNewConstituenta
} from '../utils/backendAPI'
import {
IConstituentaList, IConstituentaMeta, ICstCreateData,
ICstMovetoData, ICstUpdateData, IRSForm, IRSFormCreateData,
IRSFormData, IRSFormMeta, IRSFormUpdateData, IRSFormUploadData
ICstMovetoData, ICstUpdateData, IRSForm,
IRSFormMeta, IRSFormUpdateData, IRSFormUploadData
} from '../utils/models'
import { useAuth } from './AuthContext'
import { useLibrary } from './LibraryContext'
interface IRSFormContext {
schema?: IRSForm
@ -36,11 +35,10 @@ interface IRSFormContext {
toggleTracking: () => void
update: (data: IRSFormUpdateData, callback?: DataCallback<IRSFormMeta>) => void
destroy: (callback?: () => void) => void
claim: (callback?: DataCallback<IRSFormMeta>) => void
download: (callback: DataCallback<Blob>) => void
upload: (data: IRSFormUploadData, callback: () => void) => void
clone: (data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => void
resetAliases: (callback: () => void) => void
cstCreate: (data: ICstCreateData, callback?: DataCallback<IConstituentaMeta>) => void
@ -69,7 +67,6 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
const { user } = useAuth();
const { schema, reload, error, setError, setSchema, loading } = useRSFormDetails({ target: schemaID });
const [ processing, setProcessing ] = useState(false);
const library = useLibrary();
const [ isForceAdmin, setIsForceAdmin ] = useState(false);
const [ isReadonly, setIsReadonly ] = useState(false);
@ -130,21 +127,6 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
});
}, [schemaID, setError, setSchema, schema]);
const destroy = useCallback(
(callback?: () => void) => {
setError(undefined)
deleteRSForm(schemaID, {
showError: true,
setLoading: setProcessing,
onError: error => setError(error),
onSuccess: () => {
setSchema(undefined);
library.reload();
if (callback) callback();
}
});
}, [schemaID, setError, setSchema, library]);
const claim = useCallback(
(callback?: DataCallback<IRSFormMeta>) => {
if (!schema || !user) {
@ -162,24 +144,6 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
});
}, [schemaID, setError, schema, user, setSchema]);
const clone = useCallback(
(data: IRSFormCreateData, callback: DataCallback<IRSFormData>) => {
if (!schema || !user) {
return;
}
setError(undefined)
postCloneRSForm(schemaID, {
data: data,
showError: true,
setLoading: setProcessing,
onError: error => setError(error),
onSuccess: newSchema => {
library.reload();
if (callback) callback(newSchema);
}
});
}, [schemaID, setError, schema, user, library]);
const resetAliases = useCallback(
(callback?: () => void) => {
if (!schema || !user) {
@ -276,7 +240,7 @@ export const RSFormState = ({ schemaID, children }: RSFormStateProps) => {
toggleForceAdmin: () => { setIsForceAdmin(prev => !prev) },
toggleReadonly: () => { setIsReadonly(prev => !prev) },
toggleTracking,
update, download, upload, destroy, claim, resetAliases, clone,
update, download, upload, claim, resetAliases,
cstUpdate, cstCreate, cstDelete, cstMoveTo
}}>
{ children }

View File

@ -6,6 +6,7 @@ import Checkbox from '../../components/Common/Checkbox';
import Modal from '../../components/Common/Modal';
import TextArea from '../../components/Common/TextArea';
import TextInput from '../../components/Common/TextInput';
import { useLibrary } from '../../context/LibraryContext';
import { useRSForm } from '../../context/RSFormContext';
import { IRSFormCreateData } from '../../utils/models';
import { getCloneTitle } from '../../utils/staticUI';
@ -21,7 +22,8 @@ function DlgCloneRSForm({ hideWindow }: DlgCloneRSFormProps) {
const [comment, setComment] = useState('');
const [common, setCommon] = useState(false);
const { schema, clone } = useRSForm();
const { cloneSchema } = useLibrary();
const { schema } = useRSForm();
useEffect(() => {
if (schema) {
@ -33,13 +35,16 @@ function DlgCloneRSForm({ hideWindow }: DlgCloneRSFormProps) {
}, [schema, schema?.title, schema?.alias, schema?.comment, schema?.is_common]);
const handleSubmit = () => {
if (!schema) {
return;
}
const data: IRSFormCreateData = {
title: title,
alias: alias,
comment: comment,
is_common: common
};
clone(data, newSchema => {
cloneSchema(schema.id, data, newSchema => {
toast.success(`Схема создана: ${newSchema.alias}`);
navigate(`/rsforms/${newSchema.id}`);
});

View File

@ -1,6 +1,5 @@
import { useCallback, useLayoutEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify';
import Checkbox from '../../components/Common/Checkbox';
@ -13,15 +12,18 @@ import { useAuth } from '../../context/AuthContext';
import { useRSForm } from '../../context/RSFormContext';
import { useUsers } from '../../context/UsersContext';
import { IRSFormCreateData } from '../../utils/models';
import { claimOwnershipProc, deleteRSFormProc, downloadRSFormProc, shareCurrentURLProc } from '../../utils/procedures';
import { claimOwnershipProc, downloadRSFormProc, shareCurrentURLProc } from '../../utils/procedures';
function EditorRSForm() {
const navigate = useNavigate();
interface EditorRSFormProps {
onDestroy: () => void
}
function EditorRSForm({ onDestroy }: EditorRSFormProps) {
const intl = useIntl();
const { getUserLabel } = useUsers();
const {
schema, update, download,
isEditable, isOwned, isClaimable, processing, destroy, claim
isEditable, isOwned, isClaimable, processing, claim
} = useRSForm();
const { user } = useAuth();
@ -66,9 +68,6 @@ function EditorRSForm() {
update(data, () => toast.success('Изменения сохранены'));
};
const handleDelete =
useCallback(() => { deleteRSFormProc(destroy, navigate); }, [destroy, navigate]);
const handleDownload = useCallback(() => {
const fileName = (schema?.alias ?? 'Schema') + '.trs';
downloadRSFormProc(download, fileName);
@ -97,7 +96,7 @@ function EditorRSForm() {
<MiniButton
tooltip='Удалить схему'
disabled={!isEditable}
onClick={handleDelete}
onClick={onDestroy}
icon={<DumpBinIcon size={5} color={isEditable ? 'text-red' : ''} />}
/>
</div>

View File

@ -6,6 +6,7 @@ import { toast } from 'react-toastify';
import BackendError from '../../components/BackendError';
import ConceptTab from '../../components/Common/ConceptTab';
import { Loader } from '../../components/Common/Loader';
import { useLibrary } from '../../context/LibraryContext';
import { useRSForm } from '../../context/RSFormContext';
import { prefixes, TIMEOUT_UI_REFRESH } from '../../utils/constants';
import { CstType, ICstCreateData, SyntaxTree } from '../../utils/models';
@ -36,6 +37,7 @@ function RSTabs() {
error, schema, loading,
cstCreate, cstDelete
} = useRSForm();
const { destroySchema } = useLibrary();
const [activeTab, setActiveTab] = useState(RSTabsList.CARD);
const [activeID, setActiveID] = useState<number | undefined>(undefined)
@ -151,7 +153,6 @@ function RSTabs() {
});
}, [afterDelete, cstDelete, schema, activeID, activeTab, navigateTo]);
const promptDeleteCst = useCallback(
(selected: number[], callback?: (items: number[]) => void) => {
setAfterDelete(() => (
@ -174,6 +175,17 @@ function RSTabs() {
navigateTo(RSTabsList.CST_EDIT, cstID)
}, [navigateTo]);
const onDestroySchema = useCallback(
() => {
if (!schema || !window.confirm('Вы уверены, что хотите удалить данную схему?')) {
return;
}
destroySchema(schema.id, () => {
toast.success('Схема удалена');
navigate('/library?filter=personal');
});
}, [schema, destroySchema, navigate]);
return (
<div className='w-full'>
{ loading && <Loader /> }
@ -213,6 +225,7 @@ function RSTabs() {
>
<TabList className='flex items-start w-fit clr-bg-pop'>
<RSTabsMenu
onDestroy={onDestroySchema}
showCloneDialog={() => setShowClone(true)}
showUploadDialog={() => setShowUpload(true)}
/>
@ -226,7 +239,9 @@ function RSTabs() {
</TabList>
<TabPanel className='flex items-start w-full gap-2'>
<EditorRSForm />
<EditorRSForm
onDestroy={onDestroySchema}
/>
{schema.stats && <RSFormStats stats={schema.stats}/>}
</TabPanel>

View File

@ -1,5 +1,4 @@
import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import Button from '../../components/Common/Button';
import Checkbox from '../../components/Common/Checkbox';
@ -9,21 +8,21 @@ import { CloneIcon, CrownIcon, DownloadIcon, DumpBinIcon, EyeIcon, EyeOffIcon, M
import { useAuth } from '../../context/AuthContext';
import { useRSForm } from '../../context/RSFormContext';
import useDropdown from '../../hooks/useDropdown';
import { claimOwnershipProc, deleteRSFormProc, downloadRSFormProc, shareCurrentURLProc } from '../../utils/procedures';
import { claimOwnershipProc, downloadRSFormProc, shareCurrentURLProc } from '../../utils/procedures';
interface RSTabsMenuProps {
showUploadDialog: () => void
showCloneDialog: () => void
onDestroy: () => void
}
function RSTabsMenu({showUploadDialog, showCloneDialog}: RSTabsMenuProps) {
const navigate = useNavigate();
function RSTabsMenu({showUploadDialog, showCloneDialog, onDestroy}: RSTabsMenuProps) {
const { user } = useAuth();
const {
schema,
isOwned, isEditable, isTracking, isReadonly: readonly, isForceAdmin: forceAdmin,
toggleTracking, toggleForceAdmin, toggleReadonly,
claim, destroy, download
claim, download
} = useRSForm();
const schemaMenu = useDropdown();
const editMenu = useDropdown();
@ -35,8 +34,8 @@ function RSTabsMenu({showUploadDialog, showCloneDialog}: RSTabsMenuProps) {
const handleDelete = useCallback(() => {
schemaMenu.hide();
deleteRSFormProc(destroy, navigate);
}, [destroy, navigate, schemaMenu]);
onDestroy();
}, [onDestroy, schemaMenu]);
const handleDownload = useCallback(() => {
schemaMenu.hide();

View File

@ -20,19 +20,6 @@ export function claimOwnershipProc(
claim(() => toast.success('Вы стали владельцем схемы'));
}
export function deleteRSFormProc(
destroy: (callback?: () => void) => void,
navigate: (path: string) => void
) {
if (!window.confirm('Вы уверены, что хотите удалить данную схему?')) {
return;
}
destroy(() => {
toast.success('Схема удалена');
navigate('/library?filter=personal');
});
}
export function downloadRSFormProc(
download: (callback: DataCallback<Blob>) => void,
fileName: string