import { PureComponent } from 'react' import { createRoot } from 'react-dom/client' import { imgb64 } from '../lib/helpers/tests' import SmartDataTable from '../lib' import '../lib/css/basic.css' const sematicUI = { change: 'ui labeled secondary icon button', changeIcon: 'exchange icon', checkbox: 'ui toggle checkbox', deleteIcon: 'trash red icon', input: 'ui input', iconInput: 'ui icon input', labeledInput: 'ui right labeled input', loader: 'ui active text loader', message: 'ui message', refresh: 'ui labeled primary icon button', refreshIcon: 'sync alternate icon', rowsIcon: 'numbered list icon', searchIcon: 'search icon', segment: 'ui segment', select: 'ui dropdown', table: 'ui compact selectable table', } const generateData = async (numResults = 0) => { const { faker } = await import('@faker-js/faker') let total = numResults || 0 if (typeof numResults === 'string') { total = parseInt(numResults, 10) } const data = [] for (let i = 0; i < total; i += 1) { const row = { _id: i, address: { city: faker.location.city(), state: faker.location.state(), country: faker.location.country(), }, url: faker.internet.url(), isMarried: faker.datatype.boolean(), actions: null, avatar: imgb64, fullName: faker.person.fullName(), _username: faker.internet.username(), password_: faker.internet.password(), 'email.address': faker.internet.email(), phone_number: faker.phone.number(), } // Add random attributes to random rows (after the first) if (i > 0 && faker.datatype.boolean()) { const column = faker.database.column() if (!row[column]) { row[column] = faker.number.int() } } data.push(row) } return data } const emptyTable = (
There is no data available to display.
) const loader =
Loading...
// rowIndex is zero-based, so the 1st row (index 0) is odd const rowClassName = (_row, idx) => (idx % 2 === 0 ? 'odd-row' : 'even-row') const DeleteButton = ({ handleDelete }) => ( ) class AppDemo extends PureComponent { constructor(props) { super(props) this.state = { useApi: false, apiUrl: 'https://randomuser.me/api/?results=100', apiUrlNew: 'https://randomuser.me/api/?results=100', dataKey: 'results', numResults: 10, data: [], dataSampling: 0, filterValue: '', perPage: 0, showOnRowClick: true, changeOrder: false, orderedHeaders: [ '_id', 'avatar', 'fullName', '_username', 'password_', 'email.address', 'phone_number', 'address.city', 'address.state', 'address.country', 'url', 'isMarried', 'actions', ], hideUnordered: false, } this.changeData = this.changeData.bind(this) this.handleCheckboxChange = this.handleCheckboxChange.bind(this) this.handleNewApiUrl = this.handleNewApiUrl.bind(this) this.handleOnChange = this.handleOnChange.bind(this) this.handleOnChangeOrder = this.handleOnChangeOrder.bind(this) this.handleOnPerPage = this.handleOnPerPage.bind(this) this.onRowClick = this.onRowClick.bind(this) this.setNewData = this.setNewData.bind(this) } componentDidMount() { this.setNewData() } async setNewData() { const { numResults } = this.state const data = await generateData(numResults) this.setState({ data }) } handleNewApiUrl() { const { apiUrlNew } = this.state this.setState({ apiUrl: apiUrlNew }) } handleDelete(event, _idx, row) { event.preventDefault() event.stopPropagation() this.setState((prevState) => ({ data: prevState.data.filter((r) => r._id !== row._id), })) } getHeaders() { return { _id: { text: 'Identifier', invisible: true, filterable: false, transform: (value) => `Row #${value + 1}`, }, avatar: { text: 'Profile Pic', sortable: false, filterable: false, }, _username: { invisible: true, }, password_: { invisible: true, }, fullName: { sortable: (a, b) => a.fullName.localeCompare(b.fullName), }, phone_number: { sortable: false, }, 'address.city': { text: 'City', }, 'address.state': { text: 'State', }, 'address.country': { text: 'Country', }, url: { text: 'Web Page', sortable: (a, b) => a.url .replace(/^https?:\/\//, '') .localeCompare(b.url.replace(/^https?:\/\//, '')), }, actions: { text: 'Actions', sortable: false, filterable: false, transform: (value, idx, row) => ( this.handleDelete(e, idx, row)} /> ), }, } } handleOnChange({ target: { name, value } }) { this.setState({ [name]: value }, () => { if (name === 'numResults') this.setNewData() }) } handleOnChangeOrder(now, next) { const { orderedHeaders } = this.state const N = orderedHeaders.length let nextPos = next if (next < 0) { nextPos = N } if (next >= N) { nextPos = 0 } const newOrderedHeaders = [...orderedHeaders] const mvElement = newOrderedHeaders.splice(now, 1)[0] newOrderedHeaders.splice(nextPos, 0, mvElement) this.setState({ orderedHeaders: newOrderedHeaders }) } handleOnPerPage({ target: { name, value } }) { this.setState({ [name]: parseInt(value, 10) }) } changeData() { const { useApi } = this.state this.setState({ useApi: !useApi, filterValue: '', perPage: 0, }) } handleCheckboxChange({ target: { name, checked } }) { this.setState({ [name]: checked }) } onRowClick(event, { rowData, rowIndex, tableData }) { const { showOnRowClick } = this.state if (showOnRowClick) { const { fullName, name, id } = rowData let value = fullName || name || id if (!value) { const [key] = Object.keys(rowData) value = `${key}: ${rowData[key]}` } window.alert(`You clicked ${value}'s row !`) } else { // The following results should be identical console.log(rowData, tableData[rowIndex]) } } render() { const { apiUrl, apiUrlNew, changeOrder, data, dataKey, dataSampling, filterValue, hideUnordered, numResults, orderedHeaders, perPage, showOnRowClick, useApi, } = this.state const divider = const headers = this.getHeaders() return ( <>
{divider} {divider} {!useApi && ( <> {divider} )} {!useApi && ( {divider}
)} {divider}
{divider} {!useApi && (
)} {divider} {!useApi && ( )}
{useApi && (
{divider}
{divider}
)} {changeOrder && (
{orderedHeaders.map((header, idx) => (
{header}
))}
)}

{useApi ? 'While using async data, the state is controlled internally by the table' : `Total rows in the table: ${data.length}`}

{useApi && ( )} {!useApi && ( )} ) } } const container = document.getElementById('app') const root = createRoot(container) root.render()