mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #9689 from overleaf/jel-dash-state
[web] Fix dash view state updating GitOrigin-RevId: e46acf5de76a19ddd66cab3581edc971125dfdee
This commit is contained in:
parent
1b822621a1
commit
341ee52c3f
10 changed files with 60 additions and 66 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
)
|
||||
|
|
|
@ -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'] }}
|
||||
>
|
||||
|
|
|
@ -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'] }}
|
||||
>
|
||||
|
|
|
@ -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])
|
||||
|
||||
|
|
|
@ -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
|
||||
const visibleProjectIds = visibleProjects.map(p => p.id)
|
||||
setLoadedProjects(loadedProjects =>
|
||||
loadedProjects.map(p => {
|
||||
if (visibleProjectIds.includes(p.id)) {
|
||||
return { ...p, selected: checked }
|
||||
} else {
|
||||
return p
|
||||
}
|
||||
})
|
||||
setVisibleProjects(projects)
|
||||
)
|
||||
},
|
||||
[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) => {
|
||||
|
|
Loading…
Reference in a new issue