Skip to content

Commit

Permalink
feat(table-component): blacklist or hide columns when needed
Browse files Browse the repository at this point in the history
  • Loading branch information
DanSallau committed Apr 1, 2020
1 parent 36bf309 commit 695bf8e
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 59 deletions.
70 changes: 65 additions & 5 deletions develop/components/pages/TablePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,52 @@ const TablePage: React.FunctionComponent = () => {
const [dropDownList1Selected, setDropdownList1Selected] = React.useState<Array<DropdownItem>>([]);
const [statusDropdownSelected, setStatusDropdownSelected] = React.useState<Array<DropdownItem>>([]);
const [ageDropdownSelected, setAgeDropdownSelected] = React.useState<Array<DropdownItem>>([]);
const [blackListDropdownSelected, setBlacklisteDropdownSelected] = React.useState<Array<DropdownItem>>([]);
const [textBoxValue2, setTextBoxValue2] = React.useState<string>("");
const [searchTriggered, setSearchTriggered] = React.useState<boolean>(false);
const [editMode, setEditMode] = React.useState<EditMode>(null);
const [editableColumns, setEditableColumns] = React.useState<Array<TableHeader>>([
{
label: "id",
accessor: "id",
canSort: false
},
{
label: "First Name",
accessor: "firstName"
},
{
label: "Last Name",
accessor: "lastName"
},
{
label: "Age",
accessor: "age"
},
{
label: "Visits",
accessor: "visits"
},
{
label: "Profile Progress",
accessor: "progress"
},
{
label: "Status",
accessor: "status"
}
]);

const columns: Array<Column> = React.useMemo(
() => [
{
label: "id",
accessor: "id",
canSort: false,
canEdit: false
canSort: false
},
{
label: "First Name",
accessor: "firstName",
canEdit: false
accessor: "firstName"
},
{
label: "Last Name",
Expand All @@ -63,9 +94,21 @@ const TablePage: React.FunctionComponent = () => {
],
[]
);

const [filters, setFilters] = React.useState<Array<FilterItem>>(columns.map((column: Column) => ({ accessor: column.accessor, filters: [] })));

React.useEffect(() => {
const isBlackListed: (c: string) => boolean = (accessor: string) => blackListDropdownSelected?.some((item: DropdownItem) => item.value === accessor);
const updateColumns: Array<TableHeader> = editableColumns?.map((column: Column) => {
if (isBlackListed(column?.accessor)) {
return { ...column, isHidden: true };
}

return { ...column, isHidden: false };
});

setEditableColumns(updateColumns);
}, [blackListDropdownSelected]);

React.useEffect(() => {
const updatedFilter: Array<string> = statusDropdownSelected?.map((item: DropdownItem) => item.value);
const updatedFilterItems: Array<FilterItem> = filters?.map((filterItem: FilterItem) => {
Expand Down Expand Up @@ -167,6 +210,8 @@ const TablePage: React.FunctionComponent = () => {
[]
);

const columnsDropDownList: Array<DropdownItem> = React.useMemo(() => columns.map((column: Column) => ({ value: column.accessor, label: column.label as string })).sort(), []);

return (
<div className="route-template container">
<div className="info-holder">
Expand Down Expand Up @@ -195,6 +240,21 @@ const TablePage: React.FunctionComponent = () => {
/>
</div>

<p>Here are sample outputs with hidden columns</p>
<div className="result wide">
<div className="row">
<div className="col-3">
<Dropdown
list={columnsDropDownList}
selectedValue={blackListDropdownSelected}
onChange={(value: Array<DropdownItem>) => setBlacklisteDropdownSelected(value)}
multi={true}
/>
</div>
</div>
<Table columns={editableColumns} data={smallData} />
</div>

<p>Here an example with pagination</p>
<div className="result wide">
<Table
Expand Down
117 changes: 63 additions & 54 deletions src/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export interface Column {
label: string | React.ReactNode;
accessor: string;
canSort?: boolean;
isHidden?: boolean;
}

export interface ActionLinkItem {
Expand All @@ -67,6 +68,7 @@ interface Cell {
accessor: string;
value: string | number | boolean;
canEdit?: boolean;
hidden?: boolean;
}

export interface TableRow {
Expand Down Expand Up @@ -365,7 +367,7 @@ const RowUI: React.FunctionComponent<RowUIProps> = (props: RowUIProps) => {
)
)}
{props.row.cells.map((cell: Cell, cellIndex: number) => {
return (
return !cell.hidden ? (
<td key={`${props.type}-${cellIndex}`}>
{props.row?.isEditMode && cell.canEdit ? (
<TextboxGroup
Expand All @@ -380,7 +382,7 @@ const RowUI: React.FunctionComponent<RowUIProps> = (props: RowUIProps) => {
cell.value
)}
</td>
);
) : null;
})}
{props.useShowActionColumn && (
<td>
Expand Down Expand Up @@ -499,26 +501,28 @@ const TableUI: React.FunctionComponent<TableUIProps> = React.memo(
) : (
props.rowsAreCollapsable && <th />
)}
{props.columns?.map((header: TableHeader, index: number) => (
<th
key={index}
className={props.sortable && header.canSort ? "sortable" : ""}
onClick={(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
if (props.sortable && header.canSort) {
props.onSort(header?.accessor, header.isSortedDesc ? sortDirectionTypes.Ascending : sortDirectionTypes.Descending);
} else {
e.preventDefault();
}
}}
>
{header.label}
{props.sortable && header.canSort && (
<div role="link" className={"icon-holder" + (header.isSorted ? (header.isSortedDesc ? " desc" : " asc") : "")} id={header.accessor}>
{defaultSort}
</div>
)}
</th>
))}
{props.columns?.map((header: TableHeader, index: number) => {
return !header.isHidden ? (
<th
key={index}
className={props.sortable && header.canSort ? "sortable" : ""}
onClick={(e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
if (props.sortable && header.canSort) {
props.onSort(header?.accessor, header.isSortedDesc ? sortDirectionTypes.Ascending : sortDirectionTypes.Descending);
} else {
e.preventDefault();
}
}}
>
{header.label}
{props.sortable && header.canSort && (
<div role="link" className={"icon-holder" + (header.isSorted ? (header.isSortedDesc ? " desc" : " asc") : "")} id={header.accessor}>
{defaultSort}
</div>
)}
</th>
) : null;
})}
{props.useShowActionColumn && <th />}
</tr>
</thead>
Expand Down Expand Up @@ -1007,38 +1011,43 @@ export const Table: React.FunctionComponent<TableProps> = React.memo(
*
* @param rows The table or or data to initialize rows from
*/
const getRows = React.useCallback((rows: Array<DataItem<any>>): Array<TableRow> => {
const isBlackListed: (a: string) => boolean = (accessor: string): boolean => ["id", ...(props.editProps?.blackListedAccessors || [])].indexOf(accessor) > -1;
const updatedRows: Array<TableRow> = rows?.map((row: TableRow, index: number) => {
const updatedCells: Array<Cell> = Object.keys(row)
.filter((key: string) => {
return ["rowContentDetail", "subRows", "cells", "expanded", "actionsDropdownDropped", "selected", "rowIndex"].indexOf(key) < 0;
})
.map(
(accessor: string): Cell => {
return {
id: accessor,
accessor,
value: row[accessor],
canEdit: !isBlackListed(accessor)
};
}
);
const getRows = React.useCallback(
(rows: Array<DataItem<any>>): Array<TableRow> => {
const isBlackListed: (a: string) => boolean = (accessor: string): boolean => ["id", ...(props.editProps?.blackListedAccessors || [])].indexOf(accessor) > -1;
const isBlackListedForDisplay: (a: string) => boolean = (accessor: string): boolean => props.columns?.some((column: Column) => column.accessor === accessor && column?.isHidden);
const updatedRows: Array<TableRow> = rows?.map((row: TableRow, index: number) => {
const updatedCells: Array<Cell> = Object.keys(row)
.filter((key: string) => {
return ["rowContentDetail", "subRows", "cells", "expanded", "actionsDropdownDropped", "selected", "rowIndex"].indexOf(key) < 0;
})
.map(
(accessor: string): Cell => {
return {
id: accessor,
accessor,
value: row[accessor],
canEdit: !isBlackListed(accessor),
hidden: isBlackListedForDisplay(accessor)
};
}
);

return {
...row,
rowIndex: index,
cells: updatedCells,
selected: row.selected || false,
actionsDropdownDropped: row.actionsDropdownDropped || false,
expanded: row.expanded || false,
subRows: row.subRows ? getRows(row.subRows) : [],
isEditMode: row.isEditMode || false
};
});
return {
...row,
rowIndex: index,
cells: updatedCells,
selected: row.selected || false,
actionsDropdownDropped: row.actionsDropdownDropped || false,
expanded: row.expanded || false,
subRows: row.subRows ? getRows(row.subRows) : [],
isEditMode: row.isEditMode || false
};
});

return updatedRows || [];
}, []);
return updatedRows || [];
},
[props.columns]
);

/**
* Call when item is selected
Expand Down Expand Up @@ -1079,7 +1088,7 @@ export const Table: React.FunctionComponent<TableProps> = React.memo(
setTableRows(updatedRows);
setTableEditRows(editTableRows);
setTableRowsImage(updatedRows);
}, [props.data]);
}, [props.data, props.columns]);

const doPaginate = React.useCallback((): void => {
const chosenRows: Array<TableRow> = tableEditRows?.length ? tableEditRows : tableRows;
Expand Down Expand Up @@ -1238,7 +1247,7 @@ export const Table: React.FunctionComponent<TableProps> = React.memo(

React.useEffect(() => {
setDefaultTableRows();
}, [props.data]);
}, [props.data, props.columns]);

React.useEffect(() => {
doPaginate();
Expand Down

0 comments on commit 695bf8e

Please sign in to comment.