From 82ac31a3c4a1964e9ebfd2ba64109ef251ece0cf Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Thu, 3 Oct 2024 15:47:59 -0500 Subject: [PATCH 1/6] task/WG-232-React-Listing-UI-clean --- react/package-lock.json | 9 +++ react/package.json | 1 + .../Projects/ProjectListing.module.css | 46 +++++++++++ .../components/Projects/ProjectListing.tsx | 80 ++++++++++--------- react/src/components/Projects/index.ts | 2 +- react/src/hazmapper.css | 20 ++++- react/src/index.css | 4 +- react/src/pages/MainMenu/MainMenu.tsx | 3 +- 8 files changed, 122 insertions(+), 43 deletions(-) create mode 100644 react/src/components/Projects/ProjectListing.module.css diff --git a/react/package-lock.json b/react/package-lock.json index 98be7366..d0ed23c0 100644 --- a/react/package-lock.json +++ b/react/package-lock.json @@ -12,6 +12,7 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.0", "@changey/react-leaflet-markercluster": "^4.0.0-rc1", + "@fortawesome/fontawesome-free": "^6.6.0", "@reduxjs/toolkit": "^1.8.4", "@tacc/core-styles": "^2.24.1", "@testing-library/react": "^13.4.0", @@ -2650,6 +2651,14 @@ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz", + "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==", + "engines": { + "node": ">=6" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", diff --git a/react/package.json b/react/package.json index 648f3f86..b36aa704 100644 --- a/react/package.json +++ b/react/package.json @@ -36,6 +36,7 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.0", "@changey/react-leaflet-markercluster": "^4.0.0-rc1", + "@fortawesome/fontawesome-free": "^6.6.0", "@reduxjs/toolkit": "^1.8.4", "@tacc/core-styles": "^2.24.1", "@testing-library/react": "^13.4.0", diff --git a/react/src/components/Projects/ProjectListing.module.css b/react/src/components/Projects/ProjectListing.module.css new file mode 100644 index 00000000..af7ce673 --- /dev/null +++ b/react/src/components/Projects/ProjectListing.module.css @@ -0,0 +1,46 @@ +.root{ + display: flex; + flex-direction: column; + width: 100%; +} +.projectList { + height: 270px; + border-collapse: collapse; + align-self: center; + overflow-y: scroll; + margin-top: 40px; + margin-bottom: 40px; +} +.projectHeader, .projectHeader th { + background: #d0d0d0; + position: sticky; + top: 0; + z-index: 1; +} + +.projectListItemButton{ + cursor: pointer; + color: initial; + margin-right: 10px; +} + +.projectListItemButton:hover{ + color: #666; +} + +.mapColumn { +width: 30%; +} +.projectColumn { +width: 60%; +} +.buttonColumn { + white-space: nowrap; +} + +.projectName { + max-width: fit-content; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 7da6ecf5..f0deb073 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -1,10 +1,11 @@ import React, { useState } from 'react'; import { useProjectsWithDesignSafeInformation } from '../../hooks'; import { Button, LoadingSpinner, Icon } from '../../core-components'; +import styles from './ProjectListing.module.css'; import CreateMapModal from '../CreateMapModal/CreateMapModal'; import { useNavigate } from 'react-router-dom'; -export const ProjectListing: React.FC = () => { +const ProjectListing: React.FC = () => { const [isModalOpen, setIsModalOpen] = useState(false); const navigate = useNavigate(); @@ -20,47 +21,54 @@ export const ProjectListing: React.FC = () => { if (isLoading) { return ; - } + }; if (isError) { return

Unable to retrieve projects

; - } + }; return ( - <> - - - - - - - - - - {data?.map((proj) => ( - navigateToProject(proj.uuid)}> - - - + {data?.map((proj) => ( + navigateToProject(proj.uuid)}> + + + + + ))} + +
MapProject - - -
{proj.name} - {proj.ds_project?.value.projectId}{' '} - {proj.ds_project?.value.title} - - -
{proj.name} + {proj.ds_project?.value.projectId}{' - '} + {proj.ds_project?.value.title} + + + +
+ + ); }; +export default ProjectListing; diff --git a/react/src/components/Projects/index.ts b/react/src/components/Projects/index.ts index d4d7f8d0..abef4bd4 100644 --- a/react/src/components/Projects/index.ts +++ b/react/src/components/Projects/index.ts @@ -1 +1 @@ -export { ProjectListing } from './ProjectListing'; +export { default } from './ProjectListing'; diff --git a/react/src/hazmapper.css b/react/src/hazmapper.css index 21078670..ef734134 100644 --- a/react/src/hazmapper.css +++ b/react/src/hazmapper.css @@ -1,5 +1,7 @@ -@import url('@tacc/core-styles/dist/core-styles.base.css'); -@import url('@tacc/core-styles/dist/core-styles.portal.css'); +@import "leaflet/dist/leaflet.css"; +@import "@fortawesome/fontawesome-free/css/all.css"; +@import url('https://fonts.googleapis.com/css?family=Raleway'); +@import url('https://unpkg.com/mapillary-js@2.18.0/dist/mapillary.min.css'); /* for hazmapper specific overwrites of base and portal styles" like, @@ -8,3 +10,17 @@ } */ + + +/* CSS module styles taken from Angular styles.styl */ +:root { + --global-font-family: 'Raleway', san-serif; +} +html, +body { + height: 100%; + font-family: var(--global-font-family); +} +table, form, button { + font-family: inherit; +} diff --git a/react/src/index.css b/react/src/index.css index 70e3ac95..27f096d5 100644 --- a/react/src/index.css +++ b/react/src/index.css @@ -3,7 +3,7 @@ /* prettier-ignore */ @import url('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') layer(foundation); -@import url('@tacc/core-styles/dist/core-styles.base.css'); /* layer(base);*/ -@import url('@tacc/core-styles/dist/core-styles.portal.css'); /* layer(base);*/ +@import url('@tacc/core-styles/dist/core-styles.base.css') layer(base); +@import url('@tacc/core-styles/dist/core-styles.portal.css') layer(base); @import url('./hazmapper.css') layer(project); diff --git a/react/src/pages/MainMenu/MainMenu.tsx b/react/src/pages/MainMenu/MainMenu.tsx index 246aaf18..788d7079 100644 --- a/react/src/pages/MainMenu/MainMenu.tsx +++ b/react/src/pages/MainMenu/MainMenu.tsx @@ -7,8 +7,7 @@ import { } from '../../core-components'; import useAuthenticatedUser from '../../hooks/user/useAuthenticatedUser'; import { SystemSelect } from '../../components/Systems'; -import { ProjectListing } from '../../components/Projects/ProjectListing'; - +import ProjectListing from '../../components/Projects'; function MainMenu() { const { data: userData, From 8304f939c345166381949b4ddb2c74f1d20aff75 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Thu, 3 Oct 2024 15:52:42 -0500 Subject: [PATCH 2/6] - Linting --- .../components/Projects/ProjectListing.module.css | 15 ++++++++------- react/src/components/Projects/ProjectListing.tsx | 14 ++++++++------ react/src/hazmapper.css | 9 +++++---- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/react/src/components/Projects/ProjectListing.module.css b/react/src/components/Projects/ProjectListing.module.css index af7ce673..ddf9b5e7 100644 --- a/react/src/components/Projects/ProjectListing.module.css +++ b/react/src/components/Projects/ProjectListing.module.css @@ -1,4 +1,4 @@ -.root{ +.root { display: flex; flex-direction: column; width: 100%; @@ -11,28 +11,29 @@ margin-top: 40px; margin-bottom: 40px; } -.projectHeader, .projectHeader th { +.projectHeader, +.projectHeader th { background: #d0d0d0; - position: sticky; + position: sticky; top: 0; z-index: 1; } -.projectListItemButton{ +.projectListItemButton { cursor: pointer; color: initial; margin-right: 10px; } -.projectListItemButton:hover{ +.projectListItemButton:hover { color: #666; } .mapColumn { -width: 30%; + width: 30%; } .projectColumn { -width: 60%; + width: 60%; } .buttonColumn { white-space: nowrap; diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index f0deb073..8f3511fb 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -21,11 +21,11 @@ const ProjectListing: React.FC = () => { if (isLoading) { return ; - }; + } if (isError) { return

Unable to retrieve projects

; - }; + } return (
@@ -42,20 +42,22 @@ const ProjectListing: React.FC = () => { type="link" className={styles.projectListItemButton} > - Create a New Map + + Create a New Map {data?.map((proj) => ( - navigateToProject(proj.uuid)}> + navigateToProject(proj.uuid)}> {proj.name} - {proj.ds_project?.value.projectId}{' - '} + {proj.ds_project?.value.projectId} + {' - '} {proj.ds_project?.value.title} - + diff --git a/react/src/hazmapper.css b/react/src/hazmapper.css index ef734134..83708cfc 100644 --- a/react/src/hazmapper.css +++ b/react/src/hazmapper.css @@ -1,5 +1,5 @@ -@import "leaflet/dist/leaflet.css"; -@import "@fortawesome/fontawesome-free/css/all.css"; +@import 'leaflet/dist/leaflet.css'; +@import '@fortawesome/fontawesome-free/css/all.css'; @import url('https://fonts.googleapis.com/css?family=Raleway'); @import url('https://unpkg.com/mapillary-js@2.18.0/dist/mapillary.min.css'); @@ -11,7 +11,6 @@ */ - /* CSS module styles taken from Angular styles.styl */ :root { --global-font-family: 'Raleway', san-serif; @@ -21,6 +20,8 @@ body { height: 100%; font-family: var(--global-font-family); } -table, form, button { +table, +form, +button { font-family: inherit; } From b5c2a4ebdae836da6878be83ca69a602a7cfb495 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Thu, 3 Oct 2024 18:12:05 -0500 Subject: [PATCH 3/6] - Adds better response and error handling. - Brings over EmptyTablePlaceholder from TUP UI that CMD collaborated with us on --- .../components/Projects/ProjectListing.tsx | 70 +++++++++++++------ .../utils/EmptyTablePlaceholder.module.css | 12 ++++ .../utils/EmptyTablePlaceholder.tsx | 22 ++++++ react/src/components/utils/index.ts | 1 + 4 files changed, 85 insertions(+), 20 deletions(-) create mode 100644 react/src/components/utils/EmptyTablePlaceholder.module.css create mode 100644 react/src/components/utils/EmptyTablePlaceholder.tsx create mode 100644 react/src/components/utils/index.ts diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 8f3511fb..1111cc80 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { useProjectsWithDesignSafeInformation } from '../../hooks'; import { Button, LoadingSpinner, Icon } from '../../core-components'; import styles from './ProjectListing.module.css'; +import { EmptyTablePlaceholder} from '../utils'; import CreateMapModal from '../CreateMapModal/CreateMapModal'; import { useNavigate } from 'react-router-dom'; @@ -23,10 +24,6 @@ const ProjectListing: React.FC = () => { return ; } - if (isError) { - return

Unable to retrieve projects

; - } - return (
@@ -49,28 +46,61 @@ const ProjectListing: React.FC = () => { - {data?.map((proj) => ( - navigateToProject(proj.uuid)}> - {proj.name} - - {proj.ds_project?.value.projectId} - {' - '} - {proj.ds_project?.value.title} - - - - + {isError && ( + + + + There was an error gathering your maps and projects. {''} + + Click here to submit a ticket on DesignSafe. + + + + )} + {data && data.length > 0 ? ( + data?.map((proj) => ( + navigateToProject(proj.uuid)}> + {proj.name} + + {proj.ds_project?.value.projectId} + {' - '} + {proj.ds_project?.value.title} + + + + + + + )) + ) : ( + + + + No projects or maps found. +
Click Create New Map above to get started. +
- ))} + )}
); }; + export default ProjectListing; diff --git a/react/src/components/utils/EmptyTablePlaceholder.module.css b/react/src/components/utils/EmptyTablePlaceholder.module.css new file mode 100644 index 00000000..4ec968b9 --- /dev/null +++ b/react/src/components/utils/EmptyTablePlaceholder.module.css @@ -0,0 +1,12 @@ +/* Table Placeholder */ +.empty { + display: flex; + align-items: center; + justify-content: center; +} + +.empty > :first-child { + margin-top: 10px; + padding: 50px; + border: 1px solid var(--global-color-primary--dark); +} diff --git a/react/src/components/utils/EmptyTablePlaceholder.tsx b/react/src/components/utils/EmptyTablePlaceholder.tsx new file mode 100644 index 00000000..1d3a4ebb --- /dev/null +++ b/react/src/components/utils/EmptyTablePlaceholder.tsx @@ -0,0 +1,22 @@ +import { SectionMessage } from '../../core-components'; +import styles from './EmptyTablePlaceholder.module.css'; +import React from 'react'; + + +interface EmptyPlaceholderProps { + children: React.ReactNode; + type: 'error' | 'warning' | 'info' | 'success'; +} + +export const EmptyTablePlaceholder: React.FC = ({ + children, + type, +}) => { + return ( +
+ {children} +
+ ); +}; + +export default EmptyTablePlaceholder; diff --git a/react/src/components/utils/index.ts b/react/src/components/utils/index.ts new file mode 100644 index 00000000..bfe0cec0 --- /dev/null +++ b/react/src/components/utils/index.ts @@ -0,0 +1 @@ +export { default as EmptyTablePlaceholder } from './EmptyTablePlaceholder'; From e5a481736276561b7cb0fc6ac44eef43fc65a1ba Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Thu, 3 Oct 2024 18:17:28 -0500 Subject: [PATCH 4/6] - Linting --- .../components/Projects/ProjectListing.tsx | 40 ++++++++++--------- .../utils/EmptyTablePlaceholder.module.css | 12 +++--- .../utils/EmptyTablePlaceholder.tsx | 7 ++-- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/react/src/components/Projects/ProjectListing.tsx b/react/src/components/Projects/ProjectListing.tsx index 1111cc80..a0e40477 100644 --- a/react/src/components/Projects/ProjectListing.tsx +++ b/react/src/components/Projects/ProjectListing.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { useProjectsWithDesignSafeInformation } from '../../hooks'; import { Button, LoadingSpinner, Icon } from '../../core-components'; import styles from './ProjectListing.module.css'; -import { EmptyTablePlaceholder} from '../utils'; +import { EmptyTablePlaceholder } from '../utils'; import CreateMapModal from '../CreateMapModal/CreateMapModal'; import { useNavigate } from 'react-router-dom'; @@ -47,20 +47,21 @@ const ProjectListing: React.FC = () => { {isError && ( - - - - There was an error gathering your maps and projects. {''} - - Click here to submit a ticket on DesignSafe. - - - - )} + + + + There was an error gathering your maps and projects. {''} + + Click here to submit a ticket on DesignSafe. + + + + + )} {data && data.length > 0 ? ( data?.map((proj) => ( navigateToProject(proj.uuid)}> @@ -88,11 +89,12 @@ const ProjectListing: React.FC = () => { )) ) : ( - - + + No projects or maps found. -
Click Create New Map above to get started. -
+
+ Click Create New Map above to get started. +
)} diff --git a/react/src/components/utils/EmptyTablePlaceholder.module.css b/react/src/components/utils/EmptyTablePlaceholder.module.css index 4ec968b9..4f33ab91 100644 --- a/react/src/components/utils/EmptyTablePlaceholder.module.css +++ b/react/src/components/utils/EmptyTablePlaceholder.module.css @@ -1,12 +1,12 @@ /* Table Placeholder */ .empty { - display: flex; - align-items: center; - justify-content: center; + display: flex; + align-items: center; + justify-content: center; } .empty > :first-child { - margin-top: 10px; - padding: 50px; - border: 1px solid var(--global-color-primary--dark); + margin-top: 10px; + padding: 50px; + border: 1px solid var(--global-color-primary--dark); } diff --git a/react/src/components/utils/EmptyTablePlaceholder.tsx b/react/src/components/utils/EmptyTablePlaceholder.tsx index 1d3a4ebb..e2c61420 100644 --- a/react/src/components/utils/EmptyTablePlaceholder.tsx +++ b/react/src/components/utils/EmptyTablePlaceholder.tsx @@ -2,19 +2,18 @@ import { SectionMessage } from '../../core-components'; import styles from './EmptyTablePlaceholder.module.css'; import React from 'react'; - interface EmptyPlaceholderProps { children: React.ReactNode; - type: 'error' | 'warning' | 'info' | 'success'; + type: 'error' | 'warning' | 'info' | 'success'; } export const EmptyTablePlaceholder: React.FC = ({ children, - type, + type, }) => { return (
- {children} + {children}
); }; From 0ff0f14ecf7356ce9af257b832aae0a7886b2e2f Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Thu, 3 Oct 2024 18:25:25 -0500 Subject: [PATCH 5/6] - Addresses Type 'ReactNode' is not assignable to type 'NonNullable' error in unit test --- react/src/components/utils/EmptyTablePlaceholder.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/react/src/components/utils/EmptyTablePlaceholder.tsx b/react/src/components/utils/EmptyTablePlaceholder.tsx index e2c61420..63fc8f24 100644 --- a/react/src/components/utils/EmptyTablePlaceholder.tsx +++ b/react/src/components/utils/EmptyTablePlaceholder.tsx @@ -2,18 +2,21 @@ import { SectionMessage } from '../../core-components'; import styles from './EmptyTablePlaceholder.module.css'; import React from 'react'; + interface EmptyPlaceholderProps { - children: React.ReactNode; - type: 'error' | 'warning' | 'info' | 'success'; + children?: React.ReactNode; + type: 'error' | 'warning' | 'info' | 'success'; } export const EmptyTablePlaceholder: React.FC = ({ children, - type, + type, }) => { return (
- {children} + {children ? ( + {children} + ) : No data available.}
); }; From d55959d03362f081f0817135baf579ea01beadc1 Mon Sep 17 00:00:00 2001 From: sophia-massie Date: Thu, 3 Oct 2024 18:28:12 -0500 Subject: [PATCH 6/6] - Linting --- react/src/components/utils/EmptyTablePlaceholder.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/react/src/components/utils/EmptyTablePlaceholder.tsx b/react/src/components/utils/EmptyTablePlaceholder.tsx index 63fc8f24..2f475c7b 100644 --- a/react/src/components/utils/EmptyTablePlaceholder.tsx +++ b/react/src/components/utils/EmptyTablePlaceholder.tsx @@ -2,21 +2,22 @@ import { SectionMessage } from '../../core-components'; import styles from './EmptyTablePlaceholder.module.css'; import React from 'react'; - interface EmptyPlaceholderProps { children?: React.ReactNode; - type: 'error' | 'warning' | 'info' | 'success'; + type: 'error' | 'warning' | 'info' | 'success'; } export const EmptyTablePlaceholder: React.FC = ({ children, - type, + type, }) => { return (
{children ? ( {children} - ) : No data available.} + ) : ( + No data available. + )}
); };