From 539ed87ddf248079bd01674da9341f9eb5c5e929 Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Wed, 15 Jan 2025 23:03:23 +0300 Subject: [PATCH] R: Replace AccessMode with RoleStore --- .../src/context/AccessModeContext.tsx | 25 ---------- rsconcept/frontend/src/models/user.ts | 2 +- .../src/pages/OssPage/MenuOssTabs.tsx | 47 ++++++++++--------- .../src/pages/OssPage/OssEditContext.tsx | 35 +++++--------- .../frontend/src/pages/OssPage/OssPage.tsx | 9 ++-- .../EditorRSFormCard/EditorLibraryItem.tsx | 14 +++--- .../EditorRSFormCard/ToolbarItemAccess.tsx | 12 ++--- .../EditorRSFormCard/ToolbarRSFormCard.tsx | 8 ++-- .../src/pages/RSFormPage/MenuRSTabs.tsx | 45 +++++++++--------- .../src/pages/RSFormPage/RSEditContext.tsx | 34 +++++--------- .../src/pages/RSFormPage/RSFormPage.tsx | 9 ++-- .../ViewConstituents/ViewConstituents.tsx | 8 ++-- rsconcept/frontend/src/stores/role.ts | 37 +++++++++++++++ rsconcept/frontend/src/utils/labels.ts | 26 +++++----- 14 files changed, 147 insertions(+), 164 deletions(-) delete mode 100644 rsconcept/frontend/src/context/AccessModeContext.tsx create mode 100644 rsconcept/frontend/src/stores/role.ts diff --git a/rsconcept/frontend/src/context/AccessModeContext.tsx b/rsconcept/frontend/src/context/AccessModeContext.tsx deleted file mode 100644 index c8fe0bcc..00000000 --- a/rsconcept/frontend/src/context/AccessModeContext.tsx +++ /dev/null @@ -1,25 +0,0 @@ -'use client'; - -import { createContext, useContext, useState } from 'react'; - -import { UserLevel } from '@/models/user'; -import { contextOutsideScope } from '@/utils/labels'; - -interface IAccessModeContext { - accessLevel: UserLevel; - setAccessLevel: React.Dispatch>; -} - -const AccessContext = createContext(null); -export const useAccessMode = () => { - const context = useContext(AccessContext); - if (!context) { - throw new Error(contextOutsideScope('useAccessMode', 'AccessModeState')); - } - return context; -}; - -export const AccessModeState = ({ children }: React.PropsWithChildren) => { - const [accessLevel, setAccessLevel] = useState(UserLevel.READER); - return {children}; -}; diff --git a/rsconcept/frontend/src/models/user.ts b/rsconcept/frontend/src/models/user.ts index 485f970b..f7e9b7c2 100644 --- a/rsconcept/frontend/src/models/user.ts +++ b/rsconcept/frontend/src/models/user.ts @@ -103,7 +103,7 @@ export interface ITargetUsers { /** * Represents user access mode. */ -export enum UserLevel { +export enum UserRole { READER = 0, EDITOR, OWNER, diff --git a/rsconcept/frontend/src/pages/OssPage/MenuOssTabs.tsx b/rsconcept/frontend/src/pages/OssPage/MenuOssTabs.tsx index c2708522..a96894f5 100644 --- a/rsconcept/frontend/src/pages/OssPage/MenuOssTabs.tsx +++ b/rsconcept/frontend/src/pages/OssPage/MenuOssTabs.tsx @@ -19,13 +19,13 @@ import Button from '@/components/ui/Button'; import Divider from '@/components/ui/Divider'; import Dropdown from '@/components/ui/Dropdown'; import DropdownButton from '@/components/ui/DropdownButton'; -import { useAccessMode } from '@/context/AccessModeContext'; import { useAuth } from '@/context/AuthContext'; import { useConceptNavigation } from '@/context/NavigationContext'; import { useOSS } from '@/context/OssContext'; import useDropdown from '@/hooks/useDropdown'; -import { UserLevel } from '@/models/user'; -import { describeAccessMode, labelAccessMode } from '@/utils/labels'; +import { UserRole } from '@/models/user'; +import { useRoleStore } from '@/stores/role'; +import { describeAccessMode as describeUserRole, labelAccessMode as labelUserRole } from '@/utils/labels'; import { useOssEdit } from './OssEditContext'; @@ -39,7 +39,8 @@ function MenuOssTabs({ onDestroy }: MenuOssTabsProps) { const { user } = useAuth(); const model = useOSS(); - const { accessLevel, setAccessLevel } = useAccessMode(); + const role = useRoleStore(state => state.role); + const setRole = useRoleStore(state => state.setRole); const schemaMenu = useDropdown(); const editMenu = useDropdown(); @@ -55,9 +56,9 @@ function MenuOssTabs({ onDestroy }: MenuOssTabsProps) { controller.share(); } - function handleChangeMode(newMode: UserLevel) { + function handleChangeRole(newMode: UserRole) { accessMenu.hide(); - setAccessLevel(newMode); + setRole(newMode); } function handleCreateNew() { @@ -97,7 +98,7 @@ function MenuOssTabs({ onDestroy }: MenuOssTabsProps) { } - disabled={controller.isProcessing || accessLevel < UserLevel.OWNER} + disabled={controller.isProcessing || role < UserRole.OWNER} onClick={handleDelete} /> ) : null} @@ -151,15 +152,15 @@ function MenuOssTabs({ onDestroy }: MenuOssTabsProps) { noBorder noOutline tabIndex={-1} - title={`Режим ${labelAccessMode(accessLevel)}`} + title={`Режим ${labelUserRole(role)}`} hideTitle={accessMenu.isOpen} className='h-full pr-2' icon={ - accessLevel === UserLevel.ADMIN ? ( + role === UserRole.ADMIN ? ( - ) : accessLevel === UserLevel.OWNER ? ( + ) : role === UserRole.OWNER ? ( - ) : accessLevel === UserLevel.EDITOR ? ( + ) : role === UserRole.EDITOR ? ( ) : ( @@ -169,31 +170,31 @@ function MenuOssTabs({ onDestroy }: MenuOssTabsProps) { /> } - onClick={() => handleChangeMode(UserLevel.READER)} + onClick={() => handleChangeRole(UserRole.READER)} /> } disabled={!model.isOwned && !model.schema?.editors.includes(user.id)} - onClick={() => handleChangeMode(UserLevel.EDITOR)} + onClick={() => handleChangeRole(UserRole.EDITOR)} /> } disabled={!model.isOwned} - onClick={() => handleChangeMode(UserLevel.OWNER)} + onClick={() => handleChangeRole(UserRole.OWNER)} /> } disabled={!user?.is_staff} - onClick={() => handleChangeMode(UserLevel.ADMIN)} + onClick={() => handleChangeRole(UserRole.ADMIN)} /> diff --git a/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx b/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx index aba686f1..99b695ab 100644 --- a/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx +++ b/rsconcept/frontend/src/pages/OssPage/OssEditContext.tsx @@ -4,7 +4,6 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useState } import { toast } from 'react-toastify'; import { urls } from '@/app/urls'; -import { useAccessMode } from '@/context/AccessModeContext'; import { useAuth } from '@/context/AuthContext'; import { useLibrary } from '@/context/LibraryContext'; import { useConceptNavigation } from '@/context/NavigationContext'; @@ -30,8 +29,9 @@ import { OperationID, OperationType } from '@/models/oss'; -import { UserID, UserLevel } from '@/models/user'; +import { UserID, UserRole } from '@/models/user'; import { usePreferencesStore } from '@/stores/preferences'; +import { useRoleStore } from '@/stores/role'; import { PARAMETER } from '@/utils/constants'; import { errors, information } from '@/utils/labels'; @@ -96,14 +96,13 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit const router = useConceptNavigation(); const { user } = useAuth(); const adminMode = usePreferencesStore(state => state.adminMode); - const { accessLevel, setAccessLevel } = useAccessMode(); + + const role = useRoleStore(state => state.role); + const adjustRole = useRoleStore(state => state.adjustRole); const model = useOSS(); const library = useLibrary(); - const isMutable = useMemo( - () => accessLevel > UserLevel.READER && !model.schema?.read_only, - [accessLevel, model.schema?.read_only] - ); + const isMutable = role > UserRole.READER && !model.schema?.read_only; const [showTooltip, setShowTooltip] = useState(true); @@ -128,23 +127,13 @@ export const OssEditState = ({ selected, setSelected, children }: React.PropsWit useEffect( () => - setAccessLevel(prev => { - if ( - prev === UserLevel.EDITOR && - (model.isOwned || user?.is_staff || (user && model.schema?.editors.includes(user.id))) - ) { - return UserLevel.EDITOR; - } else if (user?.is_staff && (prev === UserLevel.ADMIN || adminMode)) { - return UserLevel.ADMIN; - } else if (model.isOwned) { - return UserLevel.OWNER; - } else if (user?.id && model.schema?.editors.includes(user?.id)) { - return UserLevel.EDITOR; - } else { - return UserLevel.READER; - } + adjustRole({ + isOwner: model.isOwned, + isEditor: (user && model.schema?.editors.includes(user?.id)) ?? false, + isStaff: user?.is_staff ?? false, + adminMode: adminMode }), - [model.schema, setAccessLevel, model.isOwned, user, adminMode] + [model.schema, adjustRole, model.isOwned, user, adminMode] ); const handleSetLocation = useCallback( diff --git a/rsconcept/frontend/src/pages/OssPage/OssPage.tsx b/rsconcept/frontend/src/pages/OssPage/OssPage.tsx index d0dae55a..a5118e00 100644 --- a/rsconcept/frontend/src/pages/OssPage/OssPage.tsx +++ b/rsconcept/frontend/src/pages/OssPage/OssPage.tsx @@ -2,7 +2,6 @@ import { useParams } from 'react-router'; -import { AccessModeState } from '@/context/AccessModeContext'; import { OssState } from '@/context/OssContext'; import OssTabs from './OssTabs'; @@ -10,11 +9,9 @@ import OssTabs from './OssTabs'; function OssPage() { const params = useParams(); return ( - - - - - + + + ); } diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/EditorLibraryItem.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/EditorLibraryItem.tsx index 43916f0c..98b38799 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/EditorLibraryItem.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/EditorLibraryItem.tsx @@ -17,13 +17,13 @@ import MiniButton from '@/components/ui/MiniButton'; import Overlay from '@/components/ui/Overlay'; import Tooltip from '@/components/ui/Tooltip'; import ValueIcon from '@/components/ui/ValueIcon'; -import { useAccessMode } from '@/context/AccessModeContext'; import { useConceptNavigation } from '@/context/NavigationContext'; import { useUsers } from '@/context/UsersContext'; import useDropdown from '@/hooks/useDropdown'; import { ILibraryItemData, ILibraryItemEditor } from '@/models/library'; -import { UserID, UserLevel } from '@/models/user'; +import { UserID, UserRole } from '@/models/user'; import { useLibrarySearchStore } from '@/stores/librarySearch'; +import { useRoleStore } from '@/stores/role'; import { prefixes } from '@/utils/constants'; import { prompts } from '@/utils/labels'; @@ -35,7 +35,7 @@ interface EditorLibraryItemProps { function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemProps) { const { getUserLabel, users } = useUsers(); - const { accessLevel } = useAccessMode(); + const role = useRoleStore(state => state.role); const intl = useIntl(); const router = useConceptNavigation(); const setLocation = useLibrarySearchStore(state => state.setLocation); @@ -86,9 +86,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr value={item.location} title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'} onClick={controller.promptLocation} - disabled={ - isModified || controller.isProcessing || controller.isAttachedToOSS || accessLevel < UserLevel.OWNER - } + disabled={isModified || controller.isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER} /> @@ -110,7 +108,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr value={getUserLabel(item.owner)} title={controller.isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Владелец'} onClick={ownerSelector.toggle} - disabled={isModified || controller.isProcessing || controller.isAttachedToOSS || accessLevel < UserLevel.OWNER} + disabled={isModified || controller.isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER} />
@@ -120,7 +118,7 @@ function EditorLibraryItem({ item, isModified, controller }: EditorLibraryItemPr icon={} value={item.editors.length} onClick={controller.promptEditors} - disabled={isModified || controller.isProcessing || accessLevel < UserLevel.OWNER} + disabled={isModified || controller.isProcessing || role < UserRole.OWNER} /> diff --git a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/ToolbarItemAccess.tsx b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/ToolbarItemAccess.tsx index a5668a24..c04f528e 100644 --- a/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/ToolbarItemAccess.tsx +++ b/rsconcept/frontend/src/pages/RSFormPage/EditorRSFormCard/ToolbarItemAccess.tsx @@ -5,10 +5,10 @@ import SelectAccessPolicy from '@/components/select/SelectAccessPolicy'; import Label from '@/components/ui/Label'; import MiniButton from '@/components/ui/MiniButton'; import Overlay from '@/components/ui/Overlay'; -import { useAccessMode } from '@/context/AccessModeContext'; import { AccessPolicy, ILibraryItemEditor } from '@/models/library'; import { HelpTopic } from '@/models/miscellaneous'; -import { UserLevel } from '@/models/user'; +import { UserRole } from '@/models/user'; +import { useRoleStore } from '@/stores/role'; import { PARAMETER } from '@/utils/constants'; interface ToolbarItemAccessProps { @@ -20,7 +20,7 @@ interface ToolbarItemAccessProps { } function ToolbarItemAccess({ visible, toggleVisible, readOnly, toggleReadOnly, controller }: ToolbarItemAccessProps) { - const { accessLevel } = useAccessMode(); + const role = useRoleStore(state => state.role); const policy = controller.schema?.access_policy ?? AccessPolicy.PRIVATE; return ( @@ -28,7 +28,7 @@ function ToolbarItemAccess({ visible, toggleVisible, readOnly, toggleReadOnly, c