From 8c38297de7b70f5a2897e9c64e7a8fb8279e7170 Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Thu, 6 Jun 2024 23:11:53 +0300 Subject: [PATCH] Refactoring: pull similar messages together --- .../src/context/AccessModeContext.tsx | 3 +- .../frontend/src/context/AuthContext.tsx | 3 +- .../frontend/src/context/LibraryContext.tsx | 3 +- .../src/context/NavigationContext.tsx | 3 +- .../frontend/src/context/OptionsContext.tsx | 3 +- rsconcept/frontend/src/context/OssContext.tsx | 3 +- .../frontend/src/context/RSFormContext.tsx | 3 +- .../src/context/UserProfileContext.tsx | 3 +- .../frontend/src/context/UsersContext.tsx | 3 +- .../src/dialogs/DlgCloneLibraryItem.tsx | 3 +- .../DlgEditWordForms/DlgEditWordForms.tsx | 3 +- .../pages/CreateItemPage/FormCreateItem.tsx | 3 +- .../pages/OssPage/EditorOssCard/FormOSS.tsx | 3 +- .../src/pages/OssPage/OssEditContext.tsx | 15 ++--- .../frontend/src/pages/OssPage/OssTabs.tsx | 5 +- .../ConstituentaToolbar.tsx | 4 +- .../EditorConstituenta/ControlsOverlay.tsx | 6 +- .../EditorConstituenta/FormConstituenta.tsx | 4 +- .../EditorRSExpression/EditorRSExpression.tsx | 4 +- .../EditorRSFormCard/FormRSForm.tsx | 3 +- .../src/pages/RSFormPage/RSEditContext.tsx | 47 ++++++++------- .../frontend/src/pages/RSFormPage/RSTabs.tsx | 6 +- .../pages/UserProfilePage/EditorPassword.tsx | 5 +- .../pages/UserProfilePage/EditorProfile.tsx | 3 +- rsconcept/frontend/src/utils/labels.ts | 58 +++++++++++++++++-- rsconcept/frontend/src/utils/utils.ts | 4 +- 26 files changed, 135 insertions(+), 68 deletions(-) diff --git a/rsconcept/frontend/src/context/AccessModeContext.tsx b/rsconcept/frontend/src/context/AccessModeContext.tsx index 531fe682..1a0732a1 100644 --- a/rsconcept/frontend/src/context/AccessModeContext.tsx +++ b/rsconcept/frontend/src/context/AccessModeContext.tsx @@ -3,6 +3,7 @@ import { createContext, useContext, useState } from 'react'; import { UserLevel } from '@/models/user'; +import { contextOutsideScope } from '@/utils/labels'; interface IAccessModeContext { accessLevel: UserLevel; @@ -13,7 +14,7 @@ const AccessContext = createContext(null); export const useAccessMode = () => { const context = useContext(AccessContext); if (!context) { - throw new Error('useAccessMode has to be used within '); + throw new Error(contextOutsideScope('useAccessMode', 'AccessModeState')); } return context; }; diff --git a/rsconcept/frontend/src/context/AuthContext.tsx b/rsconcept/frontend/src/context/AuthContext.tsx index 5ac715bf..073ec11d 100644 --- a/rsconcept/frontend/src/context/AuthContext.tsx +++ b/rsconcept/frontend/src/context/AuthContext.tsx @@ -25,6 +25,7 @@ import { IUserSignupData, IUserUpdatePassword } from '@/models/user'; +import { contextOutsideScope } from '@/utils/labels'; import { useUsers } from './UsersContext'; @@ -46,7 +47,7 @@ const AuthContext = createContext(null); export const useAuth = () => { const context = useContext(AuthContext); if (!context) { - throw new Error('useAuth has to be used within '); + throw new Error(contextOutsideScope('useAuth', 'AuthState')); } return context; }; diff --git a/rsconcept/frontend/src/context/LibraryContext.tsx b/rsconcept/frontend/src/context/LibraryContext.tsx index 6b5e4646..a93a4ce5 100644 --- a/rsconcept/frontend/src/context/LibraryContext.tsx +++ b/rsconcept/frontend/src/context/LibraryContext.tsx @@ -20,6 +20,7 @@ import { matchLibraryItem, matchLibraryItemLocation } from '@/models/libraryAPI' import { ILibraryFilter } from '@/models/miscellaneous'; import { IRSForm, IRSFormCloneData, IRSFormData } from '@/models/rsform'; import { RSFormLoader } from '@/models/RSFormLoader'; +import { contextOutsideScope } from '@/utils/labels'; import { useAuth } from './AuthContext'; import { useConceptOptions } from './OptionsContext'; @@ -46,7 +47,7 @@ const LibraryContext = createContext(null); export const useLibrary = (): ILibraryContext => { const context = useContext(LibraryContext); if (context === null) { - throw new Error('useLibrary has to be used within '); + throw new Error(contextOutsideScope('useLibrary', 'LibraryState')); } return context; }; diff --git a/rsconcept/frontend/src/context/NavigationContext.tsx b/rsconcept/frontend/src/context/NavigationContext.tsx index c50c385d..91e0accf 100644 --- a/rsconcept/frontend/src/context/NavigationContext.tsx +++ b/rsconcept/frontend/src/context/NavigationContext.tsx @@ -4,6 +4,7 @@ import { createContext, useCallback, useContext, useEffect, useState } from 'rea import { useLocation, useNavigate } from 'react-router-dom'; import { globals } from '@/utils/constants'; +import { contextOutsideScope } from '@/utils/labels'; interface INavigationContext { push: (path: string, newTab?: boolean) => void; @@ -21,7 +22,7 @@ const NavigationContext = createContext(null); export const useConceptNavigation = () => { const context = useContext(NavigationContext); if (!context) { - throw new Error('useConceptNavigation has to be used within '); + throw new Error(contextOutsideScope('useConceptNavigation', 'NavigationState')); } return context; }; diff --git a/rsconcept/frontend/src/context/OptionsContext.tsx b/rsconcept/frontend/src/context/OptionsContext.tsx index b02220fe..cef7672f 100644 --- a/rsconcept/frontend/src/context/OptionsContext.tsx +++ b/rsconcept/frontend/src/context/OptionsContext.tsx @@ -9,6 +9,7 @@ import { FontStyle } from '@/models/miscellaneous'; import { animationDuration } from '@/styling/animations'; import { darkT, IColorTheme, lightT } from '@/styling/color'; import { globals, storage } from '@/utils/constants'; +import { contextOutsideScope } from '@/utils/labels'; interface IOptionsContext { viewportHeight: string; @@ -45,7 +46,7 @@ const OptionsContext = createContext(null); export const useConceptOptions = () => { const context = useContext(OptionsContext); if (!context) { - throw new Error('useConceptTheme has to be used within '); + throw new Error(contextOutsideScope('useConceptTheme', 'ThemeState')); } return context; }; diff --git a/rsconcept/frontend/src/context/OssContext.tsx b/rsconcept/frontend/src/context/OssContext.tsx index 41385511..aa95ab43 100644 --- a/rsconcept/frontend/src/context/OssContext.tsx +++ b/rsconcept/frontend/src/context/OssContext.tsx @@ -18,6 +18,7 @@ import { AccessPolicy, ILibraryItem } from '@/models/library'; import { ILibraryUpdateData } from '@/models/library'; import { IOperationSchema } from '@/models/oss'; import { UserID } from '@/models/user'; +import { contextOutsideScope } from '@/utils/labels'; import { useAuth } from './AuthContext'; import { useLibrary } from './LibraryContext'; @@ -48,7 +49,7 @@ const OssContext = createContext(null); export const useOSS = () => { const context = useContext(OssContext); if (context === null) { - throw new Error('useOSS has to be used within '); + throw new Error(contextOutsideScope('useOSS', 'OssState')); } return context; }; diff --git a/rsconcept/frontend/src/context/RSFormContext.tsx b/rsconcept/frontend/src/context/RSFormContext.tsx index c61757a1..678c40f9 100644 --- a/rsconcept/frontend/src/context/RSFormContext.tsx +++ b/rsconcept/frontend/src/context/RSFormContext.tsx @@ -48,6 +48,7 @@ import { ITargetCst } from '@/models/rsform'; import { UserID } from '@/models/user'; +import { contextOutsideScope } from '@/utils/labels'; import { useAuth } from './AuthContext'; import { useLibrary } from './LibraryContext'; @@ -99,7 +100,7 @@ const RSFormContext = createContext(null); export const useRSForm = () => { const context = useContext(RSFormContext); if (context === null) { - throw new Error('useRSForm has to be used within '); + throw new Error(contextOutsideScope('useRSForm', 'RSFormState')); } return context; }; diff --git a/rsconcept/frontend/src/context/UserProfileContext.tsx b/rsconcept/frontend/src/context/UserProfileContext.tsx index c467be5b..7185a553 100644 --- a/rsconcept/frontend/src/context/UserProfileContext.tsx +++ b/rsconcept/frontend/src/context/UserProfileContext.tsx @@ -5,6 +5,7 @@ import { createContext, useCallback, useContext, useEffect, useState } from 'rea import { DataCallback, getProfile, patchProfile } from '@/app/backendAPI'; import { ErrorData } from '@/components/info/InfoError'; import { IUserProfile, IUserUpdateData } from '@/models/user'; +import { contextOutsideScope } from '@/utils/labels'; import { useUsers } from './UsersContext'; @@ -23,7 +24,7 @@ const ProfileContext = createContext(null); export const useUserProfile = () => { const context = useContext(ProfileContext); if (!context) { - throw new Error('useUserProfile has to be used within '); + throw new Error(contextOutsideScope('useUserProfile', 'UserProfileState')); } return context; }; diff --git a/rsconcept/frontend/src/context/UsersContext.tsx b/rsconcept/frontend/src/context/UsersContext.tsx index d404c453..2c966a6e 100644 --- a/rsconcept/frontend/src/context/UsersContext.tsx +++ b/rsconcept/frontend/src/context/UsersContext.tsx @@ -4,6 +4,7 @@ import { createContext, useCallback, useContext, useEffect, useState } from 'rea import { getActiveUsers } from '@/app/backendAPI'; import { IUserInfo } from '@/models/user'; +import { contextOutsideScope } from '@/utils/labels'; interface IUsersContext { users: IUserInfo[]; @@ -15,7 +16,7 @@ const UsersContext = createContext(null); export const useUsers = (): IUsersContext => { const context = useContext(UsersContext); if (context === null) { - throw new Error('useUsers has to be used within '); + throw new Error(contextOutsideScope('useUsers', 'UsersState')); } return context; }; diff --git a/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx b/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx index 16383c1e..bc78f010 100644 --- a/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx +++ b/rsconcept/frontend/src/dialogs/DlgCloneLibraryItem.tsx @@ -20,6 +20,7 @@ import { useConceptNavigation } from '@/context/NavigationContext'; import { AccessPolicy, ILibraryItem, LocationHead } from '@/models/library'; import { cloneTitle, combineLocation, validateLocation } from '@/models/libraryAPI'; import { ConstituentaID, IRSFormCloneData } from '@/models/rsform'; +import { information } from '@/utils/labels'; interface DlgCloneLibraryItemProps extends Pick { base: ILibraryItem; @@ -62,7 +63,7 @@ function DlgCloneLibraryItem({ hideWindow, base, initialLocation, selected, tota data.items = selected; } cloneItem(base.id, data, newSchema => { - toast.success(`Копия создана: ${newSchema.alias}`); + toast.success(information.cloneComplete(newSchema.alias)); router.push(urls.schema(newSchema.id)); }); } diff --git a/rsconcept/frontend/src/dialogs/DlgEditWordForms/DlgEditWordForms.tsx b/rsconcept/frontend/src/dialogs/DlgEditWordForms/DlgEditWordForms.tsx index 161a5085..28bd882d 100644 --- a/rsconcept/frontend/src/dialogs/DlgEditWordForms/DlgEditWordForms.tsx +++ b/rsconcept/frontend/src/dialogs/DlgEditWordForms/DlgEditWordForms.tsx @@ -16,6 +16,7 @@ import { Grammeme, ITextRequest, IWordForm, IWordFormPlain } from '@/models/lang import { parseGrammemes, wordFormEquals } from '@/models/languageAPI'; import { HelpTopic } from '@/models/miscellaneous'; import { IConstituenta, TermForm } from '@/models/rsform'; +import { prompts } from '@/utils/labels'; import { IGrammemeOption, SelectorGrammemes, SelectorGrammemesList } from '@/utils/selectors'; import WordFormsTable from './WordFormsTable'; @@ -92,7 +93,7 @@ function DlgEditWordForms({ hideWindow, target, onSave }: DlgEditWordFormsProps) function handleGenerateLexeme() { if (forms.length > 0) { - if (!window.confirm('Данное действие приведет к перезаписи словоформ при совпадении граммем. Продолжить?')) { + if (!window.confirm(prompts.generateWordforms)) { return; } } diff --git a/rsconcept/frontend/src/pages/CreateItemPage/FormCreateItem.tsx b/rsconcept/frontend/src/pages/CreateItemPage/FormCreateItem.tsx index 36e6b528..b7aeec64 100644 --- a/rsconcept/frontend/src/pages/CreateItemPage/FormCreateItem.tsx +++ b/rsconcept/frontend/src/pages/CreateItemPage/FormCreateItem.tsx @@ -25,6 +25,7 @@ import { AccessPolicy, LibraryItemType, LocationHead } from '@/models/library'; import { ILibraryCreateData } from '@/models/library'; import { combineLocation, validateLocation } from '@/models/libraryAPI'; import { EXTEOR_TRS_FILE, limits, patterns } from '@/utils/constants'; +import { information } from '@/utils/labels'; function FormCreateItem() { const router = useConceptNavigation(); @@ -78,7 +79,7 @@ function FormCreateItem() { fileName: file?.name }; createItem(data, newItem => { - toast.success('Схема успешно создана'); + toast.success(information.newLibraryItem); if (itemType == LibraryItemType.RSFORM) { router.push(urls.schema(newItem.id)); } else { diff --git a/rsconcept/frontend/src/pages/OssPage/EditorOssCard/FormOSS.tsx b/rsconcept/frontend/src/pages/OssPage/EditorOssCard/FormOSS.tsx index e7556797..babd8c69 100644 --- a/rsconcept/frontend/src/pages/OssPage/EditorOssCard/FormOSS.tsx +++ b/rsconcept/frontend/src/pages/OssPage/EditorOssCard/FormOSS.tsx @@ -12,6 +12,7 @@ import { useOSS } from '@/context/OssContext'; import { ILibraryUpdateData, LibraryItemType } from '@/models/library'; import AccessToolbar from '@/pages/RSFormPage/EditorRSFormCard/AccessToolbar'; import { limits, patterns } from '@/utils/constants'; +import { information } from '@/utils/labels'; import { useOssEdit } from '../OssEditContext'; @@ -81,7 +82,7 @@ function FormOSS({ id, isModified, setIsModified }: FormOSSProps) { visible: visible, read_only: readOnly }; - update(data, () => toast.success('Изменения сохранены')); + update(data, () => toast.success(information.changesSaved)); }; return ( diff --git a/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx b/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx index 8bf50c57..2c13cafe 100644 --- a/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx +++ b/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx @@ -13,6 +13,7 @@ import DlgEditEditors from '@/dialogs/DlgEditEditors'; import { AccessPolicy } from '@/models/library'; import { IOperationSchema } from '@/models/oss'; import { UserID, UserLevel } from '@/models/user'; +import { information } from '@/utils/labels'; interface IOssEditContext { schema?: IOperationSchema; @@ -84,7 +85,7 @@ export const OssEditState = ({ children }: OssEditStateProps) => { if (!model.schema) { return; } - model.setLocation(newLocation, () => toast.success('Схема перемещена')); + model.setLocation(newLocation, () => toast.success(information.moveComplete)); }, [model] ); @@ -102,35 +103,35 @@ export const OssEditState = ({ children }: OssEditStateProps) => { const url = currentRef.includes('?') ? currentRef + '&share' : currentRef + '?share'; navigator.clipboard .writeText(url) - .then(() => toast.success(`Ссылка скопирована: ${url}`)) + .then(() => toast.success(information.linkReady)) .catch(console.error); }, []); const toggleSubscribe = useCallback(() => { if (model.isSubscribed) { - model.unsubscribe(() => toast.success('Отслеживание отключено')); + model.unsubscribe(() => toast.success(information.unsubscribed)); } else { - model.subscribe(() => toast.success('Отслеживание включено')); + model.subscribe(() => toast.success(information.subscribed)); } }, [model]); const setOwner = useCallback( (newOwner: UserID) => { - model.setOwner(newOwner, () => toast.success('Владелец обновлен')); + model.setOwner(newOwner, () => toast.success(information.changesSaved)); }, [model] ); const setAccessPolicy = useCallback( (newPolicy: AccessPolicy) => { - model.setAccessPolicy(newPolicy, () => toast.success('Политика доступа изменена')); + model.setAccessPolicy(newPolicy, () => toast.success(information.changesSaved)); }, [model] ); const setEditors = useCallback( (newEditors: UserID[]) => { - model.setEditors(newEditors, () => toast.success('Редакторы обновлены')); + model.setEditors(newEditors, () => toast.success(information.changesSaved)); }, [model] ); diff --git a/rsconcept/frontend/src/pages/OssPage/OssTabs.tsx b/rsconcept/frontend/src/pages/OssPage/OssTabs.tsx index ac6a9505..12cbc9da 100644 --- a/rsconcept/frontend/src/pages/OssPage/OssTabs.tsx +++ b/rsconcept/frontend/src/pages/OssPage/OssTabs.tsx @@ -17,6 +17,7 @@ import { useBlockNavigation, useConceptNavigation } from '@/context/NavigationCo import { useConceptOptions } from '@/context/OptionsContext'; import { useOSS } from '@/context/OssContext'; import useQueryStrings from '@/hooks/useQueryStrings'; +import { information, prompts } from '@/utils/labels'; import EditorRSForm from './EditorOssCard'; import EditorTermGraph from './EditorOssGraph'; @@ -84,11 +85,11 @@ function OssTabs() { } const onDestroySchema = useCallback(() => { - if (!schema || !window.confirm('Вы уверены, что хотите удалить данную схему?')) { + if (!schema || !window.confirm(prompts.deleteLibraryItem)) { return; } destroyItem(schema.id, () => { - toast.success('Схема удалена'); + toast.success(information.itemDestroyed); router.push(urls.library); }); }, [schema, destroyItem, router]); diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ConstituentaToolbar.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ConstituentaToolbar.tsx index e58164d6..35b7ce62 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ConstituentaToolbar.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ConstituentaToolbar.tsx @@ -13,7 +13,7 @@ import BadgeHelp from '@/components/info/BadgeHelp'; import MiniButton from '@/components/ui/MiniButton'; import Overlay from '@/components/ui/Overlay'; import { HelpTopic } from '@/models/miscellaneous'; -import { messages, prepareTooltip } from '@/utils/labels'; +import { prepareTooltip, tooltips } from '@/utils/labels'; interface ConstituentaToolbarProps { disabled: boolean; @@ -66,7 +66,7 @@ function ConstituentaToolbar({ onClick={onCreate} /> } disabled={disabled || modified} onClick={onClone} diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ControlsOverlay.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ControlsOverlay.tsx index 22893fa2..e7804299 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ControlsOverlay.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/ControlsOverlay.tsx @@ -4,7 +4,7 @@ import { IconEdit } from '@/components/Icons'; import MiniButton from '@/components/ui/MiniButton'; import Overlay from '@/components/ui/Overlay'; import { IConstituenta } from '@/models/rsform'; -import { messages } from '@/utils/labels'; +import { tooltips } from '@/utils/labels'; interface ControlsOverlayProps { constituenta?: IConstituenta; @@ -21,7 +21,7 @@ function ControlsOverlay({ constituenta, disabled, modified, processing, onRenam {!disabled || processing ? ( } @@ -42,7 +42,7 @@ function ControlsOverlay({ constituenta, disabled, modified, processing, onRenam {!disabled || processing ? ( } disabled={modified} diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/FormConstituenta.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/FormConstituenta.tsx index fba58580..e54688df 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/FormConstituenta.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorConstituenta/FormConstituenta.tsx @@ -13,7 +13,7 @@ import AnimateFade from '@/components/wrap/AnimateFade'; import { useRSForm } from '@/context/RSFormContext'; import { CstType, IConstituenta, ICstUpdateData } from '@/models/rsform'; import { isBaseSet, isBasicConcept, isFunctional } from '@/models/rsformAPI'; -import { labelCstTypification } from '@/utils/labels'; +import { information, labelCstTypification } from '@/utils/labels'; import EditorRSExpression from '../EditorRSExpression'; import ControlsOverlay from './ControlsOverlay'; @@ -119,7 +119,7 @@ function FormConstituenta({ definition_raw: textDefinition, convention: convention }; - cstUpdate(data, () => toast.success('Изменения сохранены')); + cstUpdate(data, () => toast.success(information.changesSaved)); } return ( diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx index 0071997c..284ad11b 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx @@ -19,7 +19,7 @@ import { getDefinitionPrefix } from '@/models/rsformAPI'; import { IExpressionParse, IRSErrorDescription, SyntaxTree } from '@/models/rslang'; import { TokenID } from '@/models/rslang'; import { storage } from '@/utils/constants'; -import { labelTypification } from '@/utils/labels'; +import { errors, labelTypification } from '@/utils/labels'; import ExpressionToolbar from './ExpressionToolbar'; import ParsingResult from './ParsingResult'; @@ -131,7 +131,7 @@ function EditorRSExpression({ function handleShowAST() { handleCheckExpression(parse => { if (!parse.astText) { - toast.error('Невозможно построить дерево разбора'); + toast.error(errors.astFailed); } else { setSyntaxTree(parse.ast); setExpression(getDefinitionPrefix(activeCst!) + value); diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx index 3ab9e906..15b4becf 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx @@ -13,6 +13,7 @@ import TextInput from '@/components/ui/TextInput'; import { useRSForm } from '@/context/RSFormContext'; import { ILibraryUpdateData, LibraryItemType } from '@/models/library'; import { limits, patterns } from '@/utils/constants'; +import { information } from '@/utils/labels'; import { useRSEdit } from '../RSEditContext'; import AccessToolbar from './AccessToolbar'; @@ -84,7 +85,7 @@ function FormRSForm({ id, isModified, setIsModified }: FormRSFormProps) { visible: visible, read_only: readOnly }; - update(data, () => toast.success('Изменения сохранены')); + update(data, () => toast.success(information.changesSaved)); }; return ( diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx index d774a8cb..f2671926 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSEditContext.tsx @@ -43,6 +43,7 @@ import { import { generateAlias } from '@/models/rsformAPI'; import { UserID, UserLevel } from '@/models/user'; import { EXTEOR_TRS_FILE } from '@/utils/constants'; +import { information, prompts } from '@/utils/labels'; import { promptUnsaved } from '@/utils/utils'; interface IRSEditContext { @@ -189,14 +190,11 @@ export const RSEditState = ({ }, [isModified]); const restoreVersion = useCallback(() => { - if ( - !model.versionID || - !window.confirm('При восстановлении архивной версии актуальная схему будет заменена. Продолжить?') - ) { + if (!model.versionID || !window.confirm(prompts.restoreArchive)) { return; } model.versionRestore(model.versionID, () => { - toast.success('Загрузка версии завершена'); + toast.success(information.versionRestored); viewVersion(undefined); }); }, [model, viewVersion]); @@ -223,7 +221,7 @@ export const RSEditState = ({ } data.alias = data.alias || generateAlias(data.cst_type, model.schema); model.cstCreate(data, newCst => { - toast.success(`Конституента добавлена: ${newCst.alias}`); + toast.success(information.newConstituent(newCst.alias)); setSelected([newCst.id]); if (onCreateCst) onCreateCst(newCst); }); @@ -233,14 +231,15 @@ export const RSEditState = ({ const handleRenameCst = useCallback( (data: ICstRenameData) => { - model.cstRename(data, () => toast.success(`Переименование: ${renameInitialData!.alias} -> ${data.alias}`)); + const oldAlias = renameInitialData!.alias; + model.cstRename(data, () => toast.success(information.renameComplete(oldAlias, data.alias))); }, [model, renameInitialData] ); const handleSubstituteCst = useCallback( (data: ICstSubstituteData) => { - model.cstSubstitute(data, () => toast.success('Отождествление завершено')); + model.cstSubstitute(data, () => toast.success(information.substituteSingle)); }, [model] ); @@ -259,7 +258,7 @@ export const RSEditState = ({ const nextActive = isEmpty ? undefined : getNextActiveOnDelete(activeCst?.id, model.schema.items, deleted); model.cstDelete(data, () => { - toast.success(`Конституенты удалены: ${deletedNames}`); + toast.success(information.constituentsDestroyed(deletedNames)); setSelected(nextActive ? [nextActive] : []); if (onDeleteCst) onDeleteCst(nextActive); }); @@ -276,7 +275,7 @@ export const RSEditState = ({ id: activeCst.id, term_forms: forms }; - model.cstUpdate(data, () => toast.success('Изменения сохранены')); + model.cstUpdate(data, () => toast.success(information.changesSaved)); }, [model, activeCst] ); @@ -287,7 +286,7 @@ export const RSEditState = ({ return; } model.versionCreate(data, newVersion => { - toast.success('Версия создана'); + toast.success(information.newVersion(data.version)); viewVersion(newVersion); }); }, @@ -300,7 +299,7 @@ export const RSEditState = ({ return; } model.versionDelete(versionID, () => { - toast.success('Версия удалена'); + toast.success(information.versionDestroyed); if (String(versionID) === model.versionID) { viewVersion(undefined); } @@ -314,7 +313,7 @@ export const RSEditState = ({ if (!model.schema) { return; } - model.versionUpdate(versionID, data, () => toast.success('Версия обновлена')); + model.versionUpdate(versionID, data, () => toast.success(information.changesSaved)); }, [model] ); @@ -324,7 +323,7 @@ export const RSEditState = ({ if (!model.schema) { return; } - model.setLocation(newLocation, () => toast.success('Схема перемещена')); + model.setLocation(newLocation, () => toast.success(information.moveComplete)); }, [model] ); @@ -337,7 +336,7 @@ export const RSEditState = ({ const oldCount = model.schema.items.length; model.inlineSynthesis(data, newSchema => { setSelected([]); - toast.success(`Конституенты добавлены: ${newSchema['items'].length - oldCount}`); + toast.success(information.addedConstituents(newSchema['items'].length - oldCount)); }); }, [model, setSelected] @@ -463,8 +462,8 @@ export const RSEditState = ({ setShowEditTerm(true); }, [isModified, activeCst]); - const reindex = useCallback(() => model.resetAliases(() => toast.success('Имена конституент обновлены')), [model]); - const reorder = useCallback(() => model.restoreOrder(() => toast.success('Конституенты упорядочены')), [model]); + const reindex = useCallback(() => model.resetAliases(() => toast.success(information.reindexComplete)), [model]); + const reorder = useCallback(() => model.restoreOrder(() => toast.success(information.reorderComplete)), [model]); const canProduceStructure = useMemo(() => { return ( @@ -486,7 +485,7 @@ export const RSEditState = ({ target: activeCst.id }; model.produceStructure(data, cstList => { - toast.success(`Добавлены конституенты: ${cstList.length}`); + toast.success(information.addedConstituents(cstList.length)); if (cstList.length !== 0) { setSelected(cstList); } @@ -535,35 +534,35 @@ export const RSEditState = ({ const url = currentRef.includes('?') ? currentRef + '&share' : currentRef + '?share'; navigator.clipboard .writeText(url) - .then(() => toast.success(`Ссылка скопирована: ${url}`)) + .then(() => toast.success(information.linkReady)) .catch(console.error); }, []); const toggleSubscribe = useCallback(() => { if (model.isSubscribed) { - model.unsubscribe(() => toast.success('Отслеживание отключено')); + model.unsubscribe(() => toast.success(information.unsubscribed)); } else { - model.subscribe(() => toast.success('Отслеживание включено')); + model.subscribe(() => toast.success(information.subscribed)); } }, [model]); const setOwner = useCallback( (newOwner: UserID) => { - model.setOwner(newOwner, () => toast.success('Владелец обновлен')); + model.setOwner(newOwner, () => toast.success(information.changesSaved)); }, [model] ); const setAccessPolicy = useCallback( (newPolicy: AccessPolicy) => { - model.setAccessPolicy(newPolicy, () => toast.success('Политика доступа изменена')); + model.setAccessPolicy(newPolicy, () => toast.success(information.changesSaved)); }, [model] ); const setEditors = useCallback( (newEditors: UserID[]) => { - model.setEditors(newEditors, () => toast.success('Редакторы обновлены')); + model.setEditors(newEditors, () => toast.success(information.changesSaved)); }, [model] ); diff --git a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx index 2f37de51..ee299aa0 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/RSTabs.tsx @@ -20,7 +20,7 @@ import { useRSForm } from '@/context/RSFormContext'; import useQueryStrings from '@/hooks/useQueryStrings'; import { ConstituentaID, IConstituenta, IConstituentaMeta } from '@/models/rsform'; import { PARAMETER, prefixes } from '@/utils/constants'; -import { labelVersion } from '@/utils/labels'; +import { information, labelVersion, prompts } from '@/utils/labels'; import EditorConstituenta from './EditorConstituenta'; import EditorRSForm from './EditorRSFormCard'; @@ -173,11 +173,11 @@ function RSTabs() { ); const onDestroySchema = useCallback(() => { - if (!schema || !window.confirm('Вы уверены, что хотите удалить данную схему?')) { + if (!schema || !window.confirm(prompts.deleteLibraryItem)) { return; } destroyItem(schema.id, () => { - toast.success('Схема удалена'); + toast.success(information.itemDestroyed); router.push(urls.library); }); }, [schema, destroyItem, router]); diff --git a/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx b/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx index 890a7972..ce61faaf 100644 --- a/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx +++ b/rsconcept/frontend/src/pages/UserProfilePage/EditorPassword.tsx @@ -13,6 +13,7 @@ import TextInput from '@/components/ui/TextInput'; import { useAuth } from '@/context/AuthContext'; import { useConceptNavigation } from '@/context/NavigationContext'; import { IUserUpdatePassword } from '@/models/user'; +import { errors, information } from '@/utils/labels'; function EditorPassword() { const router = useConceptNavigation(); @@ -37,7 +38,7 @@ function EditorPassword() { function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (newPassword !== newPasswordRepeat) { - toast.error('Пароли не совпадают'); + toast.error(errors.passwordsMismatch); return; } const data: IUserUpdatePassword = { @@ -45,7 +46,7 @@ function EditorPassword() { new_password: newPassword }; updatePassword(data, () => { - toast.success('Изменения сохранены'); + toast.success(information.changesSaved); router.push(urls.login); }); } diff --git a/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx b/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx index 4b06b5aa..f1840e80 100644 --- a/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx +++ b/rsconcept/frontend/src/pages/UserProfilePage/EditorProfile.tsx @@ -11,6 +11,7 @@ import TextInput from '@/components/ui/TextInput'; import { useBlockNavigation } from '@/context/NavigationContext'; import { useUserProfile } from '@/context/UserProfileContext'; import { IUserUpdateData } from '@/models/user'; +import { information } from '@/utils/labels'; function EditorProfile() { const { updateUser, user, errorProcessing, processing } = useUserProfile(); @@ -45,7 +46,7 @@ function EditorProfile() { first_name: first_name, last_name: last_name }; - updateUser(data, () => toast.success('Изменения сохранены')); + updateUser(data, () => toast.success(information.changesSaved)); } return ( diff --git a/rsconcept/frontend/src/utils/labels.ts b/rsconcept/frontend/src/utils/labels.ts index 697e0f8b..25f2704f 100644 --- a/rsconcept/frontend/src/utils/labels.ts +++ b/rsconcept/frontend/src/utils/labels.ts @@ -852,9 +852,59 @@ export function describeLibraryItemType(itemType: LibraryItemType): string { } /** - * UI shared messages. + * UI info descriptors. */ -export const messages = { - unsaved: 'Сохраните или отмените изменения', - promptUnsaved: 'Присутствуют несохраненные изменения. Продолжить без их учета?' +export const information = { + changesSaved: 'Изменения сохранены', + + subscribed: 'Отслеживание отключено', + unsubscribed: 'Отслеживание выключено', + + substituteSingle: 'Отождествление завершено', + reorderComplete: 'Упорядочение завершено', + reindexComplete: 'Имена конституент обновлены', + moveComplete: 'Перемещение завершено', + linkReady: 'Ссылка скопирована', + versionRestored: 'Загрузка версии завершена', + cloneComplete: (alias: string) => `Копия создана: ${alias}`, + + addedConstituents: (count: number) => `Добавлены конституенты: ${count}`, + newLibraryItem: 'Схема успешно создана', + newConstituent: (alias: string) => `Конституента добавлена: ${alias}`, + newVersion: (version: string) => `Версия создана: ${version}`, + renameComplete: (oldAlias: string, newAlias: string) => `Переименование: ${oldAlias} -> ${newAlias}`, + + versionDestroyed: 'Версия удалена', + itemDestroyed: 'Схема удалена', + constituentsDestroyed: (aliases: string) => `Конституенты удалены: ${aliases}` }; + +/** + * UI error descriptors. + */ +export const errors = { + astFailed: 'Невозможно построить дерево разбора', + passwordsMismatch: 'Пароли не совпадают' +}; + +/** + * UI tooltip descriptors. + */ +export const tooltips = { + unsaved: 'Сохраните или отмените изменения' +}; + +/** + * UI prompt messages. + */ +export const prompts = { + promptUnsaved: 'Присутствуют несохраненные изменения. Продолжить без их учета?', + deleteLibraryItem: 'Вы уверены, что хотите удалить данную схему?', + generateWordforms: 'Данное действие приведет к перезаписи словоформ при совпадении граммем. Продолжить?', + restoreArchive: 'При восстановлении архивной версии актуальная схему будет заменена. Продолжить?' +}; + +// ============== INTERNAL LABELS FOR DEVELOPERS TEXT ================ +export function contextOutsideScope(contextName: string, contextState: string): string { + return `${contextName} has to be used within <${contextState}.Provider>`; +} diff --git a/rsconcept/frontend/src/utils/utils.ts b/rsconcept/frontend/src/utils/utils.ts index 5970e2b8..a775d679 100644 --- a/rsconcept/frontend/src/utils/utils.ts +++ b/rsconcept/frontend/src/utils/utils.ts @@ -4,7 +4,7 @@ import { AxiosHeaderValue, AxiosResponse } from 'axios'; -import { messages } from './labels'; +import { prompts } from './labels'; /** * Checks if arguments is Node. @@ -102,7 +102,7 @@ export function convertBase64ToBlob(base64String: string): Uint8Array { * Prompt user of confirming discarding changes before continue. */ export function promptUnsaved(): boolean { - return window.confirm(messages.promptUnsaved); + return window.confirm(prompts.promptUnsaved); } /**