Skip to content
Snippets Groups Projects

Resolve TMSS-298

Merged Ramesh Kumar requested to merge TMSS-298 into master
Files
7
import React, {useRef } from "react";
import React, {useRef, useState } from "react";
import { useSortBy, useTable, useFilters, useGlobalFilter, useAsyncDebounce, usePagination } from 'react-table'
import matchSorter from 'match-sorter'
import _ from 'lodash';
import moment from 'moment';
import { useHistory } from "react-router-dom";
import {OverlayPanel} from 'primereact/overlaypanel';
import {InputSwitch} from 'primereact/inputswitch';
import { Calendar } from 'primereact/calendar';
import {Paginator} from 'primereact/paginator';
let tbldata =[];
let isunittest = false;
@@ -16,7 +18,6 @@ function GlobalFilter({
globalFilter,
setGlobalFilter,
}) {
const [value, setValue] = React.useState(globalFilter)
const onChange = useAsyncDebounce(value => {setGlobalFilter(value || undefined)}, 200)
return (
@@ -46,10 +47,173 @@ function DefaultColumnFilter({
)
}
// This is a custom filter UI for selecting
// a unique option from a list
function SelectColumnFilter({
column: { filterValue, setFilter, preFilteredRows, id },
}) {
// Calculate the options for filtering
// using the preFilteredRows
const options = React.useMemo(() => {
const options = new Set()
preFilteredRows.forEach(row => {
options.add(row.values[id])
})
return [...options.values()]
}, [id, preFilteredRows])
// Render a multi-select box
return (
<select
value={filterValue}
onChange={e => {
setFilter(e.target.value || undefined)
}}
>
<option value="">All</option>
{options.map((option, i) => (
<option key={i} value={option}>
{option}
</option>
))}
</select>
)
}
// This is a custom filter UI that uses a
// slider to set the filter value between a column's
// min and max values
function SliderColumnFilter({
column: { filterValue, setFilter, preFilteredRows, id },
}) {
// Calculate the min and max
// using the preFilteredRows
const [min, max] = React.useMemo(() => {
let min = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
let max = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
preFilteredRows.forEach(row => {
min = Math.min(row.values[id], min)
max = Math.max(row.values[id], max)
})
return [min, max]
}, [id, preFilteredRows])
return (
<>
<input
type="range"
min={min}
max={max}
value={filterValue || min}
onChange={e => {
setFilter(parseInt(e.target.value, 10))
}}
/>
<button onClick={() => setFilter(undefined)}>Off</button>
</>
)
}
// This is a custom filter UI that uses a
// switch to set the value
function BooleanColumnFilter({
column: { setFilter},
}) {
const [value, setValue] = useState(true);
return (
<>
<InputSwitch checked={value} onChange={() => { setValue(!value); setFilter(!value); }} />
<button onClick={() => setFilter(undefined)}>Off</button>
</>
)
}
// This is a custom filter UI that uses a
// calendar to set the value
function CalendarColumnFilter({
column: { setFilter},
}) {
const [value, setValue] = useState('');
return (
<>
<Calendar value={value} onChange={(e) => {
const value = moment(e.value, moment.ISO_8601).format("YYYY-MMM-DD")
setValue(value); setFilter(value);
}} showIcon></Calendar>
<button onClick={() => setFilter(undefined)}>Off</button>
</>
)
}
// This is a custom UI for our 'between' or number range
// filter. It uses two number boxes and filters rows to
// ones that have values between the two
function NumberRangeColumnFilter({
column: { filterValue = [], preFilteredRows, setFilter, id },
}) {
const [min, max] = React.useMemo(() => {
let min = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
let max = preFilteredRows.length ? preFilteredRows[0].values[id] : 0
preFilteredRows.forEach(row => {
min = Math.min(row.values[id], min)
max = Math.max(row.values[id], max)
})
return [min, max]
}, [id, preFilteredRows])
return (
<div
style={{
display: 'flex',
}}
>
<input
value={filterValue[0] || ''}
type="number"
onChange={e => {
const val = e.target.value
setFilter((old = []) => [val ? parseInt(val, 10) : undefined, old[1]])
}}
placeholder={`Min (${min})`}
style={{
width: '70px',
marginRight: '0.5rem',
}}
/>
to
<input
value={filterValue[1] || ''}
type="number"
onChange={e => {
const val = e.target.value
setFilter((old = []) => [old[0], val ? parseInt(val, 10) : undefined])
}}
placeholder={`Max (${max})`}
style={{
width: '70px',
marginLeft: '0.5rem',
}}
/>
</div>
)
}
function fuzzyTextFilterFn(rows, id, filterValue) {
return matchSorter(rows, filterValue, { keys: [row => row.values[id]] })
}
const filterTypes = {
'select': SelectColumnFilter,
'switch': BooleanColumnFilter,
'slider': SliderColumnFilter,
'date': CalendarColumnFilter,
'range': NumberRangeColumnFilter
};
// Let the table remove the filter if the string is empty
fuzzyTextFilterFn.autoRemove = val => !val
@@ -65,7 +229,7 @@ const IndeterminateCheckbox = React.forwardRef(
)
// Our table component
function Table({ columns, data, defaultheader, optionalheader }) {
function Table({ columns, data, defaultheader, optionalheader, defaultSortColumn }) {
const filterTypes = React.useMemo(
() => ({
// Add a new fuzzyTextFilterFn filter type.
@@ -103,26 +267,21 @@ function Table({ columns, data, defaultheader, optionalheader }) {
allColumns,
getToggleHideAllColumnsProps,
state,
page,
preGlobalFilteredRows,
setGlobalFilter,
setHiddenColumns,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
defaultColumn,
filterTypes,
initialState: { pageIndex: 0 }
initialState: { pageIndex: 0,
sortBy: defaultSortColumn }
},
useFilters,
useGlobalFilter,
@@ -138,9 +297,19 @@ function Table({ columns, data, defaultheader, optionalheader }) {
let op = useRef(null);
const [currentpage, setcurrentPage] = React.useState(0);
const [currentrows, setcurrentRows] = React.useState(10);
const onPagination = (e) => {
gotoPage(e.page);
setcurrentPage(e.first);
setcurrentRows(e.rows);
setPageSize(e.rows)
};
return (
<>
<div id="block_container" style={{ display: 'flex', verticalAlign: 'middle', marginTop:'20px'}}>
<div id="block_container">
<div style={{textAlign:'left', marginRight:'30px'}}>
<i className="fa fa-columns col-filter-btn" label="Toggle Columns" onClick={(e) => op.current.toggle(e)} />
<OverlayPanel ref={op} id="overlay_panel" showCloseIcon={false} >
@@ -156,7 +325,8 @@ function Table({ columns, data, defaultheader, optionalheader }) {
</div>
{allColumns.map(column => (
<div key={column.id} style={{'display':column.id !== 'actionpath'?'block':'none'}}>
<input type="checkbox" {...column.getToggleHiddenProps()} /> {(defaultheader[column.id])?defaultheader[column.id]:(optionalheader[column.id]?optionalheader[column.id]:column.id)}
<input type="checkbox" {...column.getToggleHiddenProps()} /> {
(defaultheader[column.id]) ? defaultheader[column.id] : (optionalheader[column.id] ? optionalheader[column.id] : column.id)}
</div>
))}
<br />
@@ -178,26 +348,29 @@ function Table({ columns, data, defaultheader, optionalheader }) {
</div>
</div>
<div style={{overflow: 'auto', padding: '0.75em',}}>
<table {...getTableProps()} style={{width:'100%'}} data-testid="viewtable" className="viewtable" >
<div className="table_container">
<table {...getTableProps()} data-testid="viewtable" className="viewtable" >
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps(column.getSortByToggleProps())} >
<th>
<div {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.Header !== 'actionpath' && column.render('Header')}
{column.Header !== 'Action'?
column.isSorted ? (column.isSortedDesc ? <i className="pi pi-sort-down" aria-hidden="true"></i> : <i className="pi pi-sort-up" aria-hidden="true"></i>) : <i className="pi pi-sor" aria-hidden="true"></i>
column.isSorted ? (column.isSortedDesc ? <i className="pi pi-sort-down" aria-hidden="true"></i> : <i className="pi pi-sort-up" aria-hidden="true"></i>) : ""
: ""
}
{/* Render the columns filter UI */}
</div>
{/* Render the columns filter UI */}
{column.Header !== 'actionpath' &&
<div className={columnclassname[0][column.Header]} >
{column.canFilter && column.Header !== 'Action' ? column.render('Filter') : null}
</div>
}
</th>
</th>
))}
</tr>
))}
@@ -209,7 +382,6 @@ function Table({ columns, data, defaultheader, optionalheader }) {
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
if(cell.column.id !== 'actionpath')
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
@@ -217,40 +389,9 @@ function Table({ columns, data, defaultheader, optionalheader }) {
})}
</tbody>
</table>
</div>
<div className="pagination" style={{marginTop:"10px"}}>
<button onClick={() => gotoPage(0)} disabled={!canPreviousPage} title="Go to first page">
{'<<'}
</button>{' '}
<button onClick={() => previousPage()} disabled={!canPreviousPage} title="Go to previous page">
{'<'}
</button>{' '}
<span style={{marginLeft:"5px"}}>
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</span>
<button onClick={() => nextPage()} disabled={!canNextPage} title="Go to next page">
{'>'}
</button>{' '}
<button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage} title="Go to last page">
{'>>'}
</button>{' '}
<select
style={{marginLeft:"3px"}}
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value))
}}
>
{[10, 20, 30, 40, 50].map(pageSize => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>
<div className="pagination">
<Paginator rowsPerPageOptions={[10,25,50,100]} first={currentpage} rows={currentrows} totalRecords={rows.length} onPageChange={onPagination}></Paginator>
</div>
</>
)
@@ -281,12 +422,16 @@ function ViewTable(props) {
// Default Header to show in table and other columns header will not show until user action on UI
let defaultheader = props.defaultcolumns;
let optionalheader = props.optionalcolumns;
let defaultSortColumn = props.defaultSortColumn;
if(!defaultSortColumn){
defaultSortColumn =[{}];
}
let columns = [];
let defaultdataheader = Object.keys(defaultheader[0]);
let optionaldataheader = Object.keys(optionalheader[0]);
if(props.showaction === 'true'){
if(props.showaction === 'true') {
columns.push({
Header: 'Action',
id:'Action',
@@ -311,12 +456,14 @@ function ViewTable(props) {
}
//Default Columns
defaultdataheader.forEach(header =>{
defaultdataheader.forEach(header => {
const isString = typeof defaultheader[0][header] === 'string';
columns.push({
Header: defaultheader[0][header],
id: defaultheader[0][header],
Header: isString ? defaultheader[0][header] : defaultheader[0][header].name,
id: isString ? defaultheader[0][header] : defaultheader[0][header].name,
accessor: header,
filter: 'fuzzyText',
filter: (!isString && defaultheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText',
Filter: isString ? DefaultColumnFilter : (filterTypes[defaultheader[0][header].filter] ? filterTypes[defaultheader[0][header].filter] : DefaultColumnFilter),
isVisible: true,
Cell: props => <div> {updatedCellvalue(header, props.value)} </div>,
})
@@ -324,11 +471,13 @@ function ViewTable(props) {
//Optional Columns
optionaldataheader.forEach(header => {
const isString = typeof optionalheader[0][header] === 'string';
columns.push({
Header: optionalheader[0][header],
id: header,
Header: isString ? optionalheader[0][header] : optionalheader[0][header].name,
id: isString ? optionalheader[0][header] : optionalheader[0][header].name,
accessor: header,
filter: 'fuzzyText',
filter: (!isString && optionalheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText',
Filter: isString ? DefaultColumnFilter : (filterTypes[optionalheader[0][header].filter] ? filterTypes[optionalheader[0][header].filter] : DefaultColumnFilter),
isVisible: false,
Cell: props => <div> {updatedCellvalue(header, props.value)} </div>,
})
@@ -362,11 +511,10 @@ function ViewTable(props) {
return value;
}
return (
<div>
<Table columns={columns} data={tbldata} defaultheader={defaultheader[0]} optionalheader={optionalheader[0]} />
<Table columns={columns} data={tbldata} defaultheader={defaultheader[0]} optionalheader={optionalheader[0]}
defaultSortColumn={defaultSortColumn} />
</div>
)
}
Loading