diff --git a/services/web/app/src/Features/Project/ProjectDeleter.mjs b/services/web/app/src/Features/Project/ProjectDeleter.mjs index 02d667559a..830786486d 100644 --- a/services/web/app/src/Features/Project/ProjectDeleter.mjs +++ b/services/web/app/src/Features/Project/ProjectDeleter.mjs @@ -279,6 +279,7 @@ async function deleteProject(projectId, options = {}) { { projectId, userId: project.owner_ref }, 'successfully deleted project' ) + return { deletedAt: deleterData.deletedAt, deleterId: deleterData.deleterId } } catch (err) { logger.warn({ err }, 'problem deleting project') throw err diff --git a/services/web/modules/admin-tools/app/src/AdminToolsRouter.mjs b/services/web/modules/admin-tools/app/src/AdminToolsRouter.mjs index 39e6605a17..7a82587191 100644 --- a/services/web/modules/admin-tools/app/src/AdminToolsRouter.mjs +++ b/services/web/modules/admin-tools/app/src/AdminToolsRouter.mjs @@ -69,6 +69,10 @@ export default { AuthorizationMiddleware.ensureUserIsSiteAdmin, ProjectListController.purgeDeletedProject ) + webRouter.delete('/admin/project/:project_id', + AuthorizationMiddleware.ensureUserIsSiteAdmin, + ProjectListController.deleteProject + ) webRouter.post('/admin/project/:project_id/undelete', AuthorizationMiddleware.ensureUserIsSiteAdmin, ProjectListController.undeleteProject diff --git a/services/web/modules/admin-tools/app/src/ProjectListController.mjs b/services/web/modules/admin-tools/app/src/ProjectListController.mjs index 3d84457dd2..215fc53347 100644 --- a/services/web/modules/admin-tools/app/src/ProjectListController.mjs +++ b/services/web/modules/admin-tools/app/src/ProjectListController.mjs @@ -117,7 +117,7 @@ function _sortAndPaginate(projects, sort, page) { throw new OError('Invalid sorting criteria', { sort }) } -// sorting by owner is not implemented, it is mot needed +// sorting by owner is not implemented, it is not needed const sortedProjects = sort.by === 'title' ? [...projects].sort((a, b) => @@ -162,7 +162,7 @@ function _formatDeletedProjectInfo(deletedProject, maxDate) { trashed, deleted: true, deletedAt: deletedProject.deleterData?.deletedAt?.toISOString(), - deletedBy: deletedProject.deleterData?.deleterId, + deleterId: deletedProject.deleterData?.deleterId, } } @@ -212,6 +212,14 @@ async function untrashProjectForUser(req, res) { res.sendStatus(200) } +async function deleteProject(req, res) { + const projectId = req.params.project_id + const deleterId = SessionManager.getLoggedInUserId(req.session) + const options = { deleterUser: {_id: deleterId } } + const deletedProjectData = await ProjectDeleter.promises.deleteProject(projectId, options) + return res.json(deletedProjectData) +} + async function undeleteProject(req, res) { const projectId = req.params.project_id const { userId } = req.body @@ -232,6 +240,7 @@ async function purgeDeletedProject(req, res) { export default { manageProjectsPage: expressify(manageProjectsPage), getProjectsJson: expressify(getProjectsJson), + deleteProject: expressify(deleteProject), undeleteProject: expressify(undeleteProject), purgeDeletedProject: expressify(purgeDeletedProject), trashProjectForUser: expressify(trashProjectForUser), diff --git a/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/delete-project-button.tsx b/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/delete-project-button.tsx index 1514d97967..020d18e20c 100644 --- a/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/delete-project-button.tsx +++ b/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/delete-project-button.tsx @@ -34,11 +34,13 @@ function DeleteProjectButton({ project, children }: DeleteProjectButtonProps) { }, [isMounted]) const handleDeleteProject = useCallback(async () => { - await deleteProject(project.id) - toggleSelectedProject(project.id, false) - updateProjectViewData({ - ...project, - deleted: true, + return deleteProject(project.id).then(data => { + toggleSelectedProject(project.id, false) + updateProjectViewData({ + ...project, + ...data, + deleted: true, + }) }) }, [project, toggleSelectedProject, updateProjectViewData]) diff --git a/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/restore-project-button.tsx b/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/restore-project-button.tsx index 0aaedcbf23..56e531656e 100644 --- a/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/restore-project-button.tsx +++ b/services/web/modules/admin-tools/frontend/js/project-list/components/table/cells/action-buttons/restore-project-button.tsx @@ -35,7 +35,6 @@ function RestoreProjectButton({ }, [isMounted]) const handleRestoreProject = useCallback(() => { -// const ownerId = project.owner ?? getMeta('ol-user_id') return undeleteProject(project.id, project.owner).then(data => { toggleSelectedProject(project.id, false) updateProjectViewData({ diff --git a/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-list-table-row.tsx b/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-list-table-row.tsx index f5a6d5ec00..91ee9db272 100644 --- a/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-list-table-row.tsx +++ b/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-list-table-row.tsx @@ -19,7 +19,7 @@ function ProjectListTableRow({ project, selected, filter }: ProjectListTableRowP const ownerName = getUserNameById(project.owner) const actorName = filter !== 'deleted' ? getUserNameById(project.lastUpdatedBy) : - getUserNameById(project.deletedBy) + getUserNameById(project.deleterId) const eventDate = filter !== 'deleted' ? project.lastUpdated : project.deletedAt return ( diff --git a/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-tools/buttons/delete-projects-button.tsx b/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-tools/buttons/delete-projects-button.tsx index f8e3737fb0..dd8dce6c2f 100644 --- a/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-tools/buttons/delete-projects-button.tsx +++ b/services/web/modules/admin-tools/frontend/js/project-list/components/table/project-tools/buttons/delete-projects-button.tsx @@ -28,11 +28,13 @@ function DeleteProjectsButton() { } const handleDeleteProject = async (project: Project) => { - await deleteProject(project.id) - toggleSelectedProject(project.id, false) - updateProjectViewData({ - ...project, - deleted: true, + return deleteProject(project.id).then(data => { + toggleSelectedProject(project.id, false) + updateProjectViewData({ + ...project, + ...data, + deleted: true, + }) }) } diff --git a/services/web/modules/admin-tools/frontend/js/project-list/context/project-list-context.tsx b/services/web/modules/admin-tools/frontend/js/project-list/context/project-list-context.tsx index 6b99c42beb..9bb02257e9 100644 --- a/services/web/modules/admin-tools/frontend/js/project-list/context/project-list-context.tsx +++ b/services/web/modules/admin-tools/frontend/js/project-list/context/project-list-context.tsx @@ -184,7 +184,7 @@ export function ProjectListProvider({ projectsOwnerId, children }: ProjectListPr const loadMoreProjects = useCallback(() => { setMaxVisibleProjects(v => v + loadMoreCount) - }, [maxVisibleProjects]) + }, [loadMoreCount]) const [selectedProjectIds, setSelectedProjectIds] = useState( () => new Set() @@ -213,9 +213,8 @@ export function ProjectListProvider({ projectsOwnerId, children }: ProjectListPr return visibleProjects.filter(project => selectedProjectIds.has(project.id)) }, [selectedProjectIds, visibleProjects]) - const selectOrUnselectAllProjects = useCallback( - (checked: any) => { + (checked: boolean) => { setSelectedProjectIds(prevSelectedProjectIds => { const selectedProjectIds = new Set(prevSelectedProjectIds) for (const project of visibleProjects) { diff --git a/services/web/modules/admin-tools/frontend/js/project-list/util/api.ts b/services/web/modules/admin-tools/frontend/js/project-list/util/api.ts index 3d862a4933..0ae064554c 100644 --- a/services/web/modules/admin-tools/frontend/js/project-list/util/api.ts +++ b/services/web/modules/admin-tools/frontend/js/project-list/util/api.ts @@ -20,7 +20,7 @@ export function getProjects( } export function deleteProject(projectId: string) { - return deleteJSON(`/project/${projectId}`) + return deleteJSON(`/admin/project/${projectId}`) } export function purgeProject(projectId: string) { diff --git a/services/web/modules/admin-tools/frontend/js/project-list/util/sort-projects.ts b/services/web/modules/admin-tools/frontend/js/project-list/util/sort-projects.ts index b1ff081a8d..45d9fe5df3 100644 --- a/services/web/modules/admin-tools/frontend/js/project-list/util/sort-projects.ts +++ b/services/web/modules/admin-tools/frontend/js/project-list/util/sort-projects.ts @@ -10,7 +10,6 @@ const order = (order: SortingOrder, projects: Project[]) => { function cmp(a, b) { const aEmpty = a == null || a === "" const bEmpty = b == null || b === "" - if (aEmpty && bEmpty) return Compare.SORT_KEEP_ORDER if (aEmpty) return Compare.SORT_A_AFTER_B if (bEmpty) return Compare.SORT_A_BEFORE_B return a.localeCompare(b) @@ -57,7 +56,7 @@ export const defaultComparator = ( if (value1 !== value2) { if (value1 === undefined) return Compare.SORT_A_BEFORE_B if (value2 === undefined) return Compare.SORT_A_AFTER_B - return value1 < value2 ? Compare.SORT_A_BEFORE_B : Compare.SORT_A_AFTER_B + return value1.localeCompare(value2) } return Compare.SORT_KEEP_ORDER diff --git a/services/web/modules/admin-tools/types/project/api.d.ts b/services/web/modules/admin-tools/types/project/api.d.ts index a6102945b1..a9fd8df07f 100644 --- a/services/web/modules/admin-tools/types/project/api.d.ts +++ b/services/web/modules/admin-tools/types/project/api.d.ts @@ -40,7 +40,7 @@ export type ProjectApi = { trashed: boolean deleted: boolean inactive?: boolean - deletedBy?: string + deleterId?: string deletedAt?: Date }