Преглед изворни кода

Use permissions.write for editor editable state (#16011)

GitOrigin-RevId: b38ce53fa90a739d9e38ddcc57b01dfa0d9a104c
Alf Eaton пре 2 година
родитељ
комит
18ad44c278

+ 6 - 0
services/web/frontend/js/features/ide-react/context/ide-react-context.tsx

@@ -49,6 +49,12 @@ function populateIdeReactScope(store: ReactScopeValueStore) {
 function populateProjectScope(store: ReactScopeValueStore) {
   store.allowNonExistentPath('project', true)
   store.set('permissionsLevel', 'readOnly')
+  store.set('permissions', {
+    read: true,
+    write: false,
+    admin: false,
+    comment: true,
+  })
 }
 
 function populatePdfScope(store: ReactScopeValueStore) {

+ 1 - 1
services/web/frontend/js/features/ide-react/context/metadata-context.tsx

@@ -54,7 +54,7 @@ export const MetadataProvider: FC = ({ children }) => {
   const { socket } = useConnectionContext()
   const { onlineUsersCount } = useOnlineUsersContext()
   const { permissionsLevel } = useEditorContext()
-  const { permissions } = usePermissionsContext()
+  const permissions = usePermissionsContext()
   const { currentDocument } = useEditorManagerContext()
   const { showGenericMessageModal } = useModalsContext()
 

+ 45 - 82
services/web/frontend/js/features/ide-react/context/permissions-context.tsx

@@ -1,110 +1,73 @@
-import { createContext, useContext, useState, useEffect, useMemo } from 'react'
+import { createContext, useContext, useEffect } from 'react'
 import { useConnectionContext } from '@/features/ide-react/context/connection-context'
 import { useEditorContext } from '@/shared/context/editor-context'
 import getMeta from '@/utils/meta'
-import { Permissions } from '@/features/ide-react/types/permissions'
+import {
+  Permissions,
+  PermissionsLevel,
+} from '@/features/ide-react/types/permissions'
+import useScopeValue from '@/shared/hooks/use-scope-value'
+import { DeepReadonly } from '../../../../../types/utils'
 
-type PermissionsContextValue = {
-  permissions: Permissions
-}
-
-const PermissionsContext = createContext<PermissionsContextValue | undefined>(
-  undefined
-)
+const PermissionsContext = createContext<Permissions | undefined>(undefined)
 
-const readOnlyPermissions: Readonly<Permissions> = {
-  read: true,
-  write: false,
-  admin: false,
-  comment: true,
-}
-const readAndWritePermissions: Readonly<Permissions> = {
-  read: true,
-  write: true,
-  admin: false,
-  comment: true,
+const permissionsMap: DeepReadonly<Record<PermissionsLevel, Permissions>> = {
+  readOnly: {
+    read: true,
+    write: false,
+    admin: false,
+    comment: true,
+  },
+  readAndWrite: {
+    read: true,
+    write: true,
+    admin: false,
+    comment: true,
+  },
+  owner: {
+    read: true,
+    write: true,
+    admin: true,
+    comment: true,
+  },
 }
-const ownerPermissions: Readonly<Permissions> = {
-  read: true,
-  write: true,
-  admin: true,
-  comment: true,
+
+const anonymousPermissionsMap: typeof permissionsMap = {
+  readOnly: { ...permissionsMap.readOnly, comment: false },
+  readAndWrite: { ...permissionsMap.readAndWrite, comment: false },
+  owner: { ...permissionsMap.owner, comment: false },
 }
-const permissionsMap = {
-  readOnly: readOnlyPermissions,
-  readAndWrite: readAndWritePermissions,
-  owner: ownerPermissions,
-  anonymous: {
-    readOnly: { ...readOnlyPermissions, comment: false },
-    readAndWrite: { ...readAndWritePermissions, comment: false },
-    owner: { ...ownerPermissions, comment: false },
-  },
-} as const
 
 export const PermissionsProvider: React.FC = ({ children }) => {
-  const [permissions, setPermissions] = useState<Permissions>({
-    read: false,
-    write: false,
-    admin: false,
-    comment: false,
-  })
+  const [permissions, setPermissions] =
+    useScopeValue<Readonly<Permissions>>('permissions')
   const { connectionState } = useConnectionContext()
-  const { permissionsLevel } = useEditorContext()
+  const { permissionsLevel } = useEditorContext() as {
+    permissionsLevel: PermissionsLevel
+  }
   const anonymous = getMeta('ol-anonymous') as boolean | undefined
 
   useEffect(() => {
-    if (permissionsLevel === 'readOnly') {
-      if (anonymous) {
-        setPermissions(permissionsMap.anonymous.readOnly)
-      } else {
-        setPermissions(permissionsMap.readOnly)
-      }
-    }
-    if (permissionsLevel === 'readAndWrite') {
-      if (permissions.admin) {
-        if (anonymous) {
-          setPermissions(permissionsMap.anonymous.owner)
-        } else {
-          setPermissions(permissionsMap.owner)
-        }
-      } else {
-        if (anonymous) {
-          setPermissions(permissionsMap.anonymous.readAndWrite)
-        } else {
-          setPermissions(permissionsMap.readAndWrite)
-        }
-      }
-    }
-    if (permissionsLevel === 'owner') {
-      if (anonymous) {
-        setPermissions(permissionsMap.anonymous.owner)
-      } else {
-        setPermissions(permissionsMap.owner)
-      }
-    }
-  }, [anonymous, permissions, permissionsLevel])
+    const activePermissionsMap = anonymous
+      ? anonymousPermissionsMap
+      : permissionsMap
+    setPermissions(activePermissionsMap[permissionsLevel])
+  }, [anonymous, permissionsLevel, setPermissions])
 
   useEffect(() => {
     if (connectionState.forceDisconnected) {
       setPermissions(prevState => ({ ...prevState, write: false }))
     }
-  }, [connectionState.forceDisconnected])
-
-  const value = useMemo<PermissionsContextValue>(
-    () => ({
-      permissions,
-    }),
-    [permissions]
-  )
+  }, [connectionState.forceDisconnected, setPermissions])
 
   return (
-    <PermissionsContext.Provider value={value}>
+    <PermissionsContext.Provider value={permissions}>
       {children}
     </PermissionsContext.Provider>
   )
 }
 
-export function usePermissionsContext(): PermissionsContextValue {
+export function usePermissionsContext() {
   const context = useContext(PermissionsContext)
 
   if (!context) {

+ 1 - 1
services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts

@@ -129,7 +129,7 @@ function useReviewPanelState(): ReviewPanelStateReactIde {
   } = project
   const { isRestrictedTokenMember } = useEditorContext()
   // TODO permissions to be removed from the review panel context. It currently acts just as a proxy.
-  const { permissions } = usePermissionsContext()
+  const permissions = usePermissionsContext()
   const { showGenericMessageModal } = useModalsContext()
   const addCommentEmitter = useScopeEventEmitter('comment:start_adding')
 

+ 5 - 5
services/web/frontend/js/features/source-editor/hooks/use-codemirror-scope.ts

@@ -26,7 +26,6 @@ import { useIdeContext } from '../../../shared/context/ide-context'
 import { restoreScrollPosition } from '../extensions/scroll-position'
 import { setEditable } from '../extensions/editable'
 import { useFileTreeData } from '../../../shared/context/file-tree-data-context'
-import { useEditorContext } from '../../../shared/context/editor-context'
 import { setAutoPair } from '../extensions/auto-pair'
 import { setAutoComplete } from '../extensions/auto-complete'
 import { usePhrases } from './use-phrases'
@@ -51,7 +50,8 @@ function useCodeMirrorScope(view: EditorView) {
   const ide = useIdeContext()
 
   const { fileTreeData } = useFileTreeData()
-  const { permissionsLevel } = useEditorContext()
+
+  const [permissions] = useScopeValue<{ write: boolean }>('permissions')
 
   // set up scope listeners
 
@@ -240,7 +240,7 @@ function useCodeMirrorScope(view: EditorView) {
     }
   }, [view, fileTreeData])
 
-  const editableRef = useRef(permissionsLevel !== 'readOnly')
+  const editableRef = useRef(permissions.write)
 
   const { previewByPath } = useFileTreePathContext()
 
@@ -317,9 +317,9 @@ function useCodeMirrorScope(view: EditorView) {
   }, [view, previewByPath])
 
   useEffect(() => {
-    editableRef.current = permissionsLevel !== 'readOnly'
+    editableRef.current = permissions.write
     view.dispatch(setEditable(editableRef.current)) // the editor needs to be locked when there's a problem saving data
-  }, [view, permissionsLevel])
+  }, [view, permissions.write])
 
   useEffect(() => {
     phrasesRef.current = phrases

+ 1 - 1
services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-readonly.spec.tsx

@@ -13,7 +13,7 @@ const mountEditor = (
   props?: Omit<ComponentProps<typeof EditorProviders>, 'children' | 'scope'>
 ) => {
   const scope = mockScope(content)
-  scope.permissionsLevel = 'readOnly'
+  scope.permissions.write = false
   scope.editor.showVisual = true
 
   cy.mount(

+ 1 - 0
services/web/test/frontend/features/source-editor/components/codemirror-editor.spec.tsx

@@ -227,6 +227,7 @@ describe('<CodeMirrorEditor/>', { scrollBehavior: false }, function () {
   it('does not allow typing to the document in read-only mode', function () {
     const scope = mockScope()
     scope.permissionsLevel = 'readOnly'
+    scope.permissions.write = false
 
     cy.mount(
       <Container>