Refactor project-wide settings:

- Change api function argument (readability)
- create a new wrapper hooks for saving the project to both server-side and angular scope
- Implement the new save project settings hooks on project-wide settings update
- On spell check language update function, add new comment to give more context about the decision

GitOrigin-RevId: 93d558d1e1d4db265a943eeb4366842430900c43
This commit is contained in:
M Fahru 2023-01-06 18:45:37 -07:00 committed by Copybot
parent 654144dd40
commit 7475237170
5 changed files with 60 additions and 54 deletions

View file

@ -1,40 +1,27 @@
import { useCallback } from 'react'
import { useProjectContext } from '../../../shared/context/project-context'
import useScopeValue from '../../../shared/hooks/use-scope-value'
import { type ProjectSettings, saveProjectSettings } from '../utils/api'
import type { ProjectSettings } from '../utils/api'
import useRootDocId from './use-root-doc-id'
import useSaveProjectSettings from './use-save-project-settings'
import useSetSpellCheckLanguage from './use-set-spell-check-language'
export default function useProjectWideSettings() {
// The value will be undefined on mount
const [project, setProject] = useScopeValue<ProjectSettings | undefined>(
'project',
true
)
const { _id: projectId } = useProjectContext()
const [project] = useScopeValue<ProjectSettings | undefined>('project', true)
const saveProjectSettings = useSaveProjectSettings()
const setCompiler = useCallback(
(compiler: ProjectSettings['compiler']) => {
const allowUpdate = project?.compiler
if (allowUpdate) {
setProject({ ...project, compiler })
saveProjectSettings({ projectId, compiler })
}
(newCompiler: ProjectSettings['compiler']) => {
saveProjectSettings('compiler', newCompiler)
},
[projectId, project, setProject]
[saveProjectSettings]
)
const setImageName = useCallback(
(imageName: ProjectSettings['imageName']) => {
const allowUpdate = project?.imageName
if (allowUpdate) {
setProject({ ...project, imageName })
saveProjectSettings({ projectId, imageName })
}
(newImageName: ProjectSettings['imageName']) => {
saveProjectSettings('imageName', newImageName)
},
[projectId, project, setProject]
[saveProjectSettings]
)
const { setRootDocId, rootDocId } = useRootDocId()

View file

@ -1,32 +1,30 @@
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 { type ProjectSettings, saveProjectSettings } from '../utils/api'
import type { ProjectSettings } from '../utils/api'
import useSaveProjectSettings from './use-save-project-settings'
export default function useRootDocId() {
const [rootDocId, setRootDocId] =
const [rootDocId] =
useScopeValue<ProjectSettings['rootDocId']>('project.rootDoc_id')
const { permissionsLevel } = useEditorContext()
const { _id: projectId } = useProjectContext()
const saveProjectSettings = useSaveProjectSettings()
const setRootDocIdFunc = useCallback(
async (newRootDocId: ProjectSettings['rootDocId']) => {
// rootDoc_id will be undefined on angular scope on initialisation
const allowUpdate =
typeof rootDocId !== 'undefined' &&
permissionsLevel !== 'readOnly' &&
rootDocId !== newRootDocId
typeof rootDocId !== 'undefined' && permissionsLevel !== 'readOnly'
if (allowUpdate) {
try {
await saveProjectSettings({ projectId, rootDocId: newRootDocId })
setRootDocId(newRootDocId)
await saveProjectSettings('rootDocId', newRootDocId)
} catch (err) {
// TODO: retry mechanism (max 10x before failed completely and rollback the old value)
}
}
},
[permissionsLevel, projectId, rootDocId, setRootDocId]
[permissionsLevel, rootDocId, saveProjectSettings]
)
return {

View file

@ -0,0 +1,28 @@
import { type ProjectSettings, saveProjectSettings } from '../utils/api'
import { useProjectContext } from '../../../shared/context/project-context'
import useScopeValue from '../../../shared/hooks/use-scope-value'
export default function useSaveProjectSettings() {
// projectSettings value will be undefined on mount
const [projectSettings, setProjectSettings] = useScopeValue<
ProjectSettings | undefined
>('project', true)
const { _id: projectId } = useProjectContext()
return async (
key: keyof ProjectSettings,
newSetting: ProjectSettings[keyof ProjectSettings]
) => {
if (projectSettings) {
const currentSetting = projectSettings[key]
if (currentSetting !== newSetting) {
await saveProjectSettings(projectId, {
[key]: newSetting,
})
setProjectSettings({ ...projectSettings, [key]: newSetting })
}
}
}
}

View file

@ -1,17 +1,13 @@
import { useCallback } from 'react'
import { useProjectContext } from '../../../shared/context/project-context'
import useScopeValue from '../../../shared/hooks/use-scope-value'
import {
type ProjectSettings,
saveProjectSettings,
saveUserSettings,
} from '../utils/api'
import { type ProjectSettings, saveUserSettings } from '../utils/api'
import useSaveProjectSettings from './use-save-project-settings'
export default function useSetSpellCheckLanguage() {
const [spellCheckLanguage, setSpellCheckLanguage] = useScopeValue<
ProjectSettings['spellCheckLanguage']
>('project.spellCheckLanguage')
const { _id: projectId } = useProjectContext()
const saveProjectSettings = useSaveProjectSettings()
return useCallback(
(newSpellCheckLanguage: ProjectSettings['spellCheckLanguage']) => {
@ -21,14 +17,15 @@ export default function useSetSpellCheckLanguage() {
if (allowUpdate) {
setSpellCheckLanguage(newSpellCheckLanguage)
// save to both project setting and user setting
saveProjectSettings({
projectId,
spellCheckLanguage: newSpellCheckLanguage,
})
// Save project settings is created from hooks because it will save the value on
// both server-side and client-side (angular scope)
saveProjectSettings('spellCheckLanguage', newSpellCheckLanguage)
// For user settings, we only need to save it on server-side,
// so we import the function directly without hooks
saveUserSettings('spellCheckLanguage', newSpellCheckLanguage)
}
},
[projectId, setSpellCheckLanguage, spellCheckLanguage]
[setSpellCheckLanguage, spellCheckLanguage, saveProjectSettings]
)
}

View file

@ -53,14 +53,10 @@ export function saveUserSettings(
})
}
type SaveProjectSettings = {
projectId: string
} & Partial<ProjectSettings>
export const saveProjectSettings = async ({
projectId,
...data
}: SaveProjectSettings) => {
export const saveProjectSettings = async (
projectId: string,
data: Partial<ProjectSettings>
) => {
await postJSON<never>(`/project/${projectId}/settings`, {
body: {
...data,