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

[web] Fix dash view state updating

GitOrigin-RevId: e46acf5de76a19ddd66cab3581edc971125dfdee
This commit is contained in:
Jessica Lawshe 2022-09-26 12:39:52 -05:00 committed by Copybot
parent 1b822621a1
commit 341ee52c3f
10 changed files with 60 additions and 66 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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]
)

View file

@ -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'] }}
>

View file

@ -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'] }}
>

View file

@ -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])

View file

@ -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,39 +326,38 @@ 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)
const clonedProject = {
...project,
id: project.project_id,
owner,
lastUpdatedBy: owner,
source: 'owner',
trashed: false,
archived: false,
}
setLoadedProjects(loadedProjects => {
return sortProjects([...loadedProjects, clonedProject], sort)
})
},
[loadedProjects, visibleProjects, sort]
[sort]
)
const updateProjectViewData = useCallback(
(project: Project) => {
const projects = loadedProjects.map((p: Project) => {
if (p.id === project.id) {
p = project
}
return p
})
setLoadedProjects(projects)
},
[loadedProjects]
)
const updateProjectViewData = useCallback((newProjectData: Project) => {
setLoadedProjects(loadedProjects => {
return loadedProjects.map((p: Project) =>
p.id === newProjectData.id ? { ...newProjectData } : p
)
})
}, [])
const removeProjectFromView = useCallback(
(project: Project) => {