From 83e08ca7fcbfa2d5679e975b692950b7b8e174e0 Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Fri, 11 Aug 2023 19:28:12 +0300 Subject: [PATCH] Refactor contexts. Do not share reload in interface --- .../frontend/src/context/AuthContext.tsx | 24 +++++----- .../frontend/src/context/LibraryContext.tsx | 39 +++++++++++++-- .../frontend/src/context/RSFormContext.tsx | 48 +++---------------- .../src/pages/RSFormPage/DlgCloneRSForm.tsx | 9 +++- .../src/pages/RSFormPage/EditorRSForm.tsx | 17 ++++--- .../frontend/src/pages/RSFormPage/RSTabs.tsx | 19 +++++++- .../src/pages/RSFormPage/RSTabsMenu.tsx | 13 +++-- rsconcept/frontend/src/utils/procedures.ts | 13 ----- 8 files changed, 91 insertions(+), 91 deletions(-) diff --git a/rsconcept/frontend/src/context/AuthContext.tsx b/rsconcept/frontend/src/context/AuthContext.tsx index 7e527663..b2b433c0 100644 --- a/rsconcept/frontend/src/context/AuthContext.tsx +++ b/rsconcept/frontend/src/context/AuthContext.tsx @@ -11,7 +11,6 @@ interface IAuthContext { logout: (callback?: DataCallback) => void signup: (data: IUserSignupData, callback?: DataCallback) => 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 ( {children} diff --git a/rsconcept/frontend/src/context/LibraryContext.tsx b/rsconcept/frontend/src/context/LibraryContext.tsx index 8a4b14d9..e19c78b1 100644 --- a/rsconcept/frontend/src/context/LibraryContext.tsx +++ b/rsconcept/frontend/src/context/LibraryContext.tsx @@ -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) => void + cloneSchema: (target:number, data: IRSFormCreateData, callback: DataCallback) => void + destroySchema: (target: number, callback?: () => void) => void } const LibraryContext = createContext(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) => { + 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 ( { children } diff --git a/rsconcept/frontend/src/context/RSFormContext.tsx b/rsconcept/frontend/src/context/RSFormContext.tsx index 29c6bd51..875dac86 100644 --- a/rsconcept/frontend/src/context/RSFormContext.tsx +++ b/rsconcept/frontend/src/context/RSFormContext.tsx @@ -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) => void - destroy: (callback?: () => void) => void claim: (callback?: DataCallback) => void download: (callback: DataCallback) => void upload: (data: IRSFormUploadData, callback: () => void) => void - clone: (data: IRSFormCreateData, callback: DataCallback) => void + resetAliases: (callback: () => void) => void cstCreate: (data: ICstCreateData, callback?: DataCallback) => 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) => { 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) => { - 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 } diff --git a/rsconcept/frontend/src/pages/RSFormPage/DlgCloneRSForm.tsx b/rsconcept/frontend/src/pages/RSFormPage/DlgCloneRSForm.tsx index 65d6fd31..1b56d3cc 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/DlgCloneRSForm.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/DlgCloneRSForm.tsx @@ -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}`); }); diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx index a7765864..92fdbae5 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSForm.tsx @@ -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() { } /> diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx index b1f66100..87e673de 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx @@ -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(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 (
{ loading && } @@ -213,6 +225,7 @@ function RSTabs() { > setShowClone(true)} showUploadDialog={() => setShowUpload(true)} /> @@ -226,7 +239,9 @@ function RSTabs() { - + {schema.stats && } diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx index e33e8549..94accba1 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx @@ -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(); diff --git a/rsconcept/frontend/src/utils/procedures.ts b/rsconcept/frontend/src/utils/procedures.ts index 80612679..158ca820 100644 --- a/rsconcept/frontend/src/utils/procedures.ts +++ b/rsconcept/frontend/src/utils/procedures.ts @@ -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) => void, fileName: string