From 6053a1373e873b59c6f53bcb432d82075ec4a48c Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Wed, 16 Oct 2024 10:53:43 -0500 Subject: [PATCH 01/12] task/WG-237-Delete-Project-Modal-React --- react/src/__fixtures__/projectFixtures.ts | 100 ++++++++++++++++++ .../DeleteMapModal/DeleteMapModal.module.css | 6 ++ .../DeleteMapModal/DeleteMapModal.test.tsx | 84 +++++++++++++++ .../DeleteMapModal/DeleteMapModal.tsx | 82 ++++++++++++++ .../components/Projects/ProjectListing.tsx | 25 ++++- react/src/hooks/projects/index.ts | 1 + react/src/hooks/projects/useProjects.ts | 18 +++- react/src/requests.ts | 33 ++++++ react/src/types/projects.ts | 2 - 9 files changed, 343 insertions(+), 8 deletions(-) create mode 100644 react/src/__fixtures__/projectFixtures.ts create mode 100644 react/src/components/DeleteMapModal/DeleteMapModal.module.css create mode 100644 react/src/components/DeleteMapModal/DeleteMapModal.test.tsx create mode 100644 react/src/components/DeleteMapModal/DeleteMapModal.tsx diff --git a/react/src/__fixtures__/projectFixtures.ts b/react/src/__fixtures__/projectFixtures.ts new file mode 100644 index 00000000..e7f93b8a --- /dev/null +++ b/react/src/__fixtures__/projectFixtures.ts @@ -0,0 +1,100 @@ +import { + Project, + DesignSafeProject, + DesignSafeProjectCollection, + ProjectRequest, +} from '../types'; + +export const projectMock: Project = { + id: 1, + uuid: 'abc123', + name: 'Sample Project', + description: 'A sample project for testing purposes.', + public: true, + system_file: 'sample-file', + system_id: 'sample-id', + system_path: '/path/to/sample', + deletable: true, + streetview_instances: null, + ds_project: { + uuid: 'proj-uuid', + projectId: 'proj-id', + title: 'Sample DesignSafe Project', + value: { + dois: [], + coPis: [], + title: 'Hazmapper V3 PROD Map Test 2024.08.07', + users: [ + { + inst: 'University of Texas at Austin (utexas.edu)', + role: 'pi', + email: 'jgentle@tacc.utexas.edu', + fname: 'John', + lname: 'Gentle', + username: 'jgentle', + }, + { + inst: 'University of Texas at Austin (utexas.edu)', + role: 'co_pi', + email: 'sophia.massie@tacc.utexas.edu', + fname: 'Sophia', + lname: 'Massie-Perez', + username: 'smassie', + }, + ], + authors: [], + frTypes: [], + nhEvent: '', + nhTypes: [], + fileObjs: [], + fileTags: [], + keywords: [], + nhEvents: [], + dataTypes: [], + projectId: 'PRJ-5566', + tombstone: false, + facilities: [], + nhLatitude: '', + nhLocation: '', + description: + 'Hazmapper V3 PROD Map Test 2024.08.07 description required.', + nhLongitude: '', + projectType: 'None', + teamMembers: [], + awardNumbers: [], + guestMembers: [], + hazmapperMaps: [ + { + name: 'v3_PROD_Hazmapper_2024-08-07_TestProject', + path: '/', + uuid: '620aeaf4-f813-4b90-ba52-bc87cfa7b07b', + deployment: 'production', + }, + ], + referencedData: [], + associatedProjects: [], + }, + }, +}; + +export const designSafeProjectMock: DesignSafeProject = { + uuid: 'proj-uuid', + projectId: 'proj-id', + title: 'Sample DesignSafe Project', + value: {}, +}; + +export const designSafeProjectCollectionMock: DesignSafeProjectCollection = { + result: [designSafeProjectMock], +}; + +export const projectRequestMock: ProjectRequest = { + name: 'New Project Request', + description: 'A description for the new project request.', + public: true, + system_file: 'new-project-file', + system_id: 'new-system-id', + system_path: '/path/to/new-project', + watch_content: true, + watch_users: false, +}; diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.module.css b/react/src/components/DeleteMapModal/DeleteMapModal.module.css new file mode 100644 index 00000000..0101768c --- /dev/null +++ b/react/src/components/DeleteMapModal/DeleteMapModal.module.css @@ -0,0 +1,6 @@ +.root { + display: flex; + flex-direction: column; + width: 100%; + height: 200px; +} diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx new file mode 100644 index 00000000..029c28ac --- /dev/null +++ b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import { + render, + cleanup, + fireEvent, + screen, + waitFor, +} from '@testing-library/react'; +import { BrowserRouter as Router } from 'react-router-dom'; +import { act } from 'react-dom/test-utils'; +import { QueryClient, QueryClientProvider } from 'react-query'; +import DeleteMapModal from './DeleteMapModal'; +import { Provider } from 'react-redux'; +import store from '../../redux/store'; +import { projectMock } from '../../__fixtures__/projectFixtures'; + +jest.mock('../../hooks/projects/useProjects', () => ({ + __esModule: true, + useDeleteProject: (projectId) => ({ + mutate: jest.fn((data, { onSuccess, onError }) => { + if (projectId === 404) { + onError({ response: { status: 404 } }); + } else { + onSuccess(); + } + }), + isLoading: false, + }), +})); +const mockNavigate = jest.fn(); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: () => mockNavigate, +})); + +const toggleMock = jest.fn(); +const queryClient = new QueryClient(); + +const renderComponent = async ( + projectId = 123, + projectName = 'Sample Project' +) => { + await act(async () => { + render( + + + + + + + + ); + }); +}; + +describe('DeleteMapModal', () => { + afterEach(() => { + cleanup(); + }); + + test('renders the modal when open', async () => { + await renderComponent(); + await waitFor(() => { + expect(screen.getByText('Delete Map: Sample Project')).toBeTruthy(); + }); + }); + + test('successfully deletes a project', async () => { + await renderComponent(123, 'Test Project'); + + await act(async () => { + fireEvent.click(screen.getByRole('button', { name: /Delete/ })); + }); + + await waitFor(() => { + expect(toggleMock).toHaveBeenCalled(); + }); + }); +}); diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.tsx new file mode 100644 index 00000000..5d961a52 --- /dev/null +++ b/react/src/components/DeleteMapModal/DeleteMapModal.tsx @@ -0,0 +1,82 @@ +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import { Button, SectionMessage } from '../../core-components'; +import styles from './DeleteMapModal.module.css'; +import useAuthenticatedUser from '../../hooks/user/useAuthenticatedUser'; +import { Project } from '../../types'; +import { useDeleteProject } from '../../hooks/projects/'; + +type DeleteMapModalProps = { + isOpen: boolean; + toggle: () => void; + projectId?: number; + project?: Project; +}; + +const DeleteMapModal = ({ + isOpen, + toggle: parentToggle, + projectId, + project, +}: DeleteMapModalProps) => { + const [errorMessage, setErrorMessage] = useState(''); + const { + mutate: deleteProject, + isLoading: isDeletingProject, + isError: isErrorDeleting, + } = useDeleteProject(projectId); + const handleClose = () => { + setErrorMessage(''); // Clear the error message + parentToggle(); // Call the original toggle function passed as a prop + }; + + const handleDeleteProject = () => { + deleteProject(undefined, { + onSuccess: () => { + handleClose(); + }, + onError: () => { + setErrorMessage('There was an error deleting your project.'); + }, + }); + }; + + return ( + + + Delete Map: {project?.name}{' '} + + + {project?.deletable + ? 'Are you sure you want to delete this map? All associated features, metadata, and saved files will be deleted. THIS CANNOT BE UNDONE.' + : "This map is not able to be deleted either because the map is public or because you don't have permission."} + + + + {project?.deletable ? ( + + ) : ( + + )} + {errorMessage && ( + {errorMessage} + )} + + + ); +}; + +export default DeleteMapModal; diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 7da6ecf5..f36952c1 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -2,10 +2,14 @@ import React, { useState } from 'react'; import { useProjectsWithDesignSafeInformation } from '../../hooks'; import { Button, LoadingSpinner, Icon } from '../../core-components'; import CreateMapModal from '../CreateMapModal/CreateMapModal'; +import DeleteMapModal from '../DeleteMapModal/DeleteMapModal'; +import { Project } from '../../types'; import { useNavigate } from 'react-router-dom'; export const ProjectListing: React.FC = () => { const [isModalOpen, setIsModalOpen] = useState(false); + const [selectedProjectForDeletion, setSelectedProjectForDeletion] = + useState(null); const navigate = useNavigate(); const navigateToProject = (projectId) => { @@ -16,6 +20,10 @@ export const ProjectListing: React.FC = () => { setIsModalOpen(!isModalOpen); }; + const toggleDeleteModal = (project: Project | null) => { + setSelectedProjectForDeletion(project); + }; + const { data, isLoading, isError } = useProjectsWithDesignSafeInformation(); if (isLoading) { @@ -43,9 +51,9 @@ export const ProjectListing: React.FC = () => { {data?.map((proj) => ( - navigateToProject(proj.uuid)}> - {proj.name} - + + navigateToProject(proj.uuid)}>{proj.name} + navigateToProject(proj.uuid)}> {proj.ds_project?.value.projectId}{' '} {proj.ds_project?.value.title} @@ -53,7 +61,7 @@ export const ProjectListing: React.FC = () => { - @@ -61,6 +69,15 @@ export const ProjectListing: React.FC = () => { ))} + + {selectedProjectForDeletion && ( + toggleDeleteModal(null)} + projectId={selectedProjectForDeletion.id} + project={selectedProjectForDeletion} + /> + )} ); }; diff --git a/react/src/hooks/projects/index.ts b/react/src/hooks/projects/index.ts index 8c421c54..5b11a39b 100644 --- a/react/src/hooks/projects/index.ts +++ b/react/src/hooks/projects/index.ts @@ -1,4 +1,5 @@ export { + useDeleteProject, useProjectsWithDesignSafeInformation, useProjects, useDsProjects, diff --git a/react/src/hooks/projects/useProjects.ts b/react/src/hooks/projects/useProjects.ts index 41e531d6..733326da 100644 --- a/react/src/hooks/projects/useProjects.ts +++ b/react/src/hooks/projects/useProjects.ts @@ -1,7 +1,7 @@ -import { UseQueryResult } from 'react-query'; +import { UseQueryResult, useQueryClient } from 'react-query'; import { useMemo } from 'react'; import { Project, DesignSafeProjectCollection, ApiService } from '../../types'; -import { useGet } from '../../requests'; +import { useGet, useDelete } from '../../requests'; export const useProjects = (): UseQueryResult => { const query = useGet({ @@ -75,3 +75,17 @@ export function useProjectsWithDesignSafeInformation(): UseQueryResult< error: dsProjectQuery.error || projectQuery.error, } as UseQueryResult; } + +export const useDeleteProject = (projectId: number | undefined) => { + const queryClient = useQueryClient(); + const endpoint = `/projects/${projectId}/`; + return useDelete({ + endpoint, + apiService: ApiService.Geoapi, + options: { + onSuccess: () => { + queryClient.invalidateQueries('projects'); + }, + }, + }); +}; diff --git a/react/src/requests.ts b/react/src/requests.ts index 7e1b9be7..a48c7ccd 100644 --- a/react/src/requests.ts +++ b/react/src/requests.ts @@ -157,3 +157,36 @@ export function usePost({ return useMutation(postUtil, options); } + +type UseDeleteParams = { + endpoint: string; + options?: UseMutationOptions; + apiService?: ApiService; +}; + +export function useDelete({ + endpoint, + options = {}, + apiService = ApiService.Geoapi, +}: UseDeleteParams) { + const client = axios; + const state = store.getState(); + const configuration = useAppConfiguration(); + + useEnsureAuthenticatedUserHasValidTapisToken(); + + const baseUrl = getBaseApiUrl(apiService, configuration); + const headers = getHeaders(apiService, state.auth); + + const deleteUtil = async () => { + const response = await client.delete( + `${baseUrl}${endpoint}`, + { + headers: headers, + } + ); + return response.data; + }; + + return useMutation(deleteUtil, options); +} diff --git a/react/src/types/projects.ts b/react/src/types/projects.ts index 284846e9..bb18e41b 100644 --- a/react/src/types/projects.ts +++ b/react/src/types/projects.ts @@ -10,8 +10,6 @@ export interface Project { deletable?: boolean; streetview_instances?: any; ds_project?: DesignSafeProject; - ds_project_id?: any; - ds_project_title?: any; } export interface DesignSafeProject { uuid: string; From dc5591759d0118ad5efb946116d71047965ab494 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Wed, 16 Oct 2024 11:07:58 -0500 Subject: [PATCH 02/12] - Linting --- .../components/DeleteMapModal/DeleteMapModal.test.tsx | 5 +---- .../src/components/DeleteMapModal/DeleteMapModal.tsx | 11 +++-------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx index 029c28ac..7e1f6e71 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx @@ -36,10 +36,7 @@ jest.mock('react-router-dom', () => ({ const toggleMock = jest.fn(); const queryClient = new QueryClient(); -const renderComponent = async ( - projectId = 123, - projectName = 'Sample Project' -) => { +const renderComponent = async () => { await act(async () => { render( diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.tsx index 5d961a52..3e45dafc 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.tsx @@ -1,9 +1,7 @@ import React, { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; import { Button, SectionMessage } from '../../core-components'; import styles from './DeleteMapModal.module.css'; -import useAuthenticatedUser from '../../hooks/user/useAuthenticatedUser'; import { Project } from '../../types'; import { useDeleteProject } from '../../hooks/projects/'; @@ -21,11 +19,8 @@ const DeleteMapModal = ({ project, }: DeleteMapModalProps) => { const [errorMessage, setErrorMessage] = useState(''); - const { - mutate: deleteProject, - isLoading: isDeletingProject, - isError: isErrorDeleting, - } = useDeleteProject(projectId); + const { mutate: deleteProject, isLoading: isDeletingProject } = + useDeleteProject(projectId); const handleClose = () => { setErrorMessage(''); // Clear the error message parentToggle(); // Call the original toggle function passed as a prop @@ -43,7 +38,7 @@ const DeleteMapModal = ({ }; return ( - + Delete Map: {project?.name}{' '} From e6f85e4185011c46d0b1314989793fc5fcb62e65 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Wed, 16 Oct 2024 11:11:32 -0500 Subject: [PATCH 03/12] - Fix frontend tests --- react/src/components/DeleteMapModal/DeleteMapModal.test.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx index 7e1f6e71..029c28ac 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx @@ -36,7 +36,10 @@ jest.mock('react-router-dom', () => ({ const toggleMock = jest.fn(); const queryClient = new QueryClient(); -const renderComponent = async () => { +const renderComponent = async ( + projectId = 123, + projectName = 'Sample Project' +) => { await act(async () => { render( From f6774c07ec48bcd0c123b7dadcda2ca32a902748 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Wed, 16 Oct 2024 11:14:15 -0500 Subject: [PATCH 04/12] - Fixing unit tests --- react/src/components/DeleteMapModal/DeleteMapModal.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx index 029c28ac..6f48294c 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx @@ -71,7 +71,7 @@ describe('DeleteMapModal', () => { }); test('successfully deletes a project', async () => { - await renderComponent(123, 'Test Project'); + await renderComponent(123, 'Sample Project'); await act(async () => { fireEvent.click(screen.getByRole('button', { name: /Delete/ })); From c812876811ec5c57e6efe605b4562b0bb4d8d80d Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Tue, 29 Oct 2024 16:54:51 -0500 Subject: [PATCH 05/12] - Addresses commented suggestions and requested changes --- react/src/__fixtures__/projectFixtures.ts | 21 ++++--- .../DeleteMapModal/DeleteMapModal.module.css | 6 -- .../DeleteMapModal/DeleteMapModal.tsx | 59 +++++++++++-------- .../components/Projects/ProjectListing.tsx | 17 ++---- react/src/hooks/projects/useProjects.ts | 2 +- react/src/types/projects.ts | 10 ++-- 6 files changed, 58 insertions(+), 57 deletions(-) diff --git a/react/src/__fixtures__/projectFixtures.ts b/react/src/__fixtures__/projectFixtures.ts index e7f93b8a..4715b087 100644 --- a/react/src/__fixtures__/projectFixtures.ts +++ b/react/src/__fixtures__/projectFixtures.ts @@ -28,18 +28,18 @@ export const projectMock: Project = { { inst: 'University of Texas at Austin (utexas.edu)', role: 'pi', - email: 'jgentle@tacc.utexas.edu', - fname: 'John', - lname: 'Gentle', - username: 'jgentle', + email: 'test1@test.com', + fname: 'Fixture First Name', + lname: 'Fixture Last Name', + username: 'fixture1Username', }, { inst: 'University of Texas at Austin (utexas.edu)', role: 'co_pi', - email: 'sophia.massie@tacc.utexas.edu', - fname: 'Sophia', - lname: 'Massie-Perez', - username: 'smassie', + email: 'test2@test.com', + fname: 'Tester', + lname: 'Test', + username: 'fixture2Username', }, ], authors: [], @@ -56,8 +56,7 @@ export const projectMock: Project = { facilities: [], nhLatitude: '', nhLocation: '', - description: - 'Hazmapper V3 PROD Map Test 2024.08.07 description required.', + description: 'Map Test description required.', nhLongitude: '', projectType: 'None', teamMembers: [], @@ -65,7 +64,7 @@ export const projectMock: Project = { guestMembers: [], hazmapperMaps: [ { - name: 'v3_PROD_Hazmapper_2024-08-07_TestProject', + name: 'Hazmapper_TestProject', path: '/', uuid: '620aeaf4-f813-4b90-ba52-bc87cfa7b07b', deployment: 'production', diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.module.css b/react/src/components/DeleteMapModal/DeleteMapModal.module.css index 0101768c..e69de29b 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.module.css +++ b/react/src/components/DeleteMapModal/DeleteMapModal.module.css @@ -1,6 +0,0 @@ -.root { - display: flex; - flex-direction: column; - width: 100%; - height: 200px; -} diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.tsx index 3e45dafc..d5ed131c 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.tsx @@ -7,49 +7,54 @@ import { useDeleteProject } from '../../hooks/projects/'; type DeleteMapModalProps = { isOpen: boolean; - toggle: () => void; - projectId?: number; + close: () => void; + projectId: number; project?: Project; }; const DeleteMapModal = ({ isOpen, - toggle: parentToggle, + close: parentToggle, projectId, project, }: DeleteMapModalProps) => { - const [errorMessage, setErrorMessage] = useState(''); - const { mutate: deleteProject, isLoading: isDeletingProject } = - useDeleteProject(projectId); + const { + mutate: deleteProject, + isLoading: isDeletingProject, + isError, + isSuccess, + } = useDeleteProject(projectId); const handleClose = () => { - setErrorMessage(''); // Clear the error message - parentToggle(); // Call the original toggle function passed as a prop + parentToggle(); }; const handleDeleteProject = () => { - deleteProject(undefined, { - onSuccess: () => { - handleClose(); - }, - onError: () => { - setErrorMessage('There was an error deleting your project.'); - }, - }); + deleteProject(undefined, {}); }; return ( - + Delete Map: {project?.name}{' '} - {project?.deletable - ? 'Are you sure you want to delete this map? All associated features, metadata, and saved files will be deleted. THIS CANNOT BE UNDONE.' - : "This map is not able to be deleted either because the map is public or because you don't have permission."} + {project?.deletable ? ( + <> + Are you sure you want to delete this map? All associated features, + metadata, and saved files will be deleted. + {project?.public && Note that this is a public map. } +
+ + This cannot be undone. + + + ) : ( + "This map cannot be deleted because you don't have correct permission credentials." + )}
{project?.deletable ? ( @@ -66,8 +72,15 @@ const DeleteMapModal = ({ Delete )} - {errorMessage && ( - {errorMessage} + {isSuccess && ( + + {'Succesfully deleted the map.'} + + )} + {isError && ( + + {'There was an error deleting your map.'} + )}
diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index f36952c1..27836c29 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -20,10 +20,6 @@ export const ProjectListing: React.FC = () => { setIsModalOpen(!isModalOpen); }; - const toggleDeleteModal = (project: Project | null) => { - setSelectedProjectForDeletion(project); - }; - const { data, isLoading, isError } = useProjectsWithDesignSafeInformation(); if (isLoading) { @@ -58,12 +54,11 @@ export const ProjectListing: React.FC = () => { {proj.ds_project?.value.title} - - + + ))} @@ -73,7 +68,7 @@ export const ProjectListing: React.FC = () => { {selectedProjectForDeletion && ( toggleDeleteModal(null)} + toggle={() => setSelectedProjectForDeletion(null)} projectId={selectedProjectForDeletion.id} project={selectedProjectForDeletion} /> diff --git a/react/src/hooks/projects/useProjects.ts b/react/src/hooks/projects/useProjects.ts index 733326da..d0b8ffd3 100644 --- a/react/src/hooks/projects/useProjects.ts +++ b/react/src/hooks/projects/useProjects.ts @@ -76,7 +76,7 @@ export function useProjectsWithDesignSafeInformation(): UseQueryResult< } as UseQueryResult; } -export const useDeleteProject = (projectId: number | undefined) => { +export const useDeleteProject = (projectId: number) => { const queryClient = useQueryClient(); const endpoint = `/projects/${projectId}/`; return useDelete({ diff --git a/react/src/types/projects.ts b/react/src/types/projects.ts index bb18e41b..88e596c5 100644 --- a/react/src/types/projects.ts +++ b/react/src/types/projects.ts @@ -3,11 +3,11 @@ export interface Project { uuid?: string; name: string; description: string; - public?: boolean; - system_file?: string; - system_id?: string; - system_path?: string; - deletable?: boolean; + public: boolean; + system_file: string; + system_id: string; + system_path: string; + deletable: boolean; streetview_instances?: any; ds_project?: DesignSafeProject; } From ec62b600baae722ab4e805f7fcc96d22e1f5bd67 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Tue, 29 Oct 2024 16:58:58 -0500 Subject: [PATCH 06/12] - Updated more requested changes --- react/src/components/DeleteMapModal/DeleteMapModal.tsx | 6 ++---- react/src/components/Projects/ProjectListing.tsx | 3 +-- react/src/types/projects.ts | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.tsx index d5ed131c..e99cf6c9 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.tsx @@ -8,14 +8,12 @@ import { useDeleteProject } from '../../hooks/projects/'; type DeleteMapModalProps = { isOpen: boolean; close: () => void; - projectId: number; - project?: Project; + project: Project; }; const DeleteMapModal = ({ isOpen, close: parentToggle, - projectId, project, }: DeleteMapModalProps) => { const { @@ -23,7 +21,7 @@ const DeleteMapModal = ({ isLoading: isDeletingProject, isError, isSuccess, - } = useDeleteProject(projectId); + } = useDeleteProject(project.id); const handleClose = () => { parentToggle(); }; diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 27836c29..7fa9a8d1 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -68,8 +68,7 @@ export const ProjectListing: React.FC = () => { {selectedProjectForDeletion && ( setSelectedProjectForDeletion(null)} - projectId={selectedProjectForDeletion.id} + close={() => setSelectedProjectForDeletion(null)} project={selectedProjectForDeletion} /> )} diff --git a/react/src/types/projects.ts b/react/src/types/projects.ts index 88e596c5..2c681d2f 100644 --- a/react/src/types/projects.ts +++ b/react/src/types/projects.ts @@ -1,5 +1,5 @@ export interface Project { - id?: number; + id: number; uuid?: string; name: string; description: string; From daf0dd367beaf96e4b872b7bf3180c88f399ecbb Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Tue, 29 Oct 2024 17:24:44 -0500 Subject: [PATCH 07/12] - More updates and linting --- .../components/DeleteMapModal/DeleteMapModal.module.css | 0 .../src/components/DeleteMapModal/DeleteMapModal.test.tsx | 8 ++------ react/src/components/DeleteMapModal/DeleteMapModal.tsx | 4 ++-- react/src/components/Projects/ProjectListing.tsx | 2 +- 4 files changed, 5 insertions(+), 9 deletions(-) delete mode 100644 react/src/components/DeleteMapModal/DeleteMapModal.module.css diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.module.css b/react/src/components/DeleteMapModal/DeleteMapModal.module.css deleted file mode 100644 index e69de29b..00000000 diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx index 6f48294c..3c81f31e 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx @@ -36,10 +36,7 @@ jest.mock('react-router-dom', () => ({ const toggleMock = jest.fn(); const queryClient = new QueryClient(); -const renderComponent = async ( - projectId = 123, - projectName = 'Sample Project' -) => { +const renderComponent = async () => { await act(async () => { render( @@ -47,8 +44,7 @@ const renderComponent = async ( diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.tsx index e99cf6c9..99a57868 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.tsx @@ -1,6 +1,6 @@ -import React, { useState } from 'react'; +import React from 'react'; import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; -import { Button, SectionMessage } from '../../core-components'; +import { Button, SectionMessage } from '@tacc/core-components'; import styles from './DeleteMapModal.module.css'; import { Project } from '../../types'; import { useDeleteProject } from '../../hooks/projects/'; diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 922297d1..1d74feac 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useProjectsWithDesignSafeInformation } from '@hazmapper/hooks'; -import { Button, LoadingSpinner, Icon } from '@tacc/core-components'; +import { Button, LoadingSpinner } from '@tacc/core-components'; import CreateMapModal from '../CreateMapModal/CreateMapModal'; import DeleteMapModal from '../DeleteMapModal/DeleteMapModal'; import { Project } from '../../types'; From 89b664da9c3bad098cb6928ea23a9db65f0052e3 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Tue, 29 Oct 2024 17:31:08 -0500 Subject: [PATCH 08/12] - Added key to table rows with onClick --- react/src/components/DeleteMapModal/DeleteMapModal.tsx | 1 - react/src/components/Projects/ProjectListing.tsx | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.tsx index 99a57868..1e4c1f44 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; import { Button, SectionMessage } from '@tacc/core-components'; -import styles from './DeleteMapModal.module.css'; import { Project } from '../../types'; import { useDeleteProject } from '../../hooks/projects/'; diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 1d74feac..2bd42033 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -48,8 +48,8 @@ export const ProjectListing: React.FC = () => { {data?.map((proj) => ( - navigateToProject(proj.uuid)}>{proj.name} - navigateToProject(proj.uuid)}> + navigateToProject(proj.uuid)}>{proj.name} + navigateToProject(proj.uuid)}> {proj.ds_project?.value.projectId}{' '} {proj.ds_project?.value.title} From c3e7d145e9bbfe34beaa462f4d89e461b40c508f Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Tue, 29 Oct 2024 17:32:18 -0500 Subject: [PATCH 09/12] - Linting --- react/src/components/DeleteMapModal/DeleteMapModal.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx index 3c81f31e..f0eccdee 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.test.tsx @@ -67,7 +67,7 @@ describe('DeleteMapModal', () => { }); test('successfully deletes a project', async () => { - await renderComponent(123, 'Sample Project'); + await renderComponent(); await act(async () => { fireEvent.click(screen.getByRole('button', { name: /Delete/ })); From c3b999e6201fbdbc7fb541c1a0e01284a97a79b5 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Tue, 29 Oct 2024 17:45:27 -0500 Subject: [PATCH 10/12] - Addresses accesibility erros with table row links --- .../components/Projects/ProjectListing.tsx | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 2bd42033..d6b8ea20 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -48,10 +48,26 @@ export const ProjectListing: React.FC = () => { {data?.map((proj) => ( - navigateToProject(proj.uuid)}>{proj.name} - navigateToProject(proj.uuid)}> - {proj.ds_project?.value.projectId}{' '} - {proj.ds_project?.value.title} + + {' '} + + + + {' '} + From 5c5e0b41cb71b82a202576200cc76d3833252bc9 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Wed, 30 Oct 2024 11:45:50 -0500 Subject: [PATCH 11/12] - Updated changes --- .../DeleteMapModal/DeleteMapModal.tsx | 28 ++++++++----------- .../components/Projects/ProjectListing.tsx | 4 +-- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/react/src/components/DeleteMapModal/DeleteMapModal.tsx b/react/src/components/DeleteMapModal/DeleteMapModal.tsx index 1e4c1f44..ee814844 100644 --- a/react/src/components/DeleteMapModal/DeleteMapModal.tsx +++ b/react/src/components/DeleteMapModal/DeleteMapModal.tsx @@ -46,29 +46,23 @@ const DeleteMapModal = ({ ) : ( - "This map cannot be deleted because you don't have correct permission credentials." + 'You don’t have permission to delete this map.' )} - {project?.deletable ? ( - - ) : ( - - )} + {isSuccess && ( {'Succesfully deleted the map.'} diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index d6b8ea20..c8edc0ec 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -48,7 +48,7 @@ export const ProjectListing: React.FC = () => { {data?.map((proj) => ( - + {' '} - + {' '}