Skip to content

Commit

Permalink
Merge pull request #284 from Capgemini/feature/table-245
Browse files Browse the repository at this point in the history
feat: adding shortened customHeaderLabels
  • Loading branch information
Ibabalola authored Apr 19, 2022
2 parents 64ae62b + b028193 commit 491cf22
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 77 deletions.
60 changes: 60 additions & 0 deletions example/src/components/TableDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,66 @@ export const TableDemo = () => {
columnsWidth={['100px']}
trProps={trProps}
/>

<h1>custom header with order</h1>
<Table
dataSource={data}
customHeaderLabels={[
{ label: 'Test', data: 'id' },
{ label: 'position', data: 'position' },
{ label: 'name', data: 'name' },
{ label: 'weight', data: 'weight' },
{ label: 'symbol', data: 'symbol' },
{ label: 'actions', data: 'actions' },
]}
onSelect={handleSelect}
handleCellClick={handleCellClick}
tableClassName="table"
theadClassName="thead"
trClassName="header-row"
thClassName="th"
tbodyClassName="tbody"
tdClassName="td"
selectedRowClassName="trSelected"
withOrderBy={true}
sortAscIcon={
<FontAwesomeIcon icon={faArrowUp} style={{ marginLeft: '4px' }} />
}
sortDescIcon={
<FontAwesomeIcon icon={faArrowDown} style={{ marginLeft: '4px' }} />
}
columnsWidth={['100px']}
/>

<h1>custom 'shortened' header with order</h1>
<Table
dataSource={data}
customHeaderLabels={[
'Test',
'positions',
'names',
'weights',
'symbols',
'actions',
]}
onSelect={handleSelect}
handleCellClick={handleCellClick}
tableClassName="table"
theadClassName="thead"
trClassName="header-row"
thClassName="th"
tbodyClassName="tbody"
tdClassName="td"
selectedRowClassName="trSelected"
withOrderBy={true}
sortAscIcon={
<FontAwesomeIcon icon={faArrowUp} style={{ marginLeft: '4px' }} />
}
sortDescIcon={
<FontAwesomeIcon icon={faArrowDown} style={{ marginLeft: '4px' }} />
}
columnsWidth={['100px']}
/>
</div>
);
};
78 changes: 43 additions & 35 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,46 @@
module.exports = {
preset: "ts-jest",
testEnvironment: "jsdom",
collectCoverage: true,
"moduleNameMapper": {
"^.+\\.(css|less|scss)$": "identity-obj-proxy"
},
"modulePathIgnorePatterns": [
"<rootDir>/example",
"<rootDir>/dist",
"<rootDir>/coverage",
"<rootDir>/static",
"<rootDir>/stories"
],
"collectCoverageFrom": [
"src/**/*.{ts,tsx}",
"!src/**/index.{ts,tsx}",
"!src/typings.d.ts",
"!<rootDir>/node_modules/",
"!<rootDir>/path/to/dir/",
"!src/generatePresentationalComponent/createPresentationalComponent.ts"
],
globals: {
"ts-jest": {
tsconfig: {
outDir: "./dist/",
sourceMap: true,
noImplicitAny: true,
module: "commonjs",
target: "es6",
jsx: "react",
allowSyntheticDefaultImports: true,
esModuleInterop: true,
},
preset: 'ts-jest',
testEnvironment: 'jsdom',
collectCoverage: true,
'coverageReporters': ['json', 'lcov', 'text', 'html'],
'coverageThreshold': {
'global': {
'branches': 100,
'functions': 100,
'lines': 100,
'statements': 100
}
},
'moduleNameMapper': {
'^.+\\.(css|less|scss)$': 'identity-obj-proxy'
},
'modulePathIgnorePatterns': [
'<rootDir>/example',
'<rootDir>/dist',
'<rootDir>/coverage',
'<rootDir>/static',
'<rootDir>/stories'
],
'collectCoverageFrom': [
'src/**/*.{ts,tsx}',
'!src/**/index.{ts,tsx}',
'!src/typings.d.ts',
'!<rootDir>/node_modules/',
'!<rootDir>/path/to/dir/',
'!src/generatePresentationalComponent/createPresentationalComponent.ts'
],
globals: {
'ts-jest': {
tsconfig: {
outDir: './dist/',
sourceMap: true,
noImplicitAny: true,
module: 'commonjs',
target: 'es6',
jsx: 'react',
allowSyntheticDefaultImports: true,
esModuleInterop: true,
},
},
};
},
};
54 changes: 45 additions & 9 deletions src/table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import { Body } from './Body';
import { Header } from './Header';
import { useSortableData } from './useSortable';
import { useTableSearch } from './useTableSearch';
type CustomHeaderLabel = {
label: string;
data: string;
omit?: boolean;
};
type TableProps = {
/**
* the data source used to populate the table
Expand Down Expand Up @@ -76,7 +81,7 @@ type TableProps = {
/**
* allow to specify a custom header labels
*/
customHeaderLabels?: { label: string; data: string }[];
customHeaderLabels?: CustomHeaderLabel[] | string[];
/**
* allow to pass extra properties to each row
*/
Expand Down Expand Up @@ -117,13 +122,28 @@ export const Table = ({
data: withOrderBy ? items : dataSource,
});

const isListOfStrings = (
headers: CustomHeaderLabel[] | string[]
): headers is string[] =>
headers.some(
(header: CustomHeaderLabel | string) => typeof header === 'string'
);

const handleClick = (value: string) => {
if (customHeaderLabels) {
const customHeaderEl = customHeaderLabels.find(c => c.label === value);
const customHeaderEl = isListOfStrings(customHeaderLabels)
? customHeaderLabels.findIndex((c: string) => c === value)
: customHeaderLabels.find((c: CustomHeaderLabel) => c.label === value);

const key =
typeof customHeaderEl === 'number'
? Object.keys(dataSource[0])[customHeaderEl]
: (customHeaderEl as CustomHeaderLabel).data;

//@ts-ignore
requestSort(customHeaderEl.data);
requestSort(key);
//@ts-ignore
setSelectedHeader(customHeaderEl.data);
setSelectedHeader(key);
} else {
requestSort(value);
setSelectedHeader(value);
Expand All @@ -142,6 +162,26 @@ export const Table = ({
);
};

const getHeaderValues = () => {
if (customHeaderLabels && isListOfStrings(customHeaderLabels)) {
return customHeaderLabels.filter(
(label: string) => !columnsToOmit?.includes(label)
);
}

if (customHeaderLabels) {
return Array.from(
customHeaderLabels.filter(
(c: CustomHeaderLabel) =>
!columnsToOmit?.includes(c.data) && c.omit !== true
),
(c: CustomHeaderLabel) => c.label
);
}

return keys(items, columnsToOmit);
};

return (
<>
{withSearch && (
Expand All @@ -156,11 +196,7 @@ export const Table = ({
theadClassName={theadClassName}
trClassName={trClassName}
thClassName={thClassName}
values={
customHeaderLabels
? Array.from(customHeaderLabels, c => c.label)
: keys(items, columnsToOmit)
}
values={getHeaderValues()}
keySorted={getClassNamesFor(selectedHeader)}
sortAscIcon={sortAscIcon}
sortDescIcon={sortDescIcon}
Expand Down
116 changes: 115 additions & 1 deletion src/table/__tests__/Table.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,50 @@ describe('Table', () => {
expect(row.innerHTML).toContain('<span>1</span>');
});

it('should perform the order with short custom headers', () => {
render(
<Table
dataSource={values}
customHeaderLabels={['Test', 'position', 'actions']}
selectedRowClassName="selectedRowClassName"
withOrderBy={true}
/>
);
//body
const { id } = values[0];
const row: any = screen.getByText(id).closest('tr');
expect(row.innerHTML).toContain('<span>2</span>');
//header
const rows: any = screen.getAllByRole('row');
const idHeader = rows[0].children[0];
fireEvent.click(idHeader);
expect(row.innerHTML).toContain('<span>1</span>');
});

it('should not perform the order when data can not be found', () => {
render(
<Table
dataSource={values}
customHeaderLabels={[
{ label: 'invalid', data: 'undefined' },
{ label: 'position', data: 'position' },
{ label: 'actions', data: 'actions' },
]}
selectedRowClassName="selectedRowClassName"
withOrderBy={true}
/>
);
//body
const { id } = values[0];
const row: any = screen.getByText(id).closest('tr');
expect(row.innerHTML).toContain('<span>2</span>');
//header
const rows: any = screen.getAllByRole('row');
const idHeader = rows[0].children[0];
fireEvent.click(idHeader);
expect(row.innerHTML).toContain('<span>2</span>');
});

it('should allow to search and return 0 elements', () => {
render(
<Table
Expand Down Expand Up @@ -124,6 +168,76 @@ describe('Table', () => {
expect(tbody[1].children).toHaveLength(0);
});

it('should not display omitted table headers', () => {
render(<Table dataSource={values} columnsToOmit={['position']} />);
const row: any = screen.getAllByRole('row');
expect(row[1].innerHTML).toContain('id');
expect(row[2].innerHTML).toContain('actions');
});

it('should not display omitted table headers with given custom headers', () => {
render(
<Table
dataSource={values}
columnsToOmit={['position']}
customHeaderLabels={[
{ label: 'Test', data: 'id' },
{ label: 'position', data: 'position' },
{ label: 'actions', data: 'actions' },
]}
/>
);
const row: any = screen.getAllByRole('row');
expect(row[1].innerHTML).toContain('Test');
expect(row[2].innerHTML).toContain('actions');
});

it('should not display omitted table headers with given custom headers with omit flag', () => {
render(
<Table
dataSource={values}
customHeaderLabels={[
{ label: 'Test', data: 'id' },
{ label: 'position', data: 'position', omit: true },
{ label: 'actions', data: 'actions' },
]}
/>
);
const row: any = screen.getAllByRole('row');
expect(row[1].innerHTML).toContain('Test');
expect(row[2].innerHTML).toContain('actions');
});

it('should not display omitted table headers with given shorted custom headers', () => {
render(
<Table
dataSource={values}
columnsToOmit={['position']}
customHeaderLabels={['Test', 'position', 'actions']}
/>
);
const row: any = screen.getAllByRole('row');
expect(row[1].innerHTML).toContain('Test');
expect(row[2].innerHTML).toContain('actions');
});

it('should display only the table header', () => {
render(
<Table
dataSource={[]}
customHeaderLabels={['Test', 'position', 'actions']}
selectedRowClassName="selectedRowClassName"
withSearch={true}
/>
);
const row: any = screen.getAllByRole('row');
expect(row[1].innerHTML).toContain('Test');
expect(row[2].innerHTML).toContain('position');
expect(row[3].innerHTML).toContain('actions');
const tbody = screen.getAllByRole('rowgroup');
expect(tbody[1].children).toHaveLength(0);
});

it('should allow to reorder the data if the customHeader is specified', () => {
render(
<Table
Expand All @@ -148,7 +262,7 @@ describe('Table', () => {
expect(row.innerHTML).toContain('<span>1</span>');
});

it('should not reorder the data if the customHeader specified doesn\'t have a match data', () => {
it("should not reorder the data if the customHeader specified doesn't have a match data", () => {
render(
<Table
dataSource={values}
Expand Down
9 changes: 1 addition & 8 deletions stories/liveEdit/TableLive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,7 @@ function TableDemo() {
<div className="App">
<Table
dataSource={data}
customHeaderLabels={[
{ label: 'Test', data: 'id' },
{ label: 'position', data: 'position' },
{ label: 'name', data: 'name' },
{ label: 'weight', data: 'weight' },
{ label: 'symbol', data: 'symbol' },
{ label: 'actions', data: 'actions' },
]}
customHeaderLabels={['Test', 'position', 'name', 'weight', 'symbol', 'actions']}
columnsToOmit={['symbol']}
onSelect={handleSelect}
handleCellClick={handleCellClick}
Expand Down
Loading

0 comments on commit 491cf22

Please sign in to comment.