Skip to content

Commit

Permalink
Adds generic DataTable component with a custom useDataTable hook
Browse files Browse the repository at this point in the history
  • Loading branch information
Cemal Türkoglu committed Oct 17, 2020
1 parent 5c6f738 commit 1694602
Show file tree
Hide file tree
Showing 5 changed files with 294 additions and 2 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"import/extensions": 0,
"babel/object-curly-spacing": 0,
"react/prop-types": 0,
"no-console": "off"
"no-console": "off",
"no-unused-vars": "off"
},
"env": {
"es6": true,
Expand Down
58 changes: 58 additions & 0 deletions src/component/ActionMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import { Dropdown, Menu, Popconfirm } from 'antd';
import {
DeleteOutlined,
DownOutlined,
EditOutlined,
QuestionCircleOutlined,
} from '@ant-design/icons';
import { useHistory } from 'react-router-dom';

function useActionMenu({ selectedRow, updateEntityPath }) {
const history = useHistory();

const handleMenuClick = action => {
if (action.key === 'edit') {
const updatePath = '/' + updateEntityPath + '/' + selectedRow.id;
history.push(updatePath);
}
};

const handleSingleDelete = () => {
console.log('handleSingleDelete, selected:', selectedRow);
};

const actionMenu = (
<Menu onClick={handleMenuClick}>
<Menu.Item key="edit">
<EditOutlined />
Update
</Menu.Item>
<Menu.Item key="delete">
<Popconfirm
title="Sure to delete?"
placement="left"
icon={<QuestionCircleOutlined style={{ color: 'red' }} />}
onConfirm={handleSingleDelete}
>
<DeleteOutlined type="delete" />
Delete
</Popconfirm>
</Menu.Item>
</Menu>
);

const actionColumnView = (
<span>
<Dropdown overlay={actionMenu} trigger={['click']}>
<a className="ant-dropdown-link" href="#">
Actions <DownOutlined />
</a>
</Dropdown>
</span>
);

return [actionColumnView];
}

export default useActionMenu;
88 changes: 88 additions & 0 deletions src/component/DataTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useEffect, useState } from 'react';
import { Table } from 'antd';
import useActionMenu from './ActionMenu';

const DEFAULT_PAGE_SIZE = 10;
const DEFAULT_PAGE_NUMBER = 0;

function useDataTable({ columns, dataSource, updateEntityPath }) {
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [selectedRow, setSelectedRow] = useState(null);
const [currentPage, setCurrentPage] = useState(DEFAULT_PAGE_NUMBER);
const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE);
const [actionColumnView] = useActionMenu({ selectedRow, updateEntityPath });

const hasSelected = selectedRowKeys.length > 0;

const rowSelection = {
selectedRowKeys,
onChange: selected => {
setSelectedRowKeys(selected);
},
};

const updatedColumns = [
...columns,
{
title: 'Action',
key: 'action',
render: () => actionColumnView,
},
];

useEffect(() => {
console.log('columns:', columns);
console.log('datasoure:', dataSource);
console.log('updateColumns:', updatedColumns);
});

const handleSingleDelete = () => {
console.log('handleSingleDelete, selected:', selectedRow);
};

const resetPagination = () => {
setCurrentPage(DEFAULT_PAGE_NUMBER);
};

const handleTableChange = pagination => {
console.log('pagination:', pagination);
setCurrentPage(pagination.current - 1);
};

const DataTable = () => (
<Table
rowKey={record => record.id}
rowSelection={rowSelection}
columns={updatedColumns}
dataSource={dataSource.content}
onRow={record => {
return {
onClick: () => {
setSelectedRow(record);
},
};
}}
onChange={handleTableChange}
pagination={{
pageSize: DEFAULT_PAGE_SIZE,
current: currentPage + 1,
total: dataSource.totalElements,
showTotal: (total, range) => {
return `${range[0]}-${range[1]} of ${total} items`;
},
}}
/>
);

return {
DataTable,
hasSelected,
selectedRow,
selectedRowKeys,
currentPage,
pageSize,
resetPagination,
};
}

export default useDataTable;
125 changes: 125 additions & 0 deletions src/page/product/Constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import React from 'react';
import { Tag } from 'antd';

export const columns = [
{
title: 'Id',
dataIndex: 'key',
key: 'key',
},
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: text => <a>{text}</a>,
},
{
title: 'Description',
dataIndex: 'description',
key: 'description',
},
{
title: 'Quantity',
dataIndex: 'qty',
key: 'qty',
},
{
title: 'owner',
dataIndex: 'owner',
key: 'owner',
},
{
title: 'Category',
key: 'category',
dataIndex: 'category',
render: tags => (
<>
{tags.map(tag => {
let color = 'blue';
if (tag === 'accessory') {
color = 'volcano';
} else if (tag === 'clothing') {
color = 'geekblue';
} else if (tag === 'jewellery') {
color = 'green';
}
return (
<Tag color={color} key={tag}>
{tag.toUpperCase()}
</Tag>
);
})}
</>
),
},
];

export const data = {
totalElements: 8,
content: [
{
key: '1',
name: 'Personalized Bar Bracelet',
description: 'This is a metal bracelet',
qty: 32,
owner: 'John Brown',
category: ['jewellery', 'accessory'],
},
{
key: '2',
name: 'Handcraft Boots',
description: 'Vegan-friendly leather',
qty: 12,
owner: 'John Green',
category: ['clothing', 'living'],
},
{
key: '3',
name: 'Personalized Bar Bracelet',
description: 'This is a metal bracelet',
qty: 32,
owner: 'John Brown',
category: ['jewellery', 'clothing'],
},
{
key: '4',
name: 'Winter Hat',
description: 'Unisex wool hat',
qty: 21,
owner: 'John Smith',
category: ['clothing', 'home'],
},
{
key: '5',
name: 'Personalized Bar Bracelet',
description: 'This is a metal bracelet',
qty: 32,
owner: 'John Brown',
category: ['jewellery', 'clothing'],
},
{
key: '6',
name: 'Handcraft Boots',
description: 'Vegan-friendly leather',
qty: 12,
owner: 'John Green',
category: ['clothing', 'accessory'],
},
{
key: '7',
name: 'Personalized Bar Bracelet',
description: 'This is a metal bracelet',
qty: 32,
owner: 'John Brown',
category: ['jewellery', 'clothing'],
},
{
key: '8',
name: 'Winter Hat',
description: 'Unisex wool hat',
qty: 21,
owner: 'John Smith',
category: ['clothing', 'accessory'],
},
],
};
22 changes: 21 additions & 1 deletion src/page/product/ShowProducts.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
import React from 'react';
import Header from '../../component/Header';
import useDataTable from '../../component/DataTable';
import * as constants from './Constants';

function ShowProducts() {
return <div>Product Page</div>;
const {
DataTable,
hasSelected,
currentPage,
pageSize,
resetPagination,
} = useDataTable({
columns: constants.columns,
dataSource: constants.data,
updateEntityPath: 'update-product',
});

return (
<>
<Header addNewPath="add-product" hasSelected={hasSelected} />
<DataTable />
</>
);
}

export default ShowProducts;

0 comments on commit 1694602

Please sign in to comment.