From 8104b57097fbef7f7136740bac2b1949563edbe3 Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:27:17 +0300 Subject: [PATCH] Frontend: Implement Cst reordering --- .../backend/apps/rsform/views/rsforms.py | 22 ++++++- .../frontend/src/{utils => app}/backendAPI.ts | 10 ++- rsconcept/frontend/src/components/Icons.tsx | 1 + .../frontend/src/context/AuthContext.tsx | 2 +- .../frontend/src/context/LibraryContext.tsx | 2 +- .../frontend/src/context/RSFormContext.tsx | 65 +++++++++++++------ .../src/context/UserProfileContext.tsx | 2 +- .../frontend/src/context/UsersContext.tsx | 2 +- .../frontend/src/hooks/useCheckExpression.ts | 2 +- .../frontend/src/hooks/useConceptText.ts | 2 +- .../frontend/src/hooks/useRSFormDetails.ts | 2 +- .../frontend/src/hooks/useResolveText.ts | 2 +- .../src/pages/RSFormPage/RSEditContext.tsx | 3 + .../src/pages/RSFormPage/RSTabsMenu.tsx | 13 ++++ 14 files changed, 99 insertions(+), 31 deletions(-) rename rsconcept/frontend/src/{utils => app}/backendAPI.ts (98%) diff --git a/rsconcept/backend/apps/rsform/views/rsforms.py b/rsconcept/backend/apps/rsform/views/rsforms.py index f391ffea..d2b047bb 100644 --- a/rsconcept/backend/apps/rsform/views/rsforms.py +++ b/rsconcept/backend/apps/rsform/views/rsforms.py @@ -222,7 +222,6 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr listCst=serializer.validated_data['items'], target=serializer.validated_data['move_to'] ) - schema.item.refresh_from_db() return Response( status=c.HTTP_200_OK, data=s.RSFormParseSerializer(schema.item).data @@ -247,6 +246,27 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr status=c.HTTP_200_OK, data=s.RSFormParseSerializer(schema.item).data ) + + @extend_schema( + summary='restore order based on types and term graph', + tags=['RSForm'], + request=None, + responses={ + c.HTTP_200_OK: s.RSFormParseSerializer, + c.HTTP_403_FORBIDDEN: None, + c.HTTP_404_NOT_FOUND: None + } + ) + @action(detail=True, methods=['patch'], url_path='restore-order') + def restore_order(self, request: Request, pk): + ''' Endpoint: Restore order based on types and term graph. ''' + schema = self._get_schema() + # TODO: implement reordering + # schema.reset_aliases() + return Response( + status=c.HTTP_200_OK, + data=s.RSFormParseSerializer(schema.item).data + ) @extend_schema( summary='load data from TRS file', diff --git a/rsconcept/frontend/src/utils/backendAPI.ts b/rsconcept/frontend/src/app/backendAPI.ts similarity index 98% rename from rsconcept/frontend/src/utils/backendAPI.ts rename to rsconcept/frontend/src/app/backendAPI.ts index 2bbf321f..747f6e7a 100644 --- a/rsconcept/frontend/src/utils/backendAPI.ts +++ b/rsconcept/frontend/src/app/backendAPI.ts @@ -42,7 +42,7 @@ import { } from '@/models/rsform'; import { IExpressionParse, IRSExpression } from '@/models/rslang'; -import { buildConstants } from './constants'; +import { buildConstants } from '../utils/constants'; const defaultOptions = { xsrfCookieName: 'csrftoken', @@ -369,6 +369,14 @@ export function patchResetAliases(target: string, request: FrontPull) { + AxiosPatch({ + title: `Restore order for RSForm id=${target}`, + endpoint: `/api/rsforms/${target}/restore-order`, + request: request + }); +} + export function patchUploadTRS(target: string, request: FrontExchange) { AxiosPatch({ title: `Replacing data with trs file for RSForm id=${target}`, diff --git a/rsconcept/frontend/src/components/Icons.tsx b/rsconcept/frontend/src/components/Icons.tsx index 87b4213c..94843a01 100644 --- a/rsconcept/frontend/src/components/Icons.tsx +++ b/rsconcept/frontend/src/components/Icons.tsx @@ -21,6 +21,7 @@ export { BiMeteor as IconAdmin } from 'react-icons/bi'; export { LuGlasses as IconReader } from 'react-icons/lu'; export { FiBell as IconFollow } from 'react-icons/fi'; export { FiBellOff as IconFollowOff } from 'react-icons/fi'; +export { FaSortAmountDownAlt as IconSortText } from 'react-icons/fa'; export { LuChevronDown as IconDropArrow } from 'react-icons/lu'; export { LuChevronUp as IconDropArrowUp } from 'react-icons/lu'; diff --git a/rsconcept/frontend/src/context/AuthContext.tsx b/rsconcept/frontend/src/context/AuthContext.tsx index 44caccd9..ae9c1cec 100644 --- a/rsconcept/frontend/src/context/AuthContext.tsx +++ b/rsconcept/frontend/src/context/AuthContext.tsx @@ -19,7 +19,7 @@ import { postResetPassword, postSignup, postValidatePasswordToken -} from '@/utils/backendAPI'; +} from '@/app/backendAPI'; import { useUsers } from './UsersContext'; diff --git a/rsconcept/frontend/src/context/LibraryContext.tsx b/rsconcept/frontend/src/context/LibraryContext.tsx index 4210c7d0..dca3e4bb 100644 --- a/rsconcept/frontend/src/context/LibraryContext.tsx +++ b/rsconcept/frontend/src/context/LibraryContext.tsx @@ -16,7 +16,7 @@ import { getTemplates, postCloneLibraryItem, postNewRSForm -} from '@/utils/backendAPI'; +} from '@/app/backendAPI'; import { useAuth } from './AuthContext'; diff --git a/rsconcept/frontend/src/context/RSFormContext.tsx b/rsconcept/frontend/src/context/RSFormContext.tsx index 1efb888a..fb7aa40d 100644 --- a/rsconcept/frontend/src/context/RSFormContext.tsx +++ b/rsconcept/frontend/src/context/RSFormContext.tsx @@ -2,6 +2,28 @@ import { createContext, useCallback, useContext, useMemo, useState } from 'react'; +import { + type DataCallback, + deleteUnsubscribe, + deleteVersion, + getTRSFile, + patchConstituenta, + patchDeleteConstituenta, + patchInlineSynthesis, + patchLibraryItem, + patchMoveConstituenta, + patchProduceStructure, + patchRenameConstituenta, + patchResetAliases, + patchRestoreOrder, + patchSubstituteConstituents, + patchUploadTRS, + patchVersion, + postClaimLibraryItem, + postCreateVersion, + postNewConstituenta, + postSubscribe +} from '@/app/backendAPI'; import { type ErrorData } from '@/components/info/InfoError'; import useRSFormDetails from '@/hooks/useRSFormDetails'; import { ILibraryItem, IVersionData } from '@/models/library'; @@ -21,27 +43,6 @@ import { IRSFormData, IRSFormUploadData } from '@/models/rsform'; -import { - type DataCallback, - deleteUnsubscribe, - deleteVersion, - getTRSFile, - patchConstituenta, - patchDeleteConstituenta, - patchInlineSynthesis, - patchLibraryItem, - patchMoveConstituenta, - patchProduceStructure, - patchRenameConstituenta, - patchResetAliases, - patchSubstituteConstituents, - patchUploadTRS, - patchVersion, - postClaimLibraryItem, - postCreateVersion, - postNewConstituenta, - postSubscribe -} from '@/utils/backendAPI'; import { useAuth } from './AuthContext'; import { useLibrary } from './LibraryContext'; @@ -67,6 +68,7 @@ interface IRSFormContext { upload: (data: IRSFormUploadData, callback: () => void) => void; resetAliases: (callback: () => void) => void; + restoreOrder: (callback: () => void) => void; produceStructure: (data: ICstTarget, callback?: DataCallback) => void; inlineSynthesis: (data: IInlineSynthesisData, callback?: DataCallback) => void; @@ -268,6 +270,26 @@ export const RSFormState = ({ schemaID, versionID, children }: RSFormStateProps) [schemaID, setError, schema, library, user, setSchema] ); + const restoreOrder = useCallback( + (callback?: () => void) => { + if (!schema || !user) { + return; + } + setError(undefined); + patchRestoreOrder(schemaID, { + showError: true, + setLoading: setProcessing, + onError: setError, + onSuccess: newData => { + setSchema(Object.assign(schema, newData)); + library.localUpdateTimestamp(newData.id); + if (callback) callback(); + } + }); + }, + [schemaID, setError, schema, library, user, setSchema] + ); + const produceStructure = useCallback( (data: ICstTarget, callback?: DataCallback) => { setError(undefined); @@ -502,6 +524,7 @@ export const RSFormState = ({ schemaID, versionID, children }: RSFormStateProps) download, upload, claim, + restoreOrder, resetAliases, produceStructure, inlineSynthesis, diff --git a/rsconcept/frontend/src/context/UserProfileContext.tsx b/rsconcept/frontend/src/context/UserProfileContext.tsx index ab68f0cd..c942d7b0 100644 --- a/rsconcept/frontend/src/context/UserProfileContext.tsx +++ b/rsconcept/frontend/src/context/UserProfileContext.tsx @@ -5,7 +5,7 @@ import { createContext, useCallback, useContext, useEffect, useState } from 'rea import { ErrorData } from '@/components/info/InfoError'; import { IUserProfile } from '@/models/library'; import { IUserUpdateData } from '@/models/library'; -import { DataCallback, getProfile, patchProfile } from '@/utils/backendAPI'; +import { DataCallback, getProfile, patchProfile } from '@/app/backendAPI'; import { useUsers } from './UsersContext'; diff --git a/rsconcept/frontend/src/context/UsersContext.tsx b/rsconcept/frontend/src/context/UsersContext.tsx index e089f7b2..d430dd6b 100644 --- a/rsconcept/frontend/src/context/UsersContext.tsx +++ b/rsconcept/frontend/src/context/UsersContext.tsx @@ -3,7 +3,7 @@ import { createContext, useCallback, useContext, useEffect, useState } from 'react'; import { type IUserInfo } from '@/models/library'; -import { getActiveUsers } from '@/utils/backendAPI'; +import { getActiveUsers } from '@/app/backendAPI'; interface IUsersContext { users: IUserInfo[]; diff --git a/rsconcept/frontend/src/hooks/useCheckExpression.ts b/rsconcept/frontend/src/hooks/useCheckExpression.ts index 8c83f52d..79fd52d5 100644 --- a/rsconcept/frontend/src/hooks/useCheckExpression.ts +++ b/rsconcept/frontend/src/hooks/useCheckExpression.ts @@ -7,7 +7,7 @@ import { CstType, IConstituenta, type IRSForm } from '@/models/rsform'; import { getDefinitionPrefix } from '@/models/rsformAPI'; import { IArgumentInfo, IExpressionParse } from '@/models/rslang'; import { RSErrorType } from '@/models/rslang'; -import { DataCallback, postCheckExpression } from '@/utils/backendAPI'; +import { DataCallback, postCheckExpression } from '@/app/backendAPI'; import { PARAMETER } from '@/utils/constants'; function useCheckExpression({ schema }: { schema?: IRSForm }) { diff --git a/rsconcept/frontend/src/hooks/useConceptText.ts b/rsconcept/frontend/src/hooks/useConceptText.ts index 765338be..25fcddbd 100644 --- a/rsconcept/frontend/src/hooks/useConceptText.ts +++ b/rsconcept/frontend/src/hooks/useConceptText.ts @@ -4,7 +4,7 @@ import { useCallback, useState } from 'react'; import { ErrorData } from '@/components/info/InfoError'; import { ILexemeData, ITextRequest, ITextResult, IWordFormPlain } from '@/models/language'; -import { DataCallback, postGenerateLexeme, postInflectText, postParseText } from '@/utils/backendAPI'; +import { DataCallback, postGenerateLexeme, postInflectText, postParseText } from '@/app/backendAPI'; function useConceptText() { const [loading, setLoading] = useState(false); diff --git a/rsconcept/frontend/src/hooks/useRSFormDetails.ts b/rsconcept/frontend/src/hooks/useRSFormDetails.ts index 9dd56284..2e1e8a1d 100644 --- a/rsconcept/frontend/src/hooks/useRSFormDetails.ts +++ b/rsconcept/frontend/src/hooks/useRSFormDetails.ts @@ -5,7 +5,7 @@ import { useCallback, useEffect, useState } from 'react'; import { type ErrorData } from '@/components/info/InfoError'; import { IRSForm, IRSFormData } from '@/models/rsform'; import { RSFormLoader } from '@/models/RSFormLoader'; -import { getRSFormDetails } from '@/utils/backendAPI'; +import { getRSFormDetails } from '@/app/backendAPI'; function useRSFormDetails({ target, version }: { target?: string; version?: string }) { const [schema, setInnerSchema] = useState(undefined); diff --git a/rsconcept/frontend/src/hooks/useResolveText.ts b/rsconcept/frontend/src/hooks/useResolveText.ts index 17afe7e8..a4f962b0 100644 --- a/rsconcept/frontend/src/hooks/useResolveText.ts +++ b/rsconcept/frontend/src/hooks/useResolveText.ts @@ -5,7 +5,7 @@ import { useCallback, useState } from 'react'; import { ErrorData } from '@/components/info/InfoError'; import { IResolutionData } from '@/models/language'; import { IRSForm } from '@/models/rsform'; -import { DataCallback, postResolveText } from '@/utils/backendAPI'; +import { DataCallback, postResolveText } from '@/app/backendAPI'; function useResolveText({ schema }: { schema?: IRSForm }) { const [loading, setLoading] = useState(false); diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx index 804c0f89..d43f28ca 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx @@ -83,6 +83,7 @@ interface IRSEditContext { download: () => void; reindex: () => void; + reorder: () => void; produceStructure: () => void; inlineSynthesis: () => void; substitute: () => void; @@ -392,6 +393,7 @@ export const RSEditState = ({ }, [isModified, activeCst]); const reindex = useCallback(() => model.resetAliases(() => toast.success('Имена конституент обновлены')), [model]); + const reorder = useCallback(() => model.restoreOrder(() => toast.success('Конституенты упорядочены')), [model]); const canProduceStructure = useMemo(() => { return ( @@ -510,6 +512,7 @@ export const RSEditState = ({ toggleSubscribe, reindex, + reorder, inlineSynthesis: () => setShowInlineSynthesis(true), produceStructure, substitute diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx index 91a54621..1e828bfe 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabsMenu.tsx @@ -16,6 +16,7 @@ import { IconReader, IconReplace, IconShare, + IconSortText, IconUpload } from '@/components/Icons'; import Button from '@/components/ui/Button'; @@ -82,6 +83,11 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) { controller.reindex(); } + function handleRestoreOrder() { + editMenu.hide(); + controller.reorder(); + } + function handleSubstituteCst() { editMenu.hide(); controller.substitute(); @@ -218,6 +224,13 @@ function RSTabsMenu({ onDestroy }: RSTabsMenuProps) { /> } + disabled={!controller.isContentEditable || controller.isProcessing} + onClick={handleRestoreOrder} + /> + }