Skip to content

Commit

Permalink
feat: add glossay page
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelTaylor3D committed Apr 2, 2024
1 parent 76bbc66 commit 1e653dc
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 31 deletions.
43 changes: 43 additions & 0 deletions src/renderer/api/cadt/v1/governance/governance.api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { cadtApi } from '../';
// @ts-ignore
import { BaseQueryResult } from '@reduxjs/toolkit/dist/query/baseQueryTypes';

const host: string = 'http://localhost:31310';

interface BaseQueryResult {
[key: string]: string[];
}

interface DescriptionItem {
header: string;
definition: string;
}

interface GlossaryItem {
term: string;
description: DescriptionItem[];
}

const governanceApi = cadtApi.injectEndpoints({
endpoints: (builder) => ({
getGlossary: builder.query<GlossaryItem[], void>({
query: () => ({
url: `${host}/v1/governance/meta/glossary`,
method: 'GET',
}),
transformResponse: (baseQueryReturnValue: BaseQueryResult): GlossaryItem[] => {
return Object.entries(baseQueryReturnValue).map(([key, valueArray]) => {
// Map each value in the value array to a DescriptionItem by splitting by ";" to separate header and definition
const description: DescriptionItem[] = valueArray.map((item) => {
const [header, definition] = item.split(';').map((part) => part.trim());
return { header, definition };
});

return { term: key, description };
});
},
}),
}),
});

export const { useGetGlossaryQuery } = governanceApi;
1 change: 1 addition & 0 deletions src/renderer/api/cadt/v1/governance/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './governance.api';
7 changes: 7 additions & 0 deletions src/renderer/components/blocks/layout/LeftNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ const LeftNav = () => {
>
<FormattedMessage id="units-list" />
</Sidebar.Item>
<Sidebar.Item
style={{ cursor: 'pointer' }}
active={isActive(ROUTES.GLOSSARY)}
onClick={() => navigate(ROUTES.GLOSSARY)}
>
<FormattedMessage id="glossary" />
</Sidebar.Item>
{/* Add more Sidebar.Item as needed */}
</Sidebar.ItemGroup>
</Sidebar.Items>
Expand Down
46 changes: 46 additions & 0 deletions src/renderer/components/blocks/tables/GlossaryTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useMemo } from 'react';
import { FormattedMessage } from 'react-intl';
import { DataTable } from '@/components';

interface TableProps {
data: any[];
isLoading: boolean;
order: string;
setOrder: (sort: string) => void;
}

const GlossaryTable: React.FC<TableProps> = ({ data, isLoading, order, setOrder }) => {
const columns = useMemo(
() => [
{
title: <FormattedMessage id={'term'} />,
key: 'term',
},
{
title: <FormattedMessage id={'description'} />,
key: 'description',
render: (row: any) => {
return (
<div className="text-gray-600 dark:text-white">
{row.description.map((item, index) => (
<div key={`${item.header}-${index}`} className="mb-4 last:mb-0 text-left">
<div className="font-bold items-start">{item.header}</div>
<div className="items-start">{item.definition}</div>
</div>
))}
</div>
);
},
},
],
[],
);

return (
<div className="relative">
<DataTable columns={columns} data={data} primaryKey="term" isLoading={isLoading} order={order} onChangeOrder={setOrder}/>
</div>
);
};

export { GlossaryTable };
3 changes: 2 additions & 1 deletion src/renderer/components/blocks/tables/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './ProjectsListTable';
export * from './SkeletonTable';
export * from './UnitsListTable';
export * from './UnitsListTable';
export * from './GlossaryTable';
57 changes: 57 additions & 0 deletions src/renderer/pages/Glossary/GlossaryPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { useMemo, useCallback } from 'react';
import { useGetGlossaryQuery } from '@/api/cadt/v1/governance';
import { SkeletonTable, GlossaryTable, SearchBox } from '@/components';
import { useQueryParamState, useColumnOrderHandler } from '@/hooks';
import { FormattedMessage } from 'react-intl';
import { debounce } from 'lodash';

const GlossaryPage: React.FC = () => {
const { data: glossaryData, isLoading: glossaryLoading, error: glossaryError } = useGetGlossaryQuery();
const [search, setSearch] = useQueryParamState('search', ''); // Fixed the state name to 'search'
const [order, setOrder] = useQueryParamState('order', undefined);
const handleSetOrder = useColumnOrderHandler(order, setOrder);

// Memoized ordered data based on the `order` variable
const orderedData = useMemo(() => {
if (!order || !glossaryData) return glossaryData;

const [orderBy, direction] = order.split(':');
return [...glossaryData].sort((a, b) => {
if (a[orderBy] < b[orderBy]) return direction === 'ASC' ? -1 : 1;
if (a[orderBy] > b[orderBy]) return direction === 'ASC' ? 1 : -1;
return 0;
});
}, [glossaryData, order]);

// Filter the ordered data based on the search term
const filteredData = useMemo(() => {
if (!search.trim()) return orderedData;
return orderedData?.filter(item => item.term.toLowerCase().includes(search.toLowerCase()));
}, [orderedData, search]);

const handleSearchChange = useCallback(
debounce((event: React.ChangeEvent<HTMLInputElement>) => {
setSearch(event.target.value);
}, 800),
[] // Removed dependencies on `setSearch` and `debounce` as they are not expected to change
);

if (glossaryLoading) {
return <SkeletonTable />;
}

if (glossaryError) {
return <FormattedMessage id={'unable-to-load-contents'} />;
}

return (
<>
<div className="flex flex-col md:flex-row gap-6 pl-1 my-2.5 relative z-30">
<SearchBox defaultValue={search} onChange={handleSearchChange} />
</div>
<GlossaryTable data={filteredData || []} isLoading={glossaryLoading} order={order} setOrder={handleSetOrder} />
</>
);
};

export { GlossaryPage };
1 change: 1 addition & 0 deletions src/renderer/pages/Glossary/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './GlossaryPage'
1 change: 0 additions & 1 deletion src/renderer/pages/ProjectsList/ProjectsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ const ProjectsList: React.FC = () => {
[setSearch, debounce],
);


if (projectsLoading) {
return <SkeletonTable />;
}
Expand Down
1 change: 1 addition & 0 deletions src/renderer/pages/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './Error';
export * from './ProjectsList';
export * from './UnitsList';
export * from './Glossary';
38 changes: 11 additions & 27 deletions src/renderer/routes/AppNavigator.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import React from 'react';
import {
BrowserRouter as Router,
Routes,
Route,
Navigate,
redirect,
} from 'react-router-dom';
import { BrowserRouter as Router, Routes, Route, Navigate, redirect } from 'react-router-dom';
import ROUTES from '@/routes/route-constants';
import * as Pages from '@/pages'
import {Template} from "@/components";
import * as Pages from '@/pages';
import { Template } from '@/components';

const AppNavigator: React.FC = () => {
return (
Expand All @@ -19,23 +13,13 @@ const AppNavigator: React.FC = () => {
path="*(/+)"
loader={({ params }) => redirect(params['*'] || '/')}
/>
<Route path="" element={<Template/>}>
<Route
path="/"
element={<Navigate to={ROUTES.PROJECTS_LIST}/>}
/>
<Route
path={ROUTES.PROJECTS_LIST}
element={<Pages.ProjectsList/>}
/>
<Route
path={ROUTES.UNITS_LIST}
element={<Pages.UnitsList/>}
/>
<Route
path="*"
element={<Navigate replace to={ROUTES.PROJECTS_LIST} />}
/>
<Route path="" element={<Template />}>
<Route path="/" element={<Navigate to={ROUTES.PROJECTS_LIST} />} />
<Route path={ROUTES.PROJECTS_LIST} element={<Pages.ProjectsList />} />
<Route path={ROUTES.UNITS_LIST} element={<Pages.UnitsList />} />

<Route path={ROUTES.GLOSSARY} element={<Pages.GlossaryPage />} />
<Route path="*" element={<Navigate replace to={ROUTES.PROJECTS_LIST} />} />
</Route>
</Routes>
{/* app-wide blocking modals go below this comment*/}
Expand All @@ -44,4 +28,4 @@ const AppNavigator: React.FC = () => {
);
};

export { AppNavigator };
export { AppNavigator };
3 changes: 2 additions & 1 deletion src/renderer/routes/route-constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export default {
PROJECTS_LIST: '/projects',
UNITS_LIST: '/units'
UNITS_LIST: '/units',
GLOSSARY: '/glossary',
};
5 changes: 4 additions & 1 deletion src/renderer/translations/tokens/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,8 @@
"covered-by-ndc": "Covered By Ndc",
"project-status": "Project Status",
"unit-metric": "Unit Metric",
"validation-body": "Validation Body"
"validation-body": "Validation Body",
"glossary": "Glossary",
"term": "Term",
"description": "Description"
}

0 comments on commit 1e653dc

Please sign in to comment.