Skip to content

Commit

Permalink
feat: tables search functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanoshadjipetrou committed Sep 3, 2024
1 parent 482f06d commit a409573
Show file tree
Hide file tree
Showing 18 changed files with 782 additions and 419 deletions.
1 change: 1 addition & 0 deletions src/app/components/table-container/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface TableContainerProps extends TableProps {
selectedTab: string;
onTabChange: (tab: string) => void;
};
onSearchChange?: (search: string) => void;
}

export const TABLE_CONTAINER_TABS = [
Expand Down
98 changes: 75 additions & 23 deletions src/app/components/table-container/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import Box from "@mui/material/Box";
import { useDebounce } from "react-use";
import findIndex from "lodash/findIndex";
import Button from "@mui/material/Button";
import Popover from "@mui/material/Popover";
Expand All @@ -12,16 +13,16 @@ import Typography from "@mui/material/Typography";
import FormControlLabel from "@mui/material/FormControlLabel";
import { TabulatorFull as Tabulator } from "tabulator-tables";
import { TableContainerProps } from "app/components/table-container/data";
// import { ReactComponent as FilterIcon } from "app/assets/vectors/TableToolbarFilter.svg";
// import { ReactComponent as SearchIcon } from "app/assets/vectors/TableToolbarSearch.svg";
import { ReactComponent as SearchIcon } from "app/assets/vectors/TableToolbarSearch.svg";
import { ReactComponent as ColumnsIcon } from "app/assets/vectors/TableToolbarColumns.svg";
// import { ReactComponent as FilterIcon } from "app/assets/vectors/TableToolbarFilter.svg";
// import { ReactComponent as DownloadIcon } from "app/assets/vectors/TableToolbarDownload.svg";
import { ReactComponent as FullscreenIcon } from "app/assets/vectors/TableToolbarFullscreen.svg";

export const TableContainer: React.FC<TableContainerProps> = (
props: TableContainerProps
) => {
// const [table, setTable] = React.useState<any>(null);
const [table, setTable] = React.useState<Tabulator | null>(null);
const [columns, setColumns] = React.useState(
props.columns.map((column) => ({
...column,
Expand All @@ -39,25 +40,13 @@ export const TableContainer: React.FC<TableContainerProps> = (
const [anchorEl, setAnchorEl] = React.useState<null | HTMLButtonElement>(
null
);
const [search, setSearch] = React.useState("");
const [search1, setSearch1] = React.useState("");
const [openSearch, setOpenSearch] = React.useState(false);

const inputRef = React.useRef<HTMLInputElement>(null);
const fullscreenRef = React.useRef<HTMLDivElement>(null);

// React.useEffect(() => {
// const element = document.getElementById("table");
// if (element) {
// const tabulatorTables = Tabulator.findTable("#table");
// if (tabulatorTables.length > 0 && tabulatorTables[0]) {
// setTable(tabulatorTables[0]);
// }
// }
// }, []);

// const download = () => {
// if (table) {
// table.download("csv", "data.csv");
// }
// };

const handleColumnsMenuClick = (
event: React.MouseEvent<HTMLButtonElement>
) => {
Expand Down Expand Up @@ -87,6 +76,49 @@ export const TableContainer: React.FC<TableContainerProps> = (
setColumnsAction([...columnsLocal]);
};

const onSearchBtnClick = () => {
setOpenSearch(!openSearch);
if (openSearch) {
setSearch("");
setSearch1("");
if (props.onSearchChange) {
props.onSearchChange("");
}
} else {
setTimeout(() => {
inputRef.current?.focus();
}, 100);
}
};

const onSearchInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value);
setSearch1(e.target.value);
if (e.target.value.length === 0 && props.onSearchChange) {
props.onSearchChange("");
}
};

useDebounce(
() => {
if (search.length > 0 && props.onSearchChange) {
props.onSearchChange(search);
}
},
500,
[search]
);

React.useEffect(() => {
if (props.search) {
setSearch1(props.search);
setOpenSearch(true);
setTimeout(() => {
inputRef.current?.focus();
}, 100);
}
}, []);

return (
<Box
gap="24px"
Expand Down Expand Up @@ -172,9 +204,23 @@ export const TableContainer: React.FC<TableContainerProps> = (
},
}}
>
{/* <IconButton disableRipple>
<SearchIcon />
</IconButton> */}
{openSearch && (
<input
type="text"
ref={inputRef}
value={search1}
placeholder="Search"
onChange={onSearchInputChange}
style={{
padding: "6px 8px",
borderRadius: "4px",
border: "1px solid #DFE3E5",
}}
/>
)}
<IconButton disableRipple onClick={onSearchBtnClick}>
{!openSearch ? <SearchIcon /> : <Close />}
</IconButton>
<IconButton disableRipple onClick={fullscreen}>
<FullscreenIcon />
</IconButton>
Expand Down Expand Up @@ -261,7 +307,13 @@ export const TableContainer: React.FC<TableContainerProps> = (
</Popover>
</Box>
</Box>
<Table {...props} columns={columns} extraColumns={extraColumns} />
<Table
{...props}
data={props.data}
columns={columns}
setTable={setTable}
extraColumns={extraColumns}
/>
</Box>
);
};
4 changes: 3 additions & 1 deletion src/app/components/table/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface TableProps {
}[];
columns: ColumnDefinition[];
dataTree?: boolean;
search?: string;
setTable?: (table: Tabulator) => void;
dataTreeBranchElement?: boolean;
dataTreeStartExpanded?: boolean;
extraColumns?: ColumnDefinition[];
Expand Down Expand Up @@ -79,7 +81,7 @@ export const cellBGColorFormatter = (cell: CellComponent) => {
return text;
};

const financialFormatter = (cell: CellComponent) => {
export const financialFormatter = (cell: CellComponent) => {
if (!cell.getValue()) {
return cellBGColorFormatter(cell);
}
Expand Down
4 changes: 4 additions & 0 deletions src/app/components/table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export const Table: React.FC<TableProps> = (props: TableProps) => {
table.redraw();
}, 500);
}

if (props.setTable) {
props.setTable(table);
}
}
}, []);

Expand Down
17 changes: 15 additions & 2 deletions src/app/pages/datasets/access-to-funding/blocks/block-2/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export const AccessToFundingBlock2: React.FC<AccessToFundingBlock2Props> = (
...defaultAppliedFilters,
});

const [tableSearch, setTableSearch] = React.useState("");

const dataEligibilityTable = useStoreState((state) =>
get(state.AccessToFundingEligibilityTable, "data.data", []).map(
(item: any, index) => {
Expand Down Expand Up @@ -181,6 +183,15 @@ export const AccessToFundingBlock2: React.FC<AccessToFundingBlock2Props> = (
setChart1AppliedFilters([]);
};

const onSearchChange = (search: string) => {
setTableSearch(search);
let filterString = chart1FilterString;
if (search) {
filterString += `${filterString.length > 0 ? "&" : ""}q=${search}`;
}
fetchEligibilityTable({ filterString });
};

React.useEffect(() => {
fetchEligibilityTable({ filterString: chart1FilterString });
}, [chart1FilterString]);
Expand All @@ -199,6 +210,7 @@ export const AccessToFundingBlock2: React.FC<AccessToFundingBlock2Props> = (
>
<DatasetChartBlock
id="eligibility"
infoType="global"
title={getCMSDataField(
cmsData,
"pagesDatasetsAccessToFunding.eligibilityTitle",
Expand All @@ -212,14 +224,13 @@ export const AccessToFundingBlock2: React.FC<AccessToFundingBlock2Props> = (
dropdownItems={[]}
disableCollapse
loading={loadingEligibilityTable}
empty={dataEligibilityTable.length === 0}
filterGroups={props.filterGroups}
appliedFilters={chart1AppliedFilters}
toggleFilter={handleToggleChartFilter}
removeFilter={handleRemoveChartFilter}
handleResetFilters={handleResetChartFilters}
appliedFiltersData={chart1AppliedFiltersData}
infoType="global"
empty={dataEligibilityTable.length === 0 && tableSearch.length === 0}
>
<Box
gap="20px"
Expand Down Expand Up @@ -409,8 +420,10 @@ export const AccessToFundingBlock2: React.FC<AccessToFundingBlock2Props> = (
</Box>
<TableContainer
dataTree
search={tableSearch}
id="eligibility-table"
data={dataEligibilityTable}
onSearchChange={onSearchChange}
columns={eligibilityTableColumns}
dataTreeStartExpandedFn={(row) => row.getData().top}
/>
Expand Down
41 changes: 36 additions & 5 deletions src/app/pages/datasets/access-to-funding/blocks/block-3/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ import React from "react";
import get from "lodash/get";
import uniq from "lodash/uniq";
import Box from "@mui/material/Box";
import { Table } from "app/components/table";
import { useLocation } from "react-router-dom";
import { useCMSData } from "app/hooks/useCMSData";
import { Dropdown } from "app/components/dropdown";
import { Treemap } from "app/components/charts/treemap";
import { getCMSDataField } from "app/utils/getCMSDataField";
import { SunburstChart } from "app/components/charts/sunburst";
import { TableContainer } from "app/components/table-container";
import { FilterGroupModel } from "app/components/filters/list/data";
import { TreemapDataItem } from "app/components/charts/treemap/data";
import { useStoreActions, useStoreState } from "app/state/store/hooks";
import { DatasetChartBlock } from "app/pages/datasets/common/chart-block";
import { defaultAppliedFilters } from "app/state/api/action-reducers/sync/filters";
import { dropdownItemsAllocations } from "app/pages/datasets/access-to-funding/data";
import { TABLE_VARIATION_11_COLUMNS as ALLOCATIONS_TABLE_COLUMNS } from "app/components/table/data";
import {
financialFormatter,
cellBGColorFormatter,
} from "app/components/table/data";

interface AccessToFundingBlock3Props {
filterString: string;
Expand All @@ -41,6 +44,8 @@ export const AccessToFundingBlock3: React.FC<AccessToFundingBlock3Props> = (
...defaultAppliedFilters,
});

const [tableSearch, setTableSearch] = React.useState("");

const dataAllocationsSunburst = useStoreState((state) =>
get(state.AccessToFundingAllocationSunburst, "data.data", [])
);
Expand Down Expand Up @@ -145,6 +150,15 @@ export const AccessToFundingBlock3: React.FC<AccessToFundingBlock3Props> = (
);
}, [dataCycleFilterOptions, allocationCycleDropdownSelected]);

const onSearchChange = (search: string) => {
setTableSearch(search);
let filterString = chart2FilterString;
if (search) {
filterString += `${filterString.length > 0 ? "&" : ""}q=${search}`;
}
fetchAllocationsTable({ filterString });
};

const chartContent = React.useMemo(() => {
switch (dropdownSelected) {
case dropdownItemsAllocations[0].value:
Expand All @@ -159,17 +173,33 @@ export const AccessToFundingBlock3: React.FC<AccessToFundingBlock3Props> = (
return <Treemap data={dataAllocationsTreemap} />;
case dropdownItemsAllocations[2].value:
return (
<Table
<TableContainer
dataTree
search={tableSearch}
id="allocations-table"
data={dataAllocationsTable}
columns={ALLOCATIONS_TABLE_COLUMNS}
onSearchChange={onSearchChange}
columns={[
{
title: "Geography",
field: "name",
formatter: cellBGColorFormatter,
width: "33%",
},
{
title: "Amount ($US)",
field: allocationCycleDropdownSelected ?? "",
formatter: financialFormatter,
width: "66%",
},
]}
/>
);
default:
return null;
}
}, [
tableSearch,
dropdownSelected,
dataAllocationsSunburst,
dataAllocationsTreemap,
Expand All @@ -183,11 +213,12 @@ export const AccessToFundingBlock3: React.FC<AccessToFundingBlock3Props> = (
case dropdownItemsAllocations[1].value:
return dataAllocationsTreemap.length === 0;
case dropdownItemsAllocations[2].value:
return dataAllocationsTable.length === 0;
return dataAllocationsTable.length === 0 && tableSearch.length === 0;
default:
return false;
}
}, [
tableSearch,
dropdownSelected,
dataAllocationsSunburst,
dataAllocationsTreemap,
Expand Down
Loading

0 comments on commit a409573

Please sign in to comment.