Ver Fonte

Merge pull request #9689 from overleaf/jel-dash-state

[web] Fix dash view state updating

GitOrigin-RevId: e46acf5de76a19ddd66cab3581edc971125dfdee
Jessica Lawshe há 4 anos atrás
pai
commit
341ee52c3f

+ 1 - 4
services/web/frontend/js/features/project-list/components/table/cells/action-buttons/archive-project-button.tsx

@@ -35,10 +35,7 @@ function ArchiveProjectButton({
 
   const handleArchiveProject = useCallback(async () => {
     await archiveProject(project.id)
-
-    // update view
-    project.archived = true
-    updateProjectViewData(project)
+    updateProjectViewData({ ...project, archived: true, selected: false })
   }, [project, updateProjectViewData])
 
   if (project.archived) return null

+ 6 - 4
services/web/frontend/js/features/project-list/components/table/cells/action-buttons/copy-project-button.tsx

@@ -14,7 +14,8 @@ type CopyButtonProps = {
 }
 
 function CopyProjectButton({ project, children }: CopyButtonProps) {
-  const { addClonedProjectToViewData } = useProjectListContext()
+  const { addClonedProjectToViewData, updateProjectViewData } =
+    useProjectListContext()
   const { t } = useTranslation()
   const text = t('copy')
   const [showModal, setShowModal] = useState(false)
@@ -31,16 +32,17 @@ function CopyProjectButton({ project, children }: CopyButtonProps) {
   }, [isMounted])
 
   const handleAfterCloned = useCallback(
-    project => {
+    clonedProject => {
       eventTracking.send(
         'project-list-page-interaction',
         'project action',
         'Clone'
       )
-      addClonedProjectToViewData(project)
+      addClonedProjectToViewData(clonedProject)
+      updateProjectViewData({ ...project, selected: false })
       setShowModal(false)
     },
-    [addClonedProjectToViewData]
+    [addClonedProjectToViewData, project, updateProjectViewData]
   )
 
   if (project.archived || project.trashed) return null

+ 6 - 5
services/web/frontend/js/features/project-list/components/table/cells/action-buttons/trash-project-button.tsx

@@ -32,11 +32,12 @@ function TrashProjectButton({ project, children }: TrashProjectButtonProps) {
 
   const handleTrashProject = useCallback(async () => {
     await trashProject(project.id)
-
-    // update view
-    project.trashed = true
-    project.archived = false
-    updateProjectViewData(project)
+    updateProjectViewData({
+      ...project,
+      trashed: true,
+      archived: false,
+      selected: false,
+    })
   }, [project, updateProjectViewData])
 
   if (project.trashed) return null

+ 1 - 3
services/web/frontend/js/features/project-list/components/table/cells/action-buttons/unarchive-project-button.tsx

@@ -25,9 +25,7 @@ function UnarchiveProjectButton({
   const handleUnarchiveProject = useCallback(async () => {
     await unarchiveProject(project.id)
 
-    // update view
-    project.archived = false
-    updateProjectViewData(project)
+    updateProjectViewData({ ...project, archived: false, selected: false })
   }, [project, updateProjectViewData])
 
   if (!project.archived) return null

+ 1 - 3
services/web/frontend/js/features/project-list/components/table/cells/action-buttons/untrash-project-button.tsx

@@ -24,9 +24,7 @@ function UntrashProjectButton({
 
   const handleUntrashProject = useCallback(async () => {
     await untrashProject(project.id)
-    // update view
-    project.trashed = false
-    updateProjectViewData(project)
+    updateProjectViewData({ ...project, trashed: false, selected: false })
   }, [project, updateProjectViewData])
 
   if (!project.trashed) return null

+ 1 - 2
services/web/frontend/js/features/project-list/components/table/project-list-table-row.tsx

@@ -21,8 +21,7 @@ export default function ProjectListTableRow({
 
   const handleCheckboxChange = useCallback(
     (event: React.ChangeEvent<HTMLInputElement>) => {
-      project.selected = event.target.checked
-      updateProjectViewData(project)
+      updateProjectViewData({ ...project, selected: event.target.checked })
     },
     [project, updateProjectViewData]
   )

+ 2 - 5
services/web/frontend/js/features/project-list/components/table/project-tools/buttons/archive-projects-button.tsx

@@ -28,17 +28,14 @@ function ArchiveProjectsButton() {
   const handleArchiveProjects = useCallback(async () => {
     for (const project of selectedProjects) {
       await archiveProject(project.id)
-      // update view
-      project.archived = true
-      project.selected = false
-      updateProjectViewData(project)
+      updateProjectViewData({ ...project, archived: true, selected: false })
     }
   }, [selectedProjects, updateProjectViewData])
 
   return (
     <>
       <Tooltip
-        id="tooltip-download-projects"
+        id="tooltip-archive-projects"
         description={text}
         overlayProps={{ placement: 'bottom', trigger: ['hover', 'focus'] }}
       >

+ 7 - 6
services/web/frontend/js/features/project-list/components/table/project-tools/buttons/trash-projects-button.tsx

@@ -28,18 +28,19 @@ function TrashProjectsButton() {
   const handleTrashProjects = useCallback(async () => {
     for (const project of selectedProjects) {
       await trashProject(project.id)
-      // update view
-      project.trashed = true
-      project.archived = false
-      project.selected = false
-      updateProjectViewData(project)
+      updateProjectViewData({
+        ...project,
+        trashed: true,
+        archived: false,
+        selected: false,
+      })
     }
   }, [selectedProjects, updateProjectViewData])
 
   return (
     <>
       <Tooltip
-        id="tooltip-download-projects"
+        id="tooltip-trash-projects"
         description={text}
         overlayProps={{ placement: 'bottom', trigger: ['hover', 'focus'] }}
       >

+ 1 - 4
services/web/frontend/js/features/project-list/components/table/project-tools/buttons/untrash-projects-button.tsx

@@ -11,10 +11,7 @@ function UntrashProjectsButton() {
   const handleUntrashProjects = useCallback(async () => {
     for (const [, project] of Object.entries(selectedProjects)) {
       await untrashProject(project.id)
-      // update view
-      project.trashed = false
-      project.selected = false
-      updateProjectViewData(project)
+      updateProjectViewData({ ...project, trashed: false, selected: false })
     }
   }, [selectedProjects, updateProjectViewData])
 

+ 33 - 29
services/web/frontend/js/features/project-list/context/project-list-context.tsx

@@ -81,7 +81,7 @@ type ProjectListContextValue = {
   addTag: (tag: Tag) => void
   renameTag: (tagId: string, newTagName: string) => void
   deleteTag: (tagId: string) => void
-  updateProjectViewData: (project: Project) => void
+  updateProjectViewData: (newProjectData: Project) => void
   removeProjectFromView: (project: Project) => void
   removeProjectFromTagInView: (tagId: string, projectId: string) => void
   searchText: string
@@ -245,11 +245,16 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) {
 
   const selectOrUnselectAllProjects = useCallback(
     checked => {
-      const projects = visibleProjects.map(project => {
-        project.selected = checked
-        return project
-      })
-      setVisibleProjects(projects)
+      const visibleProjectIds = visibleProjects.map(p => p.id)
+      setLoadedProjects(loadedProjects =>
+        loadedProjects.map(p => {
+          if (visibleProjectIds.includes(p.id)) {
+            return { ...p, selected: checked }
+          } else {
+            return p
+          }
+        })
+      )
     },
     [visibleProjects]
   )
@@ -321,40 +326,39 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) {
   const addClonedProjectToViewData = useCallback(
     project => {
       // clone API not using camelCase and does not return all data
-      project.id = project.project_id
+
       const owner = {
         id: project.owner?._id,
         email: project.owner?.email,
         firstName: project.owner?.first_name,
         lastName: project.owner?.last_name,
       }
-      project.owner = owner
-      project.lastUpdatedBy = project.owner
-      project.source = 'owner'
-      project.trashed = false
-      project.archived = false
-      loadedProjects.push(project)
-      const loadedProjectsSorted = sortProjects(loadedProjects, sort)
-      const visibleProjectsSorted = sortProjects(visibleProjects, sort)
-      setVisibleProjects(visibleProjectsSorted)
-      setLoadedProjects(loadedProjectsSorted)
-    },
-    [loadedProjects, visibleProjects, sort]
-  )
 
-  const updateProjectViewData = useCallback(
-    (project: Project) => {
-      const projects = loadedProjects.map((p: Project) => {
-        if (p.id === project.id) {
-          p = project
-        }
-        return p
+      const clonedProject = {
+        ...project,
+        id: project.project_id,
+        owner,
+        lastUpdatedBy: owner,
+        source: 'owner',
+        trashed: false,
+        archived: false,
+      }
+
+      setLoadedProjects(loadedProjects => {
+        return sortProjects([...loadedProjects, clonedProject], sort)
       })
-      setLoadedProjects(projects)
     },
-    [loadedProjects]
+    [sort]
   )
 
+  const updateProjectViewData = useCallback((newProjectData: Project) => {
+    setLoadedProjects(loadedProjects => {
+      return loadedProjects.map((p: Project) =>
+        p.id === newProjectData.id ? { ...newProjectData } : p
+      )
+    })
+  }, [])
+
   const removeProjectFromView = useCallback(
     (project: Project) => {
       const projects = loadedProjects.filter(