From e93d85e666a2864d312cab52e8e96b97c605fa54 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Tue, 2 Apr 2024 15:11:23 -0400 Subject: [PATCH 1/2] feat: add organization badge --- .../components/blocks/layout/LeftNav.tsx | 12 ++++ .../components/blocks/widgets/OrgUidBadge.tsx | 67 +++++++++++++++++++ .../blocks/widgets/SyncIndicator.tsx | 9 ++- .../components/blocks/widgets/index.ts | 3 +- .../pages/ProjectsList/ProjectsList.tsx | 6 +- src/renderer/pages/UnitsList/UnitsList.tsx | 1 + 6 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 src/renderer/components/blocks/widgets/OrgUidBadge.tsx diff --git a/src/renderer/components/blocks/layout/LeftNav.tsx b/src/renderer/components/blocks/layout/LeftNav.tsx index e17d341d..197f9fe9 100644 --- a/src/renderer/components/blocks/layout/LeftNav.tsx +++ b/src/renderer/components/blocks/layout/LeftNav.tsx @@ -42,6 +42,18 @@ const LeftNav = () => { > +
handleNavigation(ROUTES.UNITS_LIST)} + className={`cursor-pointer p-3 ${isActive(ROUTES.UNITS_LIST) ? 'bg-gray-200 dark:bg-gray-600 text-gray-800 dark:text-white' : 'text-gray-700 dark:text-gray-300'} hover:bg-gray-300 dark:hover:bg-gray-700 rounded-md text-lg font-semibold`} + > + +
+
handleNavigation(ROUTES.GLOSSARY)} + className={`cursor-pointer p-3 ${isActive(ROUTES.GLOSSARY) ? 'bg-gray-200 dark:bg-gray-600 text-gray-800 dark:text-white' : 'text-gray-700 dark:text-gray-300'} hover:bg-gray-300 dark:hover:bg-gray-700 rounded-md text-lg font-semibold`} + > + +
{/* Additional mobile navigation items here */} diff --git a/src/renderer/components/blocks/widgets/OrgUidBadge.tsx b/src/renderer/components/blocks/widgets/OrgUidBadge.tsx new file mode 100644 index 00000000..2af9c6fc --- /dev/null +++ b/src/renderer/components/blocks/widgets/OrgUidBadge.tsx @@ -0,0 +1,67 @@ +import React, { useState, useEffect } from 'react'; +import { Toast, Tooltip } from 'flowbite-react'; + +interface OrgUidBadgeProps { + orgUid: string; +} + +const OrgUidBadge: React.FC = ({ orgUid }) => { + const [showToast, setShowToast] = useState(false); + const [toastVisible, setToastVisible] = useState(false); + const [toastMessage, setToastMessage] = useState(''); + + useEffect(() => { + let timeoutId: NodeJS.Timeout; + + if (showToast) { + setToastVisible(true); + timeoutId = setTimeout(() => setShowToast(false), 3000); + } else if (!showToast && toastVisible) { + timeoutId = setTimeout(() => setToastVisible(false), 300); + } + + return () => clearTimeout(timeoutId); + }, [showToast, toastVisible]); + + const handleCopyToClipboard = () => { + navigator.clipboard + .writeText(orgUid) + .then(() => { + setToastMessage('Org UID copied to clipboard!'); + setShowToast(true); + }) + .catch((err) => { + console.error('Failed to copy Org UID: ', err); + setToastMessage('Failed to copy Org UID.'); + setShowToast(true); + }); + }; + + if (!orgUid) { + return null; + } + + return ( + <> + {toastVisible && ( +
+ + {toastMessage} + +
+ )} + + + {orgUid} + + + + ); +}; + +export { OrgUidBadge }; diff --git a/src/renderer/components/blocks/widgets/SyncIndicator.tsx b/src/renderer/components/blocks/widgets/SyncIndicator.tsx index 04422d12..6ca73ed5 100644 --- a/src/renderer/components/blocks/widgets/SyncIndicator.tsx +++ b/src/renderer/components/blocks/widgets/SyncIndicator.tsx @@ -34,20 +34,19 @@ const SyncIndicator: React.FC = ({ detailed, orgUid }) => { } return ( -
+
{detailed && ( - <> +
{isSynced ? 'Synced' : 'Syncing...'} {!isSynced && ( - // Made "sync remaining" more subtle with lighter color and smaller font - ({syncRemaining} remaining) + {syncRemaining} remaining )} - +
)}
); diff --git a/src/renderer/components/blocks/widgets/index.ts b/src/renderer/components/blocks/widgets/index.ts index 0ac7de71..ff359cac 100644 --- a/src/renderer/components/blocks/widgets/index.ts +++ b/src/renderer/components/blocks/widgets/index.ts @@ -1,3 +1,4 @@ export * from './SearchBox'; export * from './OrganizationSelector'; -export * from './SyncIndicator'; \ No newline at end of file +export * from './SyncIndicator'; +export * from './OrgUidBadge'; \ No newline at end of file diff --git a/src/renderer/pages/ProjectsList/ProjectsList.tsx b/src/renderer/pages/ProjectsList/ProjectsList.tsx index a9584f35..a8ee7fc5 100644 --- a/src/renderer/pages/ProjectsList/ProjectsList.tsx +++ b/src/renderer/pages/ProjectsList/ProjectsList.tsx @@ -8,7 +8,8 @@ import { SkeletonTable, ProjectsListTable, SearchBox, - SyncIndicator + SyncIndicator, + OrgUidBadge } from '@/components'; import {FormattedMessage} from "react-intl"; @@ -60,10 +61,11 @@ const ProjectsList: React.FC = () => { return ( <> {projectsFetching && } -
+
+
{projectsLoading ? ( diff --git a/src/renderer/pages/UnitsList/UnitsList.tsx b/src/renderer/pages/UnitsList/UnitsList.tsx index 5ff36686..09585e49 100644 --- a/src/renderer/pages/UnitsList/UnitsList.tsx +++ b/src/renderer/pages/UnitsList/UnitsList.tsx @@ -64,6 +64,7 @@ const UnitsList: React.FC = () => { +
{unitsLoading ? ( From 44df937b18b68ede91f8c3c20830cdd58d166ac4 Mon Sep 17 00:00:00 2001 From: Michael Taylor Date: Tue, 2 Apr 2024 15:19:52 -0400 Subject: [PATCH 2/2] fix: mobile left nav --- .../components/blocks/layout/LeftNav.tsx | 8 +++++++- .../blocks/widgets/OrganizationSelector.tsx | 5 +++-- src/renderer/pages/Audit/AuditPage.tsx | 2 ++ .../pages/ProjectsList/ProjectsListPage.tsx | 18 +++++++++++------- .../pages/UnitsList/UnitsListPage.tsx | 19 ++++++++++++------- src/renderer/routes/AppNavigator.tsx | 1 + src/renderer/translations/tokens/en-US.json | 3 +-- 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/renderer/components/blocks/layout/LeftNav.tsx b/src/renderer/components/blocks/layout/LeftNav.tsx index 474ec4d6..8cc500f1 100644 --- a/src/renderer/components/blocks/layout/LeftNav.tsx +++ b/src/renderer/components/blocks/layout/LeftNav.tsx @@ -48,6 +48,12 @@ const LeftNav = () => { >
+
handleNavigation(ROUTES.AUDIT)} + className={`cursor-pointer p-3 ${isActive(ROUTES.AUDIT) ? 'bg-gray-200 dark:bg-gray-600 text-gray-800 dark:text-white' : 'text-gray-700 dark:text-gray-300'} hover:bg-gray-300 dark:hover:bg-gray-700 rounded-md text-lg font-semibold`} + > + +
handleNavigation(ROUTES.GLOSSARY)} className={`cursor-pointer p-3 ${isActive(ROUTES.GLOSSARY) ? 'bg-gray-200 dark:bg-gray-600 text-gray-800 dark:text-white' : 'text-gray-700 dark:text-gray-300'} hover:bg-gray-300 dark:hover:bg-gray-700 rounded-md text-lg font-semibold`} @@ -81,7 +87,7 @@ const LeftNav = () => { active={isActive(ROUTES.AUDIT)} onClick={() => navigate(ROUTES.AUDIT)} > - + void; defaultOrgUid: string | undefined; + noSelectionLabel?: string } -const OrganizationSelector: React.FC = ({ onSelect, defaultOrgUid }) => { +const OrganizationSelector: React.FC = ({ onSelect, defaultOrgUid, noSelectionLabel = 'Select Organization' }) => { const { data: organizations, error, isLoading } = useGetOrganizationsListQuery({}); const [selectedOrganization, setSelectedOrganization] = useState(undefined); @@ -36,7 +37,7 @@ const OrganizationSelector: React.FC = ({ onSelect, d }; return ( - + handleSelect(undefined)}>All Organizations {organizations.map((organization) => ( {
+
<> {auditLoading ? ( diff --git a/src/renderer/pages/ProjectsList/ProjectsListPage.tsx b/src/renderer/pages/ProjectsList/ProjectsListPage.tsx index 8521138e..3c3a30dd 100644 --- a/src/renderer/pages/ProjectsList/ProjectsListPage.tsx +++ b/src/renderer/pages/ProjectsList/ProjectsListPage.tsx @@ -1,7 +1,7 @@ import React, { useCallback } from 'react'; import { useGetProjectsQuery } from '@/api'; import { useQueryParamState, useColumnOrderHandler } from '@/hooks'; -import {debounce, DebouncedFunc} from 'lodash'; +import { debounce, DebouncedFunc } from 'lodash'; import { OrganizationSelector, IndeterminateProgressOverlay, @@ -9,9 +9,9 @@ import { ProjectsListTable, SearchBox, SyncIndicator, - OrgUidBadge + OrgUidBadge, } from '@/components'; -import {FormattedMessage} from "react-intl"; +import { FormattedMessage } from 'react-intl'; const ProjectsListPage: React.FC = () => { const [currentPage, setCurrentPage] = useQueryParamState('page', '1'); @@ -51,11 +51,11 @@ const ProjectsListPage: React.FC = () => { } if (projectsError) { - return ; + return ; } - if (!projectsData){ - return ; + if (!projectsData) { + return ; } return ( @@ -63,7 +63,11 @@ const ProjectsListPage: React.FC = () => { {projectsFetching && }
- +
diff --git a/src/renderer/pages/UnitsList/UnitsListPage.tsx b/src/renderer/pages/UnitsList/UnitsListPage.tsx index 61882786..ffe1d7f8 100644 --- a/src/renderer/pages/UnitsList/UnitsListPage.tsx +++ b/src/renderer/pages/UnitsList/UnitsListPage.tsx @@ -1,16 +1,17 @@ import React, { useCallback } from 'react'; import { useGetUnitsQuery } from '@/api'; import { useQueryParamState, useColumnOrderHandler } from '@/hooks'; -import {debounce, DebouncedFunc} from 'lodash'; +import { debounce, DebouncedFunc } from 'lodash'; import { OrganizationSelector, IndeterminateProgressOverlay, SkeletonTable, SearchBox, UnitsListTable, - SyncIndicator + SyncIndicator, + OrgUidBadge, } from '@/components'; -import {FormattedMessage} from "react-intl"; +import { FormattedMessage } from 'react-intl'; const UnitsListPage: React.FC = () => { const [currentPage, setCurrentPage] = useQueryParamState('page', '1'); @@ -50,11 +51,11 @@ const UnitsListPage: React.FC = () => { } if (unitsError) { - return ; + return ; } - if (!unitsData){ - return ; + if (!unitsData) { + return ; } return ( @@ -62,7 +63,11 @@ const UnitsListPage: React.FC = () => { {unitsFetching && }
- +
diff --git a/src/renderer/routes/AppNavigator.tsx b/src/renderer/routes/AppNavigator.tsx index edb56a54..0ec2c39d 100644 --- a/src/renderer/routes/AppNavigator.tsx +++ b/src/renderer/routes/AppNavigator.tsx @@ -23,6 +23,7 @@ const AppNavigator: React.FC = () => { } /> } /> } /> + } /> } /> } /> diff --git a/src/renderer/translations/tokens/en-US.json b/src/renderer/translations/tokens/en-US.json index acb84668..eeaf1caf 100644 --- a/src/renderer/translations/tokens/en-US.json +++ b/src/renderer/translations/tokens/en-US.json @@ -28,7 +28,6 @@ "covered-by-ndc": "Covered By Ndc", "project-status": "Project Status", "unit-metric": "Unit Metric", - "validation-body": "Validation Body", "table": "Table", "timestamp": "Timestamp", "type": "Type", @@ -36,7 +35,7 @@ "author": "Author", "comment": "Comment", "please-select-an-organization-to-view-audit-data": "Please select an organization to view audit data", - "audits": "Audits", + "audit": "Audit", "validation-body": "Validation Body", "glossary": "Glossary", "term": "Term",