Skip to content

Commit

Permalink
Merge pull request #3847 from bcgov/NDT-731-Enable-multiple-Global-Se…
Browse files Browse the repository at this point in the history
…arch-options

chore: enable global filter modes
  • Loading branch information
RRanath authored Feb 12, 2025
2 parents 8db5797 + afc71f4 commit 7756e69
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 36 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## [1.243.2](https://github.com/bcgov/CONN-CCBC-portal/compare/v1.243.1...v1.243.2) (2025-02-12)

## [1.243.1](https://github.com/bcgov/CONN-CCBC-portal/compare/v1.243.0...v1.243.1) (2025-02-12)

### Bug Fixes
Expand Down
91 changes: 56 additions & 35 deletions app/components/AnalystDashboard/AllDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,10 @@ import RowCount from 'components/Table/RowCount';
import AssignLead from 'components/Analyst/AssignLead';
import StatusPill from 'components/StatusPill';
import statusStyles from 'data/statusStyles';
import Link from 'next/link';
import StatusInformationIcon from 'components/Analyst/StatusInformationIcon';
import ClearFilters from 'components/Table/ClearFilters';
import type { AllDashboardTable_query$key } from '__generated__/AllDashboardTable_query.graphql';
import { Box, IconButton, TableCellProps } from '@mui/material';
import { Box, IconButton, MenuItem, TableCellProps } from '@mui/material';
import { useFeature } from '@growthbook/growthbook-react';
import getConfig from 'next/config';
import { DateTime } from 'luxon';
Expand Down Expand Up @@ -86,15 +85,6 @@ const cbcProjectStatusConverter = (status) => {
return status;
};

const StyledLink = styled(Link)`
color: ${(props) => props.theme.color.links};
text-decoration: none;
&:hover {
text-decoration: underline;
}
`;

const StyledTableHeader = styled.div`
display: flex;
justify-content: space-between;
Expand Down Expand Up @@ -132,25 +122,6 @@ const muiTableHeadCellProps = {
},
};

const CcbcIdCell = ({ cell }) => {
const applicationId = cell.row.original?.rowId;
const isCbcProject = cell.row.original?.isCbcProject;
const linkCbc = cell.row.original?.showLink;
return (
<>
{linkCbc ? (
<StyledLink
href={`/analyst/${isCbcProject ? 'cbc' : 'application'}/${applicationId}${isCbcProject ? '' : '/summary'}`}
>
{cell.getValue()}
</StyledLink>
) : (
cell.getValue()
)}
</>
);
};

const AnalystStatusCell = ({ cell }) => {
const analystStatus = cell.row.original?.analystStatus;
return <StatusPill status={analystStatus} styles={statusStyles} />;
Expand Down Expand Up @@ -322,6 +293,7 @@ const AllDashboardTable: React.FC<Props> = ({ query }) => {
isCcbc: boolean;
rowId: any;
} | null>(null);
const globalFilterMode = useRef('contains');

const expandedRowsRef = useRef({});

Expand Down Expand Up @@ -561,8 +533,26 @@ const AllDashboardTable: React.FC<Props> = ({ query }) => {
globalFilter,
};

const customGlobalFilter = (row, id, filterValue, filterMeta) => {
const defaultMatch = MRT_FilterFns.fuzzy(row, id, filterValue, filterMeta);
const customGlobalFilter = (
row,
id,
filterValue,
filterMeta,
columnVisibility
) => {
// exclude hidden columns from global filter
const visibility = columnVisibility?.[id];
if (visibility === false) return false;
if (!filterValue) return true;
if (row.getValue(id) === null) return false;
const filterMode = globalFilterMode.current || 'contains';
let defaultMatch = false;
if (filterMode === 'fuzzy') {
defaultMatch = MRT_FilterFns.fuzzy(row, id, filterValue, filterMeta);
} else {
defaultMatch = MRT_FilterFns[filterMode](row, id, filterValue);
}

const communitiesString = row.original.communities
?.map((item) => item.geoName)
.join(',')
Expand Down Expand Up @@ -610,6 +600,7 @@ const AllDashboardTable: React.FC<Props> = ({ query }) => {
externalStatusOrder: statusOrderMap[application.node.externalStatus],
internalStatusOrder: statusOrderMap[application.node.analystStatus],
communities: getCommunities(application.node),
organizationName: application.node.organizationName || '',
}));

const allCbcApplications = showCbcProjects
Expand Down Expand Up @@ -713,7 +704,6 @@ const AllDashboardTable: React.FC<Props> = ({ query }) => {
{
accessorKey: 'projectId',
header: 'Project ID',
Cell: CcbcIdCell,
},
{
accessorKey: 'zones',
Expand Down Expand Up @@ -822,17 +812,29 @@ const AllDashboardTable: React.FC<Props> = ({ query }) => {
onSortingChange: handleOnSortChange,
onColumnFiltersChange: setColumnFilters,
autoResetAll: false,
onColumnVisibilityChange: setVisibilityPreference,
onColumnVisibilityChange: (columnVisibility) => {
setVisibilityPreference(columnVisibility);
table.setGlobalFilter(null);
},
onDensityChange: setDensity,
onShowColumnFiltersChange: setShowColumnFilters,
onColumnSizingChange: setColumnSizing,
enablePagination: false,
enableGlobalFilter,
enableGlobalFilterModes: true,
globalFilterModeOptions: ['fuzzy', 'startsWith', 'contains'],
enableBottomToolbar: false,
filterFns: {
filterNumber,
statusFilter,
customGlobalFilter,
customGlobalFilter: (row, id, filterValue, filterMeta) =>
customGlobalFilter(
row,
id,
filterValue,
filterMeta,
table.getState()?.columnVisibility
),
},
renderDetailPanel: ({ row }) => (
<AllDashboardDetailPanel row={row} filterValue={globalFilter} />
Expand All @@ -842,6 +844,25 @@ const AllDashboardTable: React.FC<Props> = ({ query }) => {
onExpandedChange: (expanded) => {
setExpanded(expanded);
},
renderGlobalFilterModeMenuItems: ({
internalFilterOptions,
onSelectFilterMode,
}) => {
return internalFilterOptions.map((option) => (
<MenuItem
key={option.toString()}
selected={option?.option === globalFilterMode.current}
onClick={() => {
onSelectFilterMode(option?.option);
// setting up for custom global filter
table.setGlobalFilterFn('customGlobalFilter');
globalFilterMode.current = option?.option;
}}
>
{option.label}
</MenuItem>
));
},
renderToolbarInternalActions: ({ table }) => (
<Box>
<IconButton size="small">
Expand Down
68 changes: 68 additions & 0 deletions app/tests/pages/analyst/dashboard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,74 @@ describe('The index page', () => {
});
});

it('renders global filter modes', async () => {
jest
.spyOn(moduleApi, 'useFeature')
.mockReturnValue(mockShowCbcProjects(true));

pageTestingHelper.loadQuery();
pageTestingHelper.renderPage();

expect(screen.getByText('CCBC-010001')).toBeInTheDocument();
expect(screen.getByText('CCBC-010002')).toBeInTheDocument();

const globalSearch = screen.getByPlaceholderText('Search');
expect(globalSearch).toBeInTheDocument();

const searchButton = screen.getByTestId('SearchIcon');
expect(searchButton).toBeInTheDocument();

fireEvent.click(searchButton);

const menuItems = screen.getAllByRole('menuitem');
expect(menuItems).toHaveLength(3);
expect(menuItems[0]).toHaveTextContent('Fuzzy');
expect(menuItems[1]).toHaveTextContent('Contains');
expect(menuItems[2]).toHaveTextContent('Starts With');
});

it('global filter filters based on selected mode', async () => {
jest
.spyOn(moduleApi, 'useFeature')
.mockReturnValue(mockShowCbcProjects(true));

pageTestingHelper.loadQuery();
pageTestingHelper.renderPage();

expect(screen.getByText('CCBC-010001')).toBeInTheDocument();
expect(screen.getByText('CCBC-010002')).toBeInTheDocument();

const globalSearch = screen.getByPlaceholderText('Search');
expect(globalSearch).toBeInTheDocument();

const searchButton = screen.getByTestId('SearchIcon');
expect(searchButton).toBeInTheDocument();

fireEvent.click(searchButton);

const menuItems = screen.getAllByRole('menuitem');

fireEvent.change(globalSearch, {
target: { value: 'oae' },
});

await waitFor(() => {
expect(screen.queryByText('CCBC-010001')).toBeInTheDocument();
expect(screen.getByText('CCBC-010002')).toBeInTheDocument();
});

fireEvent.click(menuItems[1]);

fireEvent.change(globalSearch, {
target: { value: 'oae' },
});

await waitFor(() => {
expect(screen.queryByText('CCBC-010001')).not.toBeInTheDocument();
expect(screen.queryByText('CCBC-010002')).not.toBeInTheDocument();
});
});

it('clear filters correctly clears global filter and restore data', async () => {
jest
.spyOn(moduleApi, 'useFeature')
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "CONN-CCBC-portal",
"version": "1.243.1",
"version": "1.243.2",
"main": "index.js",
"repository": "https://github.com/bcgov/CONN-CCBC-portal.git",
"author": "Romer, Meherzad CITZ:EX <[email protected]>",
Expand Down

0 comments on commit 7756e69

Please sign in to comment.