From 0d5f5ed59ff4f465437fda6d0ba1a771db87e688 Mon Sep 17 00:00:00 2001 From: M Fahru Date: Tue, 27 Dec 2022 12:54:21 -0700 Subject: [PATCH] replace save project setting hooks with common function and implement set root doc id change GitOrigin-RevId: e5b204cd93fc188288def529cb22018b3d4f89b6 --- .../hooks/use-set-project-wide-settings.tsx | 53 ++++--------------- .../hooks/use-set-root-doc-id.tsx | 32 +++++++++++ .../js/features/editor-left-menu/utils/api.ts | 22 +++++++- 3 files changed, 64 insertions(+), 43 deletions(-) create mode 100644 services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx index d8cae54cb7..294d465770 100644 --- a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx @@ -1,80 +1,49 @@ import { useCallback } from 'react' import { ProjectCompiler } from '../../../../../types/project-settings' -import { postJSON } from '../../../infrastructure/fetch-json' import { useProjectContext } from '../../../shared/context/project-context' import useScopeValue from '../../../shared/hooks/use-scope-value' - -type ProjectScope = { - compiler: ProjectCompiler - imageName: string - rootDoc_id: string - spellCheckLanguage: string -} - -function useSaveProjectSettings() { - const { _id: projectId } = useProjectContext() - - const saveProject = useCallback( - (data: Partial) => { - postJSON(`/project/${projectId}/settings`, { - body: data, - }) - }, - [projectId] - ) - - return saveProject -} +import { ProjectSettingsScope, saveProjectSettings } from '../utils/api' +import useSetRootDocId from './use-set-root-doc-id' // TODO: handle ignoreUpdates export default function useSetProjectWideSettings() { // The value will be undefined on mount - const [project, setProject] = useScopeValue( + const [project, setProject] = useScopeValue( 'project', true ) - - const saveProject = useSaveProjectSettings() + const { _id: projectId } = useProjectContext() const setCompiler = useCallback( (compiler: ProjectCompiler) => { if (project?.compiler) { setProject({ ...project, compiler }) - saveProject({ compiler }) + saveProjectSettings(projectId, { compiler }) } }, - [saveProject, project, setProject] + [projectId, project, setProject] ) const setImageName = useCallback( (imageName: string) => { if (project?.imageName) { setProject({ ...project, imageName }) - saveProject({ imageName }) + saveProjectSettings(projectId, { imageName }) } }, - [saveProject, project, setProject] + [projectId, project, setProject] ) - // TODO - const setRootDocId = useCallback( - (rootDocId: string) => { - if (project?.imageName) { - setProject({ ...project, rootDoc_id: rootDocId }) - // saveProject({ root }) - } - }, - [project, setProject] - ) + const setRootDocId = useSetRootDocId() const setSpellCheckLanguage = useCallback( (spellCheckLanguage: string) => { if (project?.spellCheckLanguage) { setProject({ ...project, spellCheckLanguage }) - saveProject({ spellCheckLanguage }) + saveProjectSettings(projectId, { spellCheckLanguage }) } }, - [saveProject, project, setProject] + [projectId, project, setProject] ) return { diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx new file mode 100644 index 0000000000..33933644a6 --- /dev/null +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx @@ -0,0 +1,32 @@ +import { useCallback } from 'react' +import { useEditorContext } from '../../../shared/context/editor-context' +import { useProjectContext } from '../../../shared/context/project-context' +import useScopeValue from '../../../shared/hooks/use-scope-value' +import { saveProjectSettings } from '../utils/api' + +export default function useSetRootDocId() { + const [rootDocIdScope, setRootDocIdScope] = + useScopeValue('project.rootDoc_id') + const { permissionsLevel } = useEditorContext() + const { _id: projectId } = useProjectContext() + + const setRootDocId = useCallback( + async (rootDocId: string) => { + const disallowChange = + typeof rootDocIdScope === 'undefined' || + permissionsLevel === 'readOnly' || + rootDocIdScope === rootDocId + + if (!disallowChange) { + try { + await saveProjectSettings(projectId, { rootDoc_id: rootDocId }) + setRootDocIdScope(rootDocId) + } catch (err) { + // TODO: retry mechanism (max 10x before failed completely and rollback the old value) + } + } + }, + [permissionsLevel, projectId, rootDocIdScope, setRootDocIdScope] + ) + return setRootDocId +} diff --git a/services/web/frontend/js/features/editor-left-menu/utils/api.ts b/services/web/frontend/js/features/editor-left-menu/utils/api.ts index d8d04d22b9..d4d59c32b8 100644 --- a/services/web/frontend/js/features/editor-left-menu/utils/api.ts +++ b/services/web/frontend/js/features/editor-left-menu/utils/api.ts @@ -3,7 +3,11 @@ import { LineHeight, OverallTheme, } from '../../../../../modules/source-editor/frontend/js/extensions/theme' -import { Keybindings, PdfViewer } from '../../../../../types/project-settings' +import { + Keybindings, + PdfViewer, + ProjectCompiler, +} from '../../../../../types/project-settings' import { postJSON } from '../../../infrastructure/fetch-json' export type UserSettingsScope = { @@ -24,3 +28,19 @@ export function saveUserSettings(data: Partial) { body: data, }) } + +export type ProjectSettingsScope = { + compiler: ProjectCompiler + imageName: string + rootDoc_id: string + spellCheckLanguage: string +} + +export const saveProjectSettings = async ( + projectId: string, + data: Partial +) => { + await postJSON(`/project/${projectId}/settings`, { + body: data, + }) +}