Skip to content

Commit 5815705

Browse files
authored
Merge pull request #6 from fhlavac/table
Display PF table in DataView example
2 parents 20d290c + b724159 commit 5815705

File tree

10 files changed

+231
-46
lines changed

10 files changed

+231
-46
lines changed

cypress/component/DataView.cy.tsx

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,86 @@
11
import React from 'react';
22
import { Pagination } from '@patternfly/react-core';
3+
import { Table, Tbody, Th, Thead, Tr, Td } from '@patternfly/react-table';
34
import DataView from '../../packages/module/dist/dynamic/DataView';
45
import DataViewToolbar from '../../packages/module/dist/esm/DataViewToolbar';
56

7+
interface Repository {
8+
name: string;
9+
branches: string | null;
10+
prs: string | null;
11+
workspaces: string;
12+
lastCommit: string;
13+
}
14+
615
const PAGINATION = {
716
page: 1,
8-
perPage: 1
17+
perPage: 10
918
}
1019

20+
const repositories: Repository[] = [
21+
{ name: 'one', branches: 'two', prs: 'three', workspaces: 'four', lastCommit: 'five' },
22+
{ name: 'one - 2', branches: null, prs: null, workspaces: 'four - 2', lastCommit: 'five - 2' },
23+
{ name: 'one - 3', branches: 'two - 3', prs: 'three - 3', workspaces: 'four - 3', lastCommit: 'five - 3' },
24+
{ name: 'one - 4', branches: 'two - 4', prs: 'null', workspaces: 'four - 4', lastCommit: 'five - 4' },
25+
{ name: 'one - 5', branches: 'two - 5', prs: 'three - 5', workspaces: 'four - 5', lastCommit: 'five - 5' },
26+
{ name: 'one - 6', branches: 'two - 6', prs: 'three - 6', workspaces: 'four - 6', lastCommit: 'five - 6' }
27+
];
28+
29+
const cols: Record<keyof Repository, string> = {
30+
name: 'Repositories',
31+
branches: 'Branches',
32+
prs: 'Pull requests',
33+
workspaces: 'Workspaces',
34+
lastCommit: 'Last commit'
35+
};
36+
1137
describe('DataView', () => {
1238
it('renders the data view layout', () => {
1339
cy.mount(<DataView><>Data view content</></DataView>)
1440
cy.get('[data-ouia-component-id="DataView-stack-item-0"]').contains('Data view content');
1541
});
1642

17-
it('renders the data view with toolbar, data section and footer', () => {
43+
it('renders the data view with toolbar, tabular data section and footer', () => {
44+
const ouiaId = 'data';
45+
1846
cy.mount(
1947
<DataView>
2048
<DataViewToolbar pagination={<Pagination {...PAGINATION} ouiaId="DataViewToolbar-pagination" />} />
21-
<>Data section</>
49+
<Table aria-label="Repositories table" ouiaId={ouiaId}>
50+
<Thead data-ouia-component-id={`${ouiaId}-thead`}>
51+
<Tr ouiaId={`${ouiaId}-tr-head`}>
52+
{Object.values(cols).map((column, index) => <Th key={index} data-ouia-component-id={`${ouiaId}-th-${index}`}>{column}</Th>)}
53+
</Tr>
54+
</Thead>
55+
<Tbody>
56+
{repositories.map((repo, rowIndex) => (
57+
<Tr key={repo.name}>
58+
<Td data-ouia-component-id={`${ouiaId}-td-${rowIndex}-name`} dataLabel={cols.name}>{repo.name}</Td>
59+
<Td data-ouia-component-id={`${ouiaId}-td-${rowIndex}-branches`} dataLabel={cols.branches}>{repo.branches}</Td>
60+
<Td data-ouia-component-id={`${ouiaId}-td-${rowIndex}-prs`} dataLabel={cols.prs}>{repo.prs}</Td>
61+
<Td data-ouia-component-id={`${ouiaId}-td-${rowIndex}-workspaces`} dataLabel={cols.workspaces}>{repo.workspaces}</Td>
62+
<Td data-ouia-component-id={`${ouiaId}-td-${rowIndex}-last-commit`} dataLabel={cols.lastCommit}>{repo.lastCommit}</Td>
63+
</Tr>
64+
))}
65+
</Tbody>
66+
</Table>
2267
<DataViewToolbar pagination={<Pagination isCompact {...PAGINATION} ouiaId="DataViewFooter-pagination" />} ouiaId="DataViewFooter" />
2368
</DataView>
2469
);
2570
cy.get('[data-ouia-component-id="DataViewToolbar-pagination"]').should('exist');
26-
cy.get('[data-ouia-component-id="DataView-stack-item-1"]').contains('Data section');
71+
72+
cy.get('[data-ouia-component-id="data-th-0"]').contains('Repositories');
73+
cy.get('[data-ouia-component-id="data-th-1"]').contains('Branches');
74+
cy.get('[data-ouia-component-id="data-th-2"]').contains('Pull requests');
75+
cy.get('[data-ouia-component-id="data-th-3"]').contains('Workspaces');
76+
cy.get('[data-ouia-component-id="data-th-4"]').contains('Last commit');
77+
78+
cy.get('[data-ouia-component-id="data-td-0-name"]').contains('one');
79+
cy.get('[data-ouia-component-id="data-td-2-branches"]').contains('two - 3');
80+
cy.get('[data-ouia-component-id="data-td-3-prs"]').contains('null');
81+
cy.get('[data-ouia-component-id="data-td-4-workspaces"]').contains('four - 5');
82+
cy.get('[data-ouia-component-id="data-td-5-last-commit"]').contains('five - 6');
83+
2784
cy.get('[data-ouia-component-id="DataViewFooter-pagination"]').should('exist');
2885
});
2986
});

cypress/e2e/DataView.spec.cy.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
describe('Test the Data view docs page', () => {
22

3-
it.skip('renders the docs', () => {
4-
cy.visit('http://localhost:8006/extensions/data-view/data-view');
3+
it('displays a layout with a table and paginates', () => {
4+
const ouiaId = 'LayoutExample';
5+
6+
cy.visit('http://localhost:8006/extensions/data-view/data-view-layout');
7+
8+
cy.get(`[data-ouia-component-id="${ouiaId}Header-pagination"]`).should('exist');
9+
10+
cy.get(`[data-ouia-component-id="${ouiaId}Footer-pagination"]`).should('exist');
11+
12+
cy.get(`[data-ouia-component-id="${ouiaId}-th-0"]`).contains('Repositories');
13+
cy.get(`[data-ouia-component-id="${ouiaId}-th-4"]`).contains('Last commit');
14+
15+
cy.get(`[data-ouia-component-id="${ouiaId}-td-0-0"]`).contains('one');
16+
cy.get(`[data-ouia-component-id="${ouiaId}-td-4-4"]`).contains('five - 5');
17+
cy.get(`[data-ouia-component-id="${ouiaId}-td-5-4"]`).should('not.exist');
18+
19+
// move to the next page
20+
cy.get(`[data-action="next"`).first().click({ force: true });
21+
cy.get(`[data-ouia-component-id="${ouiaId}-td-0-4"]`).contains('five - 6');
22+
23+
// move to previous page
24+
cy.get(`[data-action="previous"`).eq(1).click({ force: true });
25+
cy.get(`[data-ouia-component-id="${ouiaId}-td-0-4"]`).contains('five');
526
})
627
})

packages/module/patternfly-docs/content/extensions/data-view/examples/DataView/DataView.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ source: react
1313
propComponents: ['DataView']
1414
sourceLink: https://github.com/patternfly/react-data-view/blob/main/packages/module/patternfly-docs/content/extensions/data-view/examples/DataView/DataView.md
1515
---
16-
import { Pagination } from '@patternfly/react-core';
16+
import { useMemo } from 'react';
17+
import { useDataViewPagination } from '@patternfly/react-data-view/dist/dynamic/Hooks';
1718
import DataView from '@patternfly/react-data-view/dist/dynamic/DataView';
1819
import DataViewToolbar from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
1920

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,65 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22
import { Pagination } from '@patternfly/react-core';
3+
import { Table, Tbody, Th, Thead, Tr, Td } from '@patternfly/react-table';
4+
import { useDataViewPagination } from '@patternfly/react-data-view/dist/dynamic/Hooks';
35
import DataView from '@patternfly/react-data-view/dist/dynamic/DataView';
46
import DataViewToolbar from '@patternfly/react-data-view/dist/dynamic/DataViewToolbar';
57

6-
const layoutItemStyling = {
7-
width: '100%',
8-
height: '5rem',
9-
padding: 'var(--pf-t--global--spacer--md)',
10-
border: 'var(--pf-t--global--border--width--box--default) dashed var(--pf-t--global--border--color--default)'
11-
};
8+
const perPageOptions = [
9+
{ title: '5', value: 5 },
10+
{ title: '10', value: 10 }
11+
]
1212

13-
const PAGINATION = {
14-
page: 1,
15-
perPage: 1
13+
interface Repository {
14+
name: string;
15+
branches: string | null;
16+
prs: string | null;
17+
workspaces: string;
18+
lastCommit: string;
1619
}
1720

18-
export const BasicExample: React.FunctionComponent = () => (
19-
<DataView>
20-
<DataViewToolbar pagination={<Pagination {...PAGINATION} />} />
21-
<div style={layoutItemStyling}>Data representation</div>
22-
<DataViewToolbar pagination={<Pagination isCompact {...PAGINATION} ouiaId="DataViewFooter" />} />
23-
</DataView>
24-
)
21+
const repositories: Repository[] = [
22+
{ name: 'one', branches: 'two', prs: 'three', workspaces: 'four', lastCommit: 'five' },
23+
{ name: 'one - 2', branches: null, prs: null, workspaces: 'four - 2', lastCommit: 'five - 2' },
24+
{ name: 'one - 3', branches: 'two - 3', prs: 'three - 3', workspaces: 'four - 3', lastCommit: 'five - 3' },
25+
{ name: 'one - 4', branches: 'two - 4', prs: 'null', workspaces: 'four - 4', lastCommit: 'five - 4' },
26+
{ name: 'one - 5', branches: 'two - 5', prs: 'three - 5', workspaces: 'four - 5', lastCommit: 'five - 5' },
27+
{ name: 'one - 6', branches: 'two - 6', prs: 'three - 6', workspaces: 'four - 6', lastCommit: 'five - 6' }
28+
];
29+
30+
const cols = {
31+
name: 'Repositories',
32+
branches: 'Branches',
33+
prs: 'Pull requests',
34+
workspaces: 'Workspaces',
35+
lastCommit: 'Last commit'
36+
};
37+
38+
const ouiaId = 'LayoutExample';
39+
40+
export const BasicExample: React.FunctionComponent = () => {
41+
const pagination = useDataViewPagination({ perPage: 5 });
42+
const { page, perPage } = pagination;
43+
44+
const data = useMemo(() => repositories.slice((page - 1) * perPage, ((page - 1) * perPage) + perPage), [ page, perPage ]);
45+
46+
return (
47+
<DataView>
48+
<DataViewToolbar pagination={<Pagination ouiaId={`${ouiaId}Header-pagination`} perPageOptions={perPageOptions} itemCount={repositories.length} {...pagination} />} />
49+
<Table aria-label="Repositories table" ouiaId={ouiaId}>
50+
<Thead data-ouia-component-id={`${ouiaId}-thead`}>
51+
<Tr ouiaId={`${ouiaId}-tr-head`}>
52+
{Object.values(cols).map((column, index) => <Th key={index} data-ouia-component-id={`${ouiaId}-th-${index}`}>{column}</Th>)}
53+
</Tr>
54+
</Thead>
55+
<Tbody>
56+
{data.map((repo, rowIndex) => (
57+
<Tr key={repo.name} ouiaId={`${ouiaId}-tr-${rowIndex}`}>
58+
{Object.keys(cols).map((column, colIndex) => <Td key={colIndex} data-ouia-component-id={`${ouiaId}-td-${rowIndex}-${colIndex}`}>{repo[column]}</Td>)}
59+
</Tr>
60+
))}
61+
</Tbody>
62+
</Table>
63+
<DataViewToolbar pagination={<Pagination isCompact ouiaId={`${ouiaId}Footer-pagination`} perPageOptions={perPageOptions} itemCount={repositories.length} {...pagination} />} />
64+
</DataView>
65+
)}

packages/module/patternfly-docs/content/extensions/data-view/examples/Hooks/Hooks.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,4 @@ Data view hooks provide a predefined solution to manage state of the data view.
1717

1818
### useDataViewPagination()
1919

20-
The `useDataViewPagination` hook manages the pagination state of the data view. It retrieves the current `page` and `perPage` values together with functions to set them (`setPage`, `setPerPage`)
21-
22-
Coming soon...
23-
20+
The `useDataViewPagination` hook manages the pagination state of the data view. It retrieves the current `page` and `perPage` values together with functions to set them (`onSetPage`, `onPerPageSelect`). You can easily spread the retrieved values to the PatternFly [pagination](/components/pagination) component and make it live.

packages/module/src/DataView/DataView.test.tsx

Lines changed: 0 additions & 13 deletions
This file was deleted.

packages/module/src/Hooks/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from './useDataViewPagination';
1+
export * from './pagination';
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import '@testing-library/jest-dom';
2+
import { renderHook, act } from '@testing-library/react';
3+
import { useDataViewPagination } from './pagination';
4+
5+
describe('useDataViewPagination', () => {
6+
7+
it('should get initial state correctly - no page', () => {
8+
const { result } = renderHook(() => useDataViewPagination({ perPage: 7 }))
9+
expect(result.current).toEqual({
10+
onPerPageSelect: expect.any(Function),
11+
onSetPage: expect.any(Function),
12+
page: 1,
13+
perPage: 7
14+
})
15+
});
16+
17+
it('should get initial state correctly - page set', () => {
18+
const { result } = renderHook(() => useDataViewPagination({ page: 3, perPage: 5 }))
19+
expect(result.current).toEqual({
20+
onPerPageSelect: expect.any(Function),
21+
onSetPage: expect.any(Function),
22+
page: 3,
23+
perPage: 5
24+
})
25+
});
26+
27+
it('should set page correctly', () => {
28+
const { result } = renderHook(() => useDataViewPagination({ page: 3, perPage: 5 }))
29+
30+
act(() => {
31+
result.current.onSetPage(undefined, 8);
32+
});
33+
34+
expect(result.current).toEqual({
35+
onPerPageSelect: expect.any(Function),
36+
onSetPage: expect.any(Function),
37+
page: 8,
38+
perPage: 5
39+
})
40+
});
41+
42+
it('should set perPage correctly', () => {
43+
const { result } = renderHook(() => useDataViewPagination({ page: 3, perPage: 5 }))
44+
45+
act(() => {
46+
result.current.onPerPageSelect(undefined, 50);
47+
});
48+
49+
expect(result.current).toEqual({
50+
onPerPageSelect: expect.any(Function),
51+
onSetPage: expect.any(Function),
52+
page: 3,
53+
perPage: 50
54+
})
55+
});
56+
57+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { useState } from "react";
2+
3+
export interface UseDataViewPaginationProps {
4+
page?: number;
5+
perPage: number;
6+
}
7+
8+
export interface DataViewPaginationProps extends UseDataViewPaginationProps {
9+
page: number;
10+
}
11+
12+
export const useDataViewPagination = ({ page = 1, perPage }: UseDataViewPaginationProps) => {
13+
const [ state, setState ] = useState({ page, perPage });
14+
15+
const onPerPageSelect = (_event: React.MouseEvent | React.KeyboardEvent | MouseEvent | undefined, newPerPage: number) => {
16+
setState(prev => ({ ...prev, perPage: newPerPage }));
17+
}
18+
19+
const onSetPage = (_event: React.MouseEvent | React.KeyboardEvent | MouseEvent | undefined, newPage: number) => {
20+
setState(prev => ({ ...prev, page: newPage }));
21+
}
22+
23+
return {
24+
...state,
25+
onPerPageSelect,
26+
onSetPage
27+
}
28+
}

packages/module/src/Hooks/useDataViewPagination.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)