import React, { useRef, useState } from "react"; import { useFlexLayout , useResizeColumns, useSortBy, useTable, useFilters, useGlobalFilter, useAsyncDebounce, usePagination, useRowSelect, useColumnOrder } from 'react-table' import matchSorter from 'match-sorter' import _, { filter } from 'lodash'; import moment from 'moment'; import { useHistory } from "react-router-dom"; import { OverlayPanel } from 'primereact/overlaypanel'; import { InputMask } from 'primereact/inputmask'; import { InputText } from 'primereact/inputtext'; import { Calendar } from 'primereact/calendar'; import { Paginator } from 'primereact/paginator'; import { TriStateCheckbox } from 'primereact/tristatecheckbox'; import { Slider } from 'primereact/slider'; import { Button } from "react-bootstrap"; import { Link } from "react-router-dom"; import { InputNumber } from "primereact/inputnumber"; import { MultiSelect } from 'primereact/multiselect'; import { RadioButton } from 'primereact/radiobutton'; import { useExportData } from "react-table-plugins"; import { ProgressBar } from 'primereact/progressbar'; import {Checkbox} from 'primereact/checkbox'; import { Dropdown } from 'primereact/dropdown'; import "flatpickr/dist/flatpickr.css"; import Flatpickr from "react-flatpickr"; import confirmDatePlugin from "flatpickr/dist/plugins/confirmDate/confirmDate"; import shortcutButtonsPlugin from "shortcut-buttons-flatpickr"; import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd"; import UtilService from '../../src/services/util.service' import Papa from "papaparse"; import JsPDF from "jspdf"; import "jspdf-autotable"; import TableUtil from "../utils/table.util"; import Validator from "../utils/validator" let tblinstance; let tableInstanceRef; let doServersideFilter = false; let tbldata = [], filteredData = []; let data = []; let selectedRows = []; let isunittest = false; let showTopTotal = true; let showGlobalFilter = true; let showColumnFilter = true; let allowColumnSelection = true; let allowRowSelection = false; let columnclassname = []; let parentCallbackFunction, parentCBonSelection; let showCSV = false; let multiSelectOption = {}; let filterCallback = null; let clearAllFuncCallback = null; let tableOptionsState = null; let tableToolTipsState = {}; let setLoaderFunction = null; let showFilterOption = null; let hasFilters = false; let loadingStatus = false; let tmpTableData = null; let currentTableName = null; let storeFilter = false; let storage_array = []; let dragged = null; let reorder = []; //let confirmDatePlugin = new confirmDatePlugin(); // Define a default UI for filtering let fixedColumns = ['Select', 'Action', 'Status Logs', 'View Summary']; const getItemStyle = ({ isDragging, isDropAnimating }, draggableStyle) => ({ ...draggableStyle, // some basic styles to make the items look a bit nicer userSelect: "none", cursor: isDragging? 'move': 'move', ...(!isDragging && { transform: "translate(0,0)" }), ...(isDropAnimating && { transitionDuration: "0.001s" }) // styles we need to apply on draggables }); function GlobalFilter({ preGlobalFilteredRows, globalFilter, setGlobalFilter, }) { const [value, setValue] = React.useState(globalFilter) const onChange = useAsyncDebounce(value => { setGlobalFilter(value || undefined) }, 200) return ( <span style={{ marginLeft: "-10px" }}> <input value={value || ""} onChange={e => { setValue(e.target.value); onChange(e.target.value); }} /> {" "}<i className="fa fa-search"></i> </span> ) } // Define a default UI for filtering function DefaultColumnFilter({ column: { filterValue, preFilteredRows, setFilter, filteredRows, Header }, }) { const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(''); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if (filterValue) { setFiltered(true); } if(!value){ setValue(filterValue); setFilter(filterValue); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; if (isCleared) { hasFilters = false; if (filtered) { _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); filterCallback(tableOptionsState, setLoaderFunction); } } else { filterCallback(tableOptionsState, setLoaderFunction); } }; return ( <> <div className="table-filter" onClick={e => { e.stopPropagation() }} style={{marginRight: '5px'}}> <input title={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter few characters and press ‘Enter’ key to search"} value={value} //***TO REMOVE - INCOMING CHANGE WAS value={filterValue || ''} onChange={e => { setValue(e.target.value); setFilter(e.target.value || undefined) // Set undefined to remove the filter entirely if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, e.target.value); } }} onKeyUp={(e) => { if (e.key === "Enter" && doServersideFilter) { setFiltered(true); callServerFilter(e); } }} /> {value && <i className="table-reset fa fa-times" style={{cursor: 'pointer'}} title="Clear the filter" onClick={(e) => { setFilter(undefined); setValue(''); setFiltered(false); if (doServersideFilter) { setFilter(undefined); setValue(''); callServerFilter(e, true); } if(storeFilter){ TableUtil.saveFilter(currentTableName, Header, ''); } }} /> } </div> </> ) } const setStoreData = (id, value) => { debugger let localstorage_key = window.location.pathname.split('/')[1]; let storage = UtilService.localStore({ type: 'get', key: localstorage_key }); if(storage && storage.length > 0) { storage.forEach(function(value, index) { if(value.name === id) { value.name = id value.value = value } }); const selected = _.filter(storage, function (filter) { if ( filter.name === id) { return true; } }) if(selected.length <= 0) { storage.push({name: id, value: value}) } } else { storage = [{name: id, value: value}] } UtilService.localStore({ type: 'set', key: localstorage_key, value: storage }); } /* Generate and download csv */ function getExportFileBlob({ columns, data, fileType, fileName }) { if (fileType === "csv") { // CSV download const headerNames = columns.map((col) => col.exportValue); // remove actionpath column in csv export var index = headerNames.indexOf('actionpath'); if (index > -1) { headerNames.splice(index, 1); } const csvString = Papa.unparse({ fields: headerNames, data }); return new Blob([csvString], { type: "text/csv" }); } //PDF download else if (fileType === "pdf") { const headerNames = columns.map((column) => column.exportValue); const doc = new JsPDF(); var index = headerNames.indexOf('Action'); if (index > -1) { headerNames.splice(index, 1); } doc.autoTable({ head: [headerNames], body: data, }); doc.save(`${fileName}.pdf`); return false; } } /** * Custom filter UI for selecting a unique option from a list. * option values are getting from callback funtion or from the table data. * @param {*} param0 * @returns */ function SelectColumnFilter({ column: { filterValue, setFilter, preFilteredRows, id, Header }, }) { const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); const [rowData, setRowData] = useState(null); React.useEffect(() => { if (!filterValue && value) { setValue(''); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); setValue(filterValue); setFilter(filterValue); } }, [filterValue, value]); const options = React.useMemo(() => { let options = null; if (showFilterOption) { options = new Set(showFilterOption(id)); } if (options === null || options.size === 0) { options = new Set(); if (preFilteredRows || rowData) { preFilteredRows = preFilteredRows ? preFilteredRows : rowData; setRowData(preFilteredRows); preFilteredRows.forEach(row => { options.add(row.values[id]) }); } } return [...options.values()] }, [id, preFilteredRows]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); if (isCleared) { hasFilters = false; //if (filtered) { filterCallback(tableOptionsState, setLoaderFunction); //} } else { tableOptionsState.filters.push({id: Header, value: event.target.value}); filterCallback(tableOptionsState, setLoaderFunction); } }; // Render a multi-select box return ( <div onClick={e => { e.stopPropagation() }}> <select title={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Select a value from list to search"} // className= {columnclassname[0][Header]} style={{ height: '24.2014px', border: '1px solid lightgrey', }} value={value} onChange={e => { setValue(e.target.value); setFilter(e.target.value || undefined); if (doServersideFilter) { if (e.target.value === '' || e.target.value === 'All') { hasFilters = false; setFiltered(false); setFilter(undefined); setValue(''); callServerFilter(e, true); } else { setFiltered(true); callServerFilter(e, false); } } if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, e.target.value); } }} > <option value="">All</option> {options.map((option, i) => ( <option key={i} value={option}> {_.startCase(option)} </option> ))} </select> </div> ) } // Multi-Select Custom Filter and set unique options value function MultiSelectColumnFilter({ column: { filterValue, setFilter, preFilteredRows, id, Header }, }) { const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); const [filtertype, setFiltertype] = useState('Any'); React.useEffect(() => { if (!filterValue && value) { setValue(''); setFiltertype('Any'); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); const filterType = TableUtil.getFilter(currentTableName, 'stationFilterType'); if(filterValue && !value){ setValue(filterValue); setFilter(filterValue); setFiltertype(filterType); multiSelectOption[Header] = filterType; } } }, [filterValue, value, filtertype]); // Set Any / All Filter type const setSelectTypeOption = (option) => { setFiltertype(option); multiSelectOption[Header] = option if (value !== '') { if (storeFilter) { TableUtil.saveFilter(currentTableName, 'stationFilterType', option); } setFilter(value); } }; /** * Trigger server side data fetch in parent component * @param {*} e */ function callSearchFunc(e) { callServerFilter(e); } // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; tableOptionsState.filters.push({id: 'stationFilterType', value: filtertype}); if (isCleared) { hasFilters = false; if (filtered) { _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); filterCallback(tableOptionsState, setLoaderFunction); } } else { filterCallback(tableOptionsState, setLoaderFunction); } }; multiSelectOption[Header] = filtertype; const options = React.useMemo(() => { let options = new Set(); if (showFilterOption) { return showFilterOption(id); } preFilteredRows.forEach(row => { row.values[id].split(',').forEach(value => { if (value !== '') { let hasValue = false; options.forEach(option => { if (option.name === value) { hasValue = true; } }); if (!hasValue) { let option = { 'name': value, 'value': value }; options.add(option); } } }); }); return [...options.values()] }, [id, preFilteredRows]); // Render a multi-select box return ( <div onClick={e => { e.stopPropagation() }} > <div className="p-field-radiobutton"> <RadioButton inputId="filtertype1" name="filtertype" value="Any" onChange={(e) => setSelectTypeOption(e.value)} checked={filtertype === '' || filtertype === 'Any'} tooltip= "Search the row if the Station contains at least one of the selected value" /> <label htmlFor="filtertype1">Any</label> </div> <div className="p-field-radiobutton"> <RadioButton inputId="filtertype2" name="filtertype" value="All" onChange={(e) => setSelectTypeOption(e.value)} checked={filtertype === 'All'} tooltip= "Search the row if the Station contains all of the selected value" /> <label htmlFor="filtertype2">All</label> </div> <div style={{ position: 'relative', display: 'flex'}} > <MultiSelect data-testid="multi-select" id="multi-select" optionLabel="value" optionValue="value" filter={true} value={value} options={options} onChange={e => { setValue(e.target.value); setFilter(e.target.value || undefined); setFiltertype(filtertype); setFiltered(true); if(storeFilter) { if (e.target.value.length > 0) { TableUtil.saveFilter(currentTableName, Header, e.target.value); TableUtil.saveFilter(currentTableName, `${Header}-FilterOption`, filtertype); } else { TableUtil.clearColumnFilter(currentTableName, Header); TableUtil.clearColumnFilter(currentTableName, `${Header}-FilterOption`); } } }} maxSelectedLabels="1" selectedItemsLabel="{0} Selected" className="multi-select" tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Select one or more value from list to search"} style={{width: '95%'}} /> {doServersideFilter && <button className="p-link" onClick={callSearchFunc} > <i className="pi pi-search search-btn" /> </button> } </div> </div> ) } // Multi-Select Custom Filter and set unique options value function MultiSelectFilter({ column: { filterValue, setFilter, preFilteredRows, id, Header }, }) { const [value, setValue] = useState(''); const [filtertype, setFiltertype] = useState('Any'); const [filtered, setFiltered] = useState(false); function callSearchFunc(e) { callServerFilter(e); } React.useEffect(() => { if (!filterValue && value) { setValue(''); setFiltertype('Any'); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if(filterValue && !value){ setValue(filterValue); setFilter(filterValue); setFiltertype(filtertype); } } }, [filterValue, value, filtertype]); multiSelectOption[Header] = filtertype; const options = React.useMemo(() => { let options = new Set(); if (showFilterOption) { return showFilterOption(id); } preFilteredRows.forEach(row => { row.values[id].split(',').forEach(value => { if (value !== '') { let hasValue = false; options.forEach(option => { if (option.name === value) { hasValue = true; } }); if (!hasValue) { let option = { 'name': value, 'value': value }; options.add(option); } } }); }); return [...options.values()] }, [id, preFilteredRows]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; if (isCleared) { hasFilters = false; if (filtered) { _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); filterCallback(tableOptionsState, setLoaderFunction); } } else { filterCallback(tableOptionsState, setLoaderFunction); } }; // Render a multi-select box return ( <div onClick={e => { e.stopPropagation()}}> <div style={{ position: 'relative', display: 'flex'}} > <MultiSelect data-testid="multi-select" id="multi-select" optionLabel="name" optionValue="value" filter //={!doServersideFilter} value={value} options={options} onChange={e => { setValue(e.target.value); setFilter(e.target.value || undefined); if(storeFilter) { if (e.target.value.length > 0) { TableUtil.saveFilter(currentTableName, Header, e.target.value); } else { TableUtil.clearColumnFilter(currentTableName, Header); } } setFiltered(true); //callServerFilter(e); }} maxSelectedLabels="1" selectedItemsLabel="{0} Selected" className="multi-select" tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Select one or more value from list and click search icon to search"} style={{width: '85%'}} /> {doServersideFilter && <div> <button className="p-link" onClick={callSearchFunc} > <i className="pi pi-search search-btn" /> </button> </div> } </div> </div> ) } // 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, Header }, }) { // Calculate the min and max // using the preFilteredRows const [value, setValue] = useState(0); React.useEffect(() => { if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if (filterValue && !value) { setValue(filterValue); setFilter(filterValue); } } }); return ( <div onClick={e => { e.stopPropagation() }} className="table-slider"> <Slider value={value} onChange={(e) => { setFilter(e.value); setValue(e.value); if (storeFilter) { TableUtil.saveFilter(currentTableName, Header, e.value); } }} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Select range value to search"} /> </div> ) } // This is a custom filter UI that uses a // switch to set the value function BooleanColumnFilter({ column: { setFilter, filterValue, Header }, }) { // Calculate the min and max // using the preFilteredRows const [value, setValue] = useState(null); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(null); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if(filterValue && !value){ setValue(filterValue); setFilter(filterValue); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (isCleared) => { hasFilters = true; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); if (isCleared == null) { setFiltered(false); } else if (isCleared) { hasFilters = false; tableOptionsState.filters.push({id: Header, value: true}); setFiltered(true); setValue(true); } else { setFiltered(true); setValue(false); tableOptionsState.filters.push({id: Header, value: false}); } filterCallback(tableOptionsState, setLoaderFunction); }; return ( <div onClick={e => { e.stopPropagation() }}> <TriStateCheckbox value={value} style={{ 'width': '15px', 'height': '24.2014px' }} on onChange={(e) => { setValue(e.target.value); setFilter(e.target.value || undefined); setFiltered(true); if (storeFilter) { TableUtil.saveFilter(currentTableName, Header, e.target.value); } if (doServersideFilter) { callServerFilter(e.value); } }} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Select checkbox (True/False/None) to search"} /> </div> ) } // This is a custom filter UI that uses a // calendar to set the valueCalendar function ColumnFilter({ column: { setFilter, filterValue, Header }, }) { // Calculate the min and max // using the preFilteredRows const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(null); } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; if (isCleared) { hasFilters = false; if (filtered) { _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); filterCallback(tableOptionsState, setLoaderFunction); } } else { filterCallback(tableOptionsState, setLoaderFunction); } }; return ( <div className="table-filter" onClick={e => { e.stopPropagation() }}> <Calendar value={filterValue} appendTo={document.body} dateFormat="yy-mm-dd" onChange={(e) => { const value = moment(e.value).format('YYYY-MM-DD') setValue(value); setFilter(e.value); if (value !== 'Invalid date' && doServersideFilter) { setFiltered(true); callServerFilter(e); } }} showIcon></Calendar> {value && <i onClick={(e) => { setFilter(undefined); setValue(''); setFiltered(false); if (doServersideFilter) { setFilter(undefined); setValue(''); callServerFilter(e, true); } }} className="tb-cal-reset fa fa-times" />} </div> ) } // This is a custom filter UI that uses a // calendar range to set the value function DateRangeColumnFilter({ column: { setFilter, filterValue, Header }, }) { // Calculate the min and max // using the preFilteredRows const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(null); } if (storeFilter) { const filter = TableUtil.getFilter(currentTableName, Header); const filterValue = _.map(filter, date => {return new Date(date)} ) if (filterValue[1] && !value ){ setValue(filterValue); setFilter(filterValue); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (value, isCleared) => { hasFilters = true; if (isCleared) { hasFilters = false; if (filtered) { _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); filterCallback(tableOptionsState, setLoaderFunction); } } else { let filterColumn = _.find(tableOptionsState.filters, {id: Header }); if(filterColumn) { filterColumn.value = value; filterCallback(tableOptionsState, setLoaderFunction); } else { filterCallback(tableOptionsState, setLoaderFunction); } } }; return ( <div className="table-filter" onClick={e => { e.stopPropagation() }}> <Calendar selectionMode="range" value={filterValue} appendTo={document.body} placeholder="Range" onChange={(e) => { setValue(e.value); setFilter(e.value); if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, e.target.value); } if ((value !== '' && value !== 'Invalid date' ) && doServersideFilter) { setFiltered(true); callServerFilter(e.target.value); } }} showIcon></Calendar> {value && <i onClick={(e) => { setFilter(undefined); setValue([]); setFiltered(false); if(storeFilter){ TableUtil.saveFilter(currentTableName, Header, [] ); } if (doServersideFilter) { setFilter(undefined); setValue(''); callServerFilter(e.target.value, true); } }} className="tb-cal-reset fa fa-times" />} </div> ) } // This is a custom filter UI that uses a // flatpickr range calendar to set the value function FlatpickrRangeColumnFilter({ column: { setFilter, filterValue, Header }, }) { const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(null); } if (storeFilter) { const filter = TableUtil.getFilter(currentTableName, Header); const filterValue = _.map(filter, date => {return new Date(date)} ) if (filter === '') { TableUtil.saveFilter(currentTableName, Header, [] ); setFilter(undefined); } if (filterValue && !value ){ setValue(filterValue); setFilter(filterValue); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (value, isCleared) => { hasFilters = true; if (isCleared) { hasFilters = false; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); filterCallback(tableOptionsState, setLoaderFunction); } else { let filterColumn = _.find(tableOptionsState.filters, {id: Header }); if(filterColumn) { filterColumn.value = value; filterCallback(tableOptionsState, setLoaderFunction); } else if (!filterColumn && value && value.length === 2) { // Here the above condition placed because the Start/End time filters is not consistency in tableOptionsState.filters filterColumn = {id: Header, value: value} tableOptionsState.filters.push(filterColumn); filterCallback(tableOptionsState, setLoaderFunction); } else { filterCallback(tableOptionsState, setLoaderFunction); } } }; return ( <div className="table-filter" onClick={e => { e.stopPropagation() }}> <Flatpickr data-enable-time data-input className="flatpickr-range-filter" options={{ "inlineHideInput": true, "wrap": true, "enableSeconds": true, "time_24hr": true, "minuteIncrement": 1, "allowInput": true, "mode": "range", "defaultHour": 0, "plugins": [new confirmDatePlugin()] }} title={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter the date & time range to search and press ‘Ok’ button"} value={filterValue} onClose={newValue => { if(newValue) { // To apply serverside filter only when the value is changed let isValueChanged = false; if (value.length !== newValue.length) { isValueChanged = true; } else if (value.length === newValue.length) { if (value.length === 1 && !(moment(value[0]).isSame(moment(newValue[0])))) { isValueChanged = true } else if (value.length === 2 && (!(moment(value[0]).isSame(moment(newValue[0]))) || !(moment(value[1]).isSame(moment(newValue[1]))))) { isValueChanged = true; } } setValue(newValue); setFilter(newValue); if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, newValue); } if ((newValue !== '' && newValue !== 'Invalid date' ) && isValueChanged && doServersideFilter) { setFiltered(true); callServerFilter(newValue); } } }} > <input type="text" data-input className={`p-inputtext p-component calendar-input`} /> <button class="p-button p-component p-button-icon-only calendar-button" data-toggle title="Click to select the date range" > <i class="fas fa-calendar"></i> </button> <button class="p-button p-component p-button-icon-only calendar-reset" onClick={(value) => { setFilter(undefined); setValue([]); setFiltered(false);filterValue = []; if(storeFilter){ TableUtil.saveFilter(currentTableName, Header, [] ); } if (doServersideFilter) { setFilter(undefined); setValue(''); callServerFilter(value, true); } }} title="Clear date range" > <i class="fa fa-times" style={{color:'white', marginTop:'-2.85px'}} ></i> </button> </Flatpickr> </div> ) } // This is a custom filter UI that uses a // calendar to set the value function CalendarColumnFilter({ column: { setFilter, filterValue, Header }, }) { // Calculate the min and max // using the preFilteredRows const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(null); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if(filterValue && !value){ const valueAsDate = new Date(filterValue) setValue(valueAsDate); setFilter(valueAsDate); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; if (isCleared) { hasFilters = false; if (filtered) { _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); filterCallback(tableOptionsState, setLoaderFunction); } } else { filterCallback(tableOptionsState, setLoaderFunction); } }; return ( <div className="table-filter" onClick={e => { e.stopPropagation() }}> <Calendar value={filterValue} appendTo={document.body} dateFormat="yy-mm-dd" onChange={(e) => { const value = moment(e.value).format('YYYY-MM-DD') setValue(value); setFilter(e.value); if (value !== 'Invalid date' && doServersideFilter) { setFiltered(true); callServerFilter(e); } if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, value); } }} onClearButtonClick={(e) => { if(storeFilter) { TableUtil.clearColumnFilter(currentTableName, Header); } }} showIcon></Calendar> {value && <i onClick={(e) => { setFilter(undefined); setValue(''); setFiltered(false); if (storeFilter) { TableUtil.clearColumnFilter(currentTableName, Header); } if (doServersideFilter) { setFilter(undefined); setValue(''); callServerFilter(e, true); } }} className="tb-cal-reset fa fa-times" />} </div> ) } // This is a custom filter UI that uses a // calendar to set the value function DateTimeColumnFilter({ column: { setFilter, filterValue, Header }, }) { const [value, setValue] = useState(''); React.useEffect(() => { if (!filterValue && value) { setValue(null); } if (storeFilter) { const getValue = TableUtil.getFilter(currentTableName, Header); if (getValue && !value) { const valueAsDate = new Date(getValue) setValue(valueAsDate); setFilter(valueAsDate); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); if (isCleared) { hasFilters = false; filterCallback(tableOptionsState, setLoaderFunction); } else { tableOptionsState.filters.push({id: Header, value: moment(event.value, moment.ISO_8601).format('YYYY-MM-DD HH:mm:ss')}); filterCallback(tableOptionsState, setLoaderFunction); } }; return ( <div className="table-filter" onClick={e => { e.stopPropagation() }}> <Calendar value={value} appendTo={document.body} dateFormat="yy/mm/dd" onKeyUp={(e) => { if (e.key === "Enter" && doServersideFilter) { callServerFilter(e); } }} onChange={(e) => { const value = moment(e.value, moment.ISO_8601).format('YYYY-MM-DD HH:mm:ss'); setValue(value); setFilter(value); if (value !== 'Invalid date' && doServersideFilter) { callServerFilter(e); } if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, value); } }} showIcon // showTime= {true} //showSeconds= {true} // hourFormat= "24" ></Calendar> {value && <i onClick={(e) => { setFilter(undefined); setValue(''); if (doServersideFilter) { setFilter(undefined); setValue(''); callServerFilter(e, true); } if (storeFilter) { TableUtil.clearColumnFilter(currentTableName, Header); } }} className="tb-cal-reset fa fa-times" />} </div> ) } /** * Custom function to filter data from date field. * @param {Array} rows * @param {String} id * @param {String} filterValue */ function fromDatetimeFilterFn(rows, id, filterValue) { const filteredRows = _.filter(rows, function (row) { // If cell value is null or empty if (!row.values[id]) { return false; } //Remove microsecond if value passed is UTC string in format "YYYY-MM-DDTHH:mm:ss.sssss" let rowValue = moment.utc(row.values[id].split('.')[0]); if (!rowValue.isValid()) { // For cell data in format 'YYYY-MMM-DD' rowValue = moment.utc(moment(row.values[id], 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS")); } const start = moment.utc(moment(filterValue, 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS")); return (start.isSameOrBefore(rowValue)); }); return filteredRows; } /** * Custom function to filter Multi selection based on filter type (Any/All) . * @param {Array} rows * @param {String} id * @param {String} filterValue */ function multiSelectFilterFn(rows, id, filterValue) { if (filterValue) { const filteredRows = _.filter(rows, function (row) { if (filterValue.length === 0) { return true; } // If cell value is null or empty if (!row.values[id]) { return false; } let rowValue = row.values[id]; let hasData = false; let columnValues = rowValue.split(','); let unfilteredColValues = _.difference(filterValue, columnValues); if (multiSelectOption[id] === 'Any') { hasData = unfilteredColValues.length < filterValue.length; } else { hasData = unfilteredColValues.length === 0; } return hasData; }); return filteredRows; } } /** * Custom function to filter data from date field. * @param {Array} rows * @param {String} id * @param {String} filterValue */ function toDatetimeFilterFn(rows, id, filterValue) { let end = moment.utc(moment(filterValue, 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS")); end = moment(end, "DD-MM-YYYY").add(1, 'days'); const filteredRows = _.filter(rows, function (row) { // If cell value is null or empty if (!row.values[id]) { return false; } //Remove microsecond if value passed is UTC string in format "YYYY-MM-DDTHH:mm:ss.sssss" let rowValue = moment.utc(row.values[id].split('.')[0]); if (!rowValue.isValid()) { // For cell data in format 'YYYY-MMM-DD' rowValue = moment.utc(moment(row.values[id], 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS")); } return (end.isSameOrAfter(rowValue)); }); return filteredRows; } /** * Custom function to filter data from date field. * @param {Array} rows * @param {String} id * @param {String} filterValue */ function dateFilterFn(rows, id, filterValue) { const filteredRows = _.filter(rows, function (row) { // If cell value is null or empty if (!row.values[id]) { return false; } //Remove microsecond if value passed is UTC string in format "YYYY-MM-DDTHH:mm:ss.sssss" let rowValue = moment.utc(row.values[id].split('.')[0]); if (!rowValue.isValid()) { // For cell data in format 'YYYY-MMM-DD' rowValue = moment.utc(moment(row.values[id], 'YYYY-MM-DD').format("YYYY-MM-DDT00:00:00")); } const start = moment.utc(moment(filterValue, 'YYYY-MM-DD').format("YYYY-MM-DDT00:00:00")); const end = moment.utc(moment(filterValue, 'YYYY-MM-DD').format("YYYY-MM-DDT23:59:59")); return (start.isSameOrBefore(rowValue) && end.isSameOrAfter(rowValue)); }); return filteredRows; } /** * Custom function to filter data Range from date field. * @param {Array} rows * @param {String} id * @param {String} filterValue */ function dateRangeFilterFn(rows, id, filterValue) { const filteredRows = _.filter(rows, function (row) { // If cell value is null or empty if (!row.values[id]) { return true; } //Remove microsecond if value passed is UTC string in format "YYYY-MM-DDTHH:mm:ss.sssss" let rowValue = moment.utc(row.values[id].split('.')[0]); if (!rowValue.isValid()) { // For cell data in format 'YYYY-MMM-DD' rowValue = moment.utc(moment(row.values[id], 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS")); } const start = moment.utc(moment(filterValue[0], 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS")); const end = moment.utc(moment(filterValue[1], 'YYYY-MM-DDTHH:mm:SS').format("YYYY-MM-DDTHH:mm:SS")); if(moment(end,'YYYY-MM-DDTHH:mm:SS', true).isValid() && moment(start,'YYYY-MM-DDTHH:mm:SS', true).isValid()) { return (start.isSameOrBefore(rowValue) && end.isSameOrAfter(rowValue)); } else if(moment(start,'YYYY-MM-DDTHH:mm:SS', true).isValid()) { return (start.isSameOrBefore(rowValue)); } else { return true; } }); return filteredRows; } function durationTimeFilterFn(rows, id, filterValue) { const filteredRows = _.filter(rows, function (row) { // If cell value is null or empty if (!row.values[id]) { return false; } //Remove microsecond if value passed is UTC string in format "HH:mm:ss.sssss" let rowValue = moment(row.values[id], 'HH:mm:SS'); if (!rowValue.isValid()) { // For cell data in format 'HH:mm:SS' rowValue = moment(row.values[id], 'HH:mm:SS'); } const start = moment(filterValue[0], 'HH:mm:SS'); const end = moment(filterValue[1], 'HH:mm:SS'); if(moment(end,'HH:mm:SS', true).isValid() && moment(start,'HH:mm:SS', true).isValid()) { return (start.isSameOrBefore(rowValue) && end.isSameOrAfter(rowValue)); } else if (!(moment(end,'HH:mm:SS', true).isValid()) && !(moment(start,'HH:mm:SS', true).isValid()) ){ return true } else if(!(moment(start,'HH:mm:SS', true).isValid())) { return end.isSameOrAfter(rowValue); } else if(!(moment(end,'HH:mm:SS', true).isValid())) { return start.isSameOrBefore(rowValue); } }); return filteredRows; } // This is a custom UI for our 'between' or number range // filter. It uses slider to filter between min and max values. function RangeColumnFilter({ column: { filterValue = [], preFilteredRows, setFilter, id, Header }, }) { let [value, setValue] = useState(''); let [firstLoad, setFirstLoad] = useState(true); const [min, max] = React.useMemo(() => { let min = 0; let max = 0; if (preFilteredRows.length > 0 && preFilteredRows[0].values[id]) { min = preFilteredRows[0].values[id]; } preFilteredRows.forEach(row => { min = Math.min(row.values[id] ? row.values[id] : 0, min); max = Math.max(row.values[id] ? row.values[id] : 0, max); }); if (storeFilter && firstLoad) { let storedFilter = TableUtil.getFilter(currentTableName, Header); if (storedFilter) { setValue(storedFilter); setFilter(storedFilter); setFirstLoad(false); } } return [min, max]; }, [id, preFilteredRows]); if (filterValue.length === 0) { filterValue = [min, max]; } return ( <> <div className="filter-slider-label"> <span style={{ float: "left" }}>{filterValue[0]}</span> <span style={{ float: "right", marginRight: "5px" }}>{min !== max ? filterValue[1] : ""}</span> </div> <Slider value={filterValue} min={min} max={max} className="filter-slider" style={{}} onChange={(e) => { setValue(e.value); setFilter(e.value); if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, e.value); } }} range /> </> ); } /** * Number range rilter * @param {number} param0 : Range value for min and max filters * @returns */ function NumberRangeFilter({ column: { filterValue = [], preFilteredRows, setFilter, id, Header }, }) { let [rangeValue, setRangeValue] = useState([0,0]); const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(''); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if (filterValue) { setFiltered(true); } if(!value){ setValue(filterValue); //setFilter(filterValue); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); if (isCleared) { hasFilters = false; if (filtered) { filterCallback(tableOptionsState, setLoaderFunction); } } else { tableOptionsState.filters.push({id: Header, value: rangeValue}); filterCallback(tableOptionsState, setLoaderFunction); } }; return ( <div style={{ alignItems: 'center' }} > <InputText value={value[0]} type="number" tooltip="Enter the minimum value to search" onKeyUp={(e) => { if (e.key === "Enter" && doServersideFilter) { TableUtil.saveFilter(currentTableName, Header, rangeValue); setFiltered(true); callServerFilter(e, false); } }} onChange={e => { setFilter(undefined); setFiltered(false); const val = e.target.value; let max = rangeValue[1]; setValue([val,max]); setFilter([val,max] || undefined); setRangeValue([val,max]); filterValue[0] = val; if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, [val,max]); setFilter([val,max]); } }} style={{ width: '65px', height: '25px' // marginRight: '0.5rem', }} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Minimum Range value and press ‘Enter’ key to search"} /> <InputText value={value[1]} type="number" tooltip="Enter the maximum value to search" onKeyUp={(e) => { if (e.key === "Enter" && doServersideFilter) { setFiltered(true); callServerFilter(e, false); } }} onChange={e => { const val = e.target.value; let min = rangeValue[0]; setRangeValue([min,val]); filterValue[1] = val; setValue([min,val]); setFilter([min,val] || undefined); if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, [min,val]); setFilter([min,val]); } }} style={{ width: '65px', height: '25px' }} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Maximum Range value and press ‘Enter’ key to search"} /> </div> ) } // Priority Rank Range Filter function RankRangeFilter({ column: { filterValue = [], preFilteredRows, setFilter, id, Header }, }) { let [rangeValue, setRangeValue] = useState([]); const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(''); //setRangeValue([]) } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if (filterValue) { setFiltered(true); } if(!value){ setValue(filterValue); //setFilter(filterValue); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); if (isCleared) { hasFilters = false; if (filtered) { filterCallback(tableOptionsState, setLoaderFunction); } } else { tableOptionsState.filters.push({id: Header, value: rangeValue}); filterCallback(tableOptionsState, setLoaderFunction); } }; return ( <div style={{ alignItems: 'center' }} > <input type="decimal" title={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Minimum Range value and press ‘Enter’ key to search"} max="1" min="0" className="p-inputtext p-component" value={value[0]} step="0.0001" onKeyUp={(e) => { if (e.key === "Enter" && doServersideFilter) { TableUtil.saveFilter(currentTableName, Header, rangeValue); setFiltered(true); callServerFilter(e, false); } }} onChange={e => { setFilter(undefined); setFiltered(false); let val = e.target.value; val = val.replace(/([^0-9.]+)/, ""); const match = /(\d{0,1})[^.]*((?:\.\d{0,4})?)/g.exec(val); val = match[1] + match[2]; if (val == '' || (val >= 0 && val <= 1)) { let max = rangeValue[1]; setValue([val,max]); setFilter([val,max] || undefined); setRangeValue([val,max]); filterValue[0] = val; if(storeFilter) { //TableUtil.saveFilter(currentTableName, Header, [val,max]); setFilter([val,max]); } } else { e.target.value = rangeValue[0]; } }} style={{ minWidth: '48px', maxWidth: '85px', width:'100%', height: '25px' }} /> <input type="decimal" title={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Maximum Range value and press ‘Enter’ key to search"} max="1" min="0" className="p-inputtext p-component" value={value[1]} step="0.0001" onKeyUp={(e) => { if (e.key === "Enter" && doServersideFilter) { TableUtil.saveFilter(currentTableName, Header, rangeValue); setFiltered(true); callServerFilter(e, false); } }} onChange={e => { setFilter(undefined); setFiltered(false); let val = e.target.value; val = val.replace(/([^0-9.]+)/, ""); const match = /(\d{0,1})[^.]*((?:\.\d{0,4})?)/g.exec(val); val = match[1] + match[2]; if (val == '' || (val >= 0 && val <= 1)) { let min = rangeValue[0]; setRangeValue([min,val]); filterValue[1] = val; setValue([min,val]); setFilter([min,val] || undefined); if(storeFilter) { //TableUtil.saveFilter(currentTableName, Header, [min,val]); setFilter([min,val]); } } else { e.target.value = rangeValue[0]; } }} style={{ minWidth: '48px', maxWidth: '85px', width:'100%', height: '25px' }} /> </div> ) } // Duration Range Filter function DurationRangeFilter({ column: { filterValue = [], preFilteredRows, setFilter, id, Header }, }) { let [rangeValue, setRangeValue] = useState(['','']); const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); React.useEffect(() => { if (!filterValue && value) { setValue(''); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); if (filterValue) { setFiltered(true); } if(filterValue && !value){ setValue(filterValue); setFilter(filterValue); } if(!filterValue && value.length>0){ setValue([]); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); if (isCleared) { hasFilters = false; if (filtered) { filterCallback(tableOptionsState, setLoaderFunction); } } else { tableOptionsState.filters.push({id: Header, value: rangeValue}); filterCallback(tableOptionsState, setLoaderFunction); } }; return ( <div onKeyPress={(e) => { if (e.key === "Enter" && doServersideFilter) { TableUtil.saveFilter(currentTableName, Header, rangeValue); setFiltered(true); callServerFilter(e, false); } else if(e.key === "Enter" ) { setFilter(rangeValue); } }} style={{ alignItems: 'center' }} > <InputMask mask="99:99:99" value={value[0]} placeholder="HH:mm:ss" tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Minimum Range value in HH:mm:ss format and press ‘Enter’ key to search"} onChange={e => { let val = e.target.value; if (val.includes(":") && !Validator.isValidHHmmss(val, true)) { val = rangeValue[0]; } let max = rangeValue[1]; setValue([val,max]); if(doServersideFilter) { setFilter([val,max] || undefined); } setRangeValue([val,max]); filterValue[0] = val; if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, [val,max]); } }} style={{ minWidth: '48px', maxWidth: '85px', width:'100%', height: '25px' }} /> <InputMask mask="99:99:99" value={value[1]} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Maximum Range value in HH:mm:ss format and press ‘Enter’ key to search"} placeholder="HH:mm:ss" onChange={e => { let val = e.target.value; if (val.includes(":") && !Validator.isValidHHmmss(val, true)) { val = rangeValue[1]; } let min = rangeValue[0]; setValue([min,val]); if(doServersideFilter) { setFilter([min,val] || undefined); } setRangeValue([min,val]); filterValue[1] = val; if(storeFilter) { TableUtil.saveFilter(currentTableName, Header, [min,val]); } }} style={{ minWidth: '48px', maxWidth: '85px', width: '100%', height: '25px' }} /> </div> ) } // Duration Range Filter function DurationRangeFilterWithDays({ column: { filterValue = [], preFilteredRows, setFilter, id, Header }, }) { let [rangeValue, setRangeValue] = useState([0,0]); const [value, setValue] = useState(''); const [filtered, setFiltered] = useState(false); const [filterType, setFilterType] = useState(); React.useEffect(() => { if (!filterValue && value) { setValue(''); } if (storeFilter) { const filterValue = TableUtil.getFilter(currentTableName, Header); const storedFilterType = TableUtil.getFilter(currentTableName, `${Header}-FilterOption`); if (filterValue) { setFiltered(true); setFilterType('Range'); } else { setFilterType('All'); } if (storedFilterType) { //setFiltered(`${Header}-FilterOption`, true); setFilterType(storedFilterType); } if(!value){ setValue(filterValue); } } }, [filterValue, value]); // Function to call the server side filtering const callServerFilter = (event, isCleared) => { hasFilters = true; _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); if (isCleared) { hasFilters = false; if (filtered) { filterCallback(tableOptionsState, setLoaderFunction); } } else { tableOptionsState.filters.push({id: Header, value: rangeValue}); filterCallback(tableOptionsState, setLoaderFunction); } }; const filterTypeChangeEvent =(e) => { setFilterType(e.value); if(e.value === null || e.value === 'All') { setFiltered(false); _.remove(tableOptionsState.filters, function(filter) { return filter.id === 'durationNull' }); _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); callServerFilter(e, true); } else if( e.value === 'Range') { setFiltered(true); setRangeValue([0,0]); setValue([0,0]); _.remove(tableOptionsState.filters, function(filter) { return filter.id === 'durationNull' }); } else if( e.value === 'Unknown') { setFiltered(true); _.remove(tableOptionsState.filters, function(filter) { return filter.id === Header }); tableOptionsState.filters.push({id: 'durationNull', value: true}); filterCallback(tableOptionsState, setLoaderFunction); } if (storeFilter) { if (e.value) { TableUtil.saveFilter(currentTableName, `${Header}-FilterOption`, e.value); tableOptionsState.filters.push({id: `${Header}-FilterOption`, value: e.value}); setFiltered(true); } else { TableUtil.saveFilter(currentTableName, `${Header}-FilterOption`, null); } } } return ( <div onKeyPress={(e) => { if (e.key === "Enter" && doServersideFilter) { TableUtil.saveFilter(currentTableName, Header, rangeValue); setFiltered(true); callServerFilter(e, false); } }} style={{ alignItems: 'center' }} > <div onClick={e => { e.stopPropagation() }} > <div > <Dropdown optionLabel="name" optionValue="name" tooltip="Select the Duration filter type to search" value={filterType} options={[{name:'All', value: 'All'},{name:'Range', value: 'Range'},{name:'Unknown', value: 'Unknown'}]} onChange={(e) => {filterTypeChangeEvent(e)}} style={{width: '10em'}} showClear={true} /> { filterType === 'Range' && <div style={{marginTop: '1em'}}> <InputMask mask="999 99:99:99" value={value[0]} placeholder="DDD HH:mm:ss" tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Minimum Range value in DDD HH:mm:ss format and press ‘Enter’ key to search"} onChange={e => { setFilter(undefined); setFiltered(false); let val = e.target.value; if (val.includes(":") && !Validator.isValidDDDHHmmss(val, false)) { val = rangeValue[0]; } let max = rangeValue[1]; setValue([val,max]); setFilter([val,max] || undefined); setRangeValue([val,max]); filterValue[0] = val; if(storeFilter) { //TableUtil.saveFilter(currentTableName, Header, [val,max]); setFilter([val,max]); } }} style={{ width: '115px', height: '25px' }} /> <InputMask mask="999 99:99:99" value={value[1]} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Maximum Range value in DDD HH:mm:ss format and press ‘Enter’ key to search"} placeholder="DDD HH:mm:ss" onChange={e => { setFilter(undefined); setFiltered(false); let val = e.target.value; if (val.includes(":") && !Validator.isValidDDDHHmmss(val, false)) { val = rangeValue[1]; } let min = rangeValue[0]; setValue([min,val]); setFilter([min,val] || undefined); setRangeValue([min,val]); filterValue[1] = val; if(storeFilter) { //TableUtil.saveFilter(currentTableName, Header, [min,val]); setFilter([min,val]); } }} style={{ width: '115px', height: '25px' }} /> </div> } </div> </div> </div> ) } // 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, Header }, }) { const [errorProps, setErrorProps] = useState({}); const [maxErr, setMaxErr] = useState(false); 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', // flexdirection:'column', alignItems: 'center' }} > <InputText value={filterValue[0]} type="number" onChange={e => { const val = e.target.value; setFilter((old = []) => [val ? parseFloat(val, 10) : undefined, old[1]]); }} placeholder={`Min (${min})`} style={{ width: '55px', height: '25px' // marginRight: '0.5rem', }} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Minimum Range value and press ‘Enter’ key to search"} /> <InputText value={filterValue[1] || ''} type="number" {...errorProps} className={maxErr && 'field-error'} onChange={e => { const val = e.target.value; const minVal = filterValue.length && filterValue[0]; if (minVal && e.target.value < minVal) { setMaxErr(true); setErrorProps({ tooltip: "Max value should be greater than Min", tooltipOptions: { event: 'hover' } }); } else { setMaxErr(false); setErrorProps({}); } setFilter((old = []) => [old[0], val ? parseFloat(val, 10) : undefined]) }} placeholder={`Max (${max})`} style={{ width: '55px', height: '25px' // marginLeft: '0.5rem', }} tooltip={(tableToolTipsState[Header])?tableToolTipsState[Header]:"Enter Maximum Range value and press ‘Enter’ key to search"} /> </div> ) } function fuzzyTextFilterFn(rows, id, filterValue) { return matchSorter(rows, filterValue, { keys: [row => row.values[id]] }); } const filterTypes = { 'select': { fn: SelectColumnFilter, }, // This component has Any and All Radio buttons 'multiselect': { fn: MultiSelectColumnFilter, type: multiSelectFilterFn }, // This component does not have Any and All Radio buttons 'multiselect-filter': { fn: MultiSelectFilter, type: multiSelectFilterFn }, 'switch': { fn: BooleanColumnFilter }, 'slider': { fn: SliderColumnFilter }, 'date': { fn: CalendarColumnFilter, type: dateFilterFn }, 'dateRange': { fn: DateRangeColumnFilter, type: dateRangeFilterFn }, 'flatpickrDateRange': { fn: FlatpickrRangeColumnFilter, type: dateRangeFilterFn }, 'fromdatetime': { fn: DateTimeColumnFilter, type: fromDatetimeFilterFn }, 'todatetime': { fn: DateTimeColumnFilter, type: toDatetimeFilterFn }, 'range': { fn: RangeColumnFilter, type: 'between' }, 'minMax': { fn: NumberRangeColumnFilter, type: 'between' }, 'numberRangeMinMax': { fn: NumberRangeFilter, type: 'between' }, 'rankMinMax': { fn: RankRangeFilter, type: 'between' }, 'durationMinMax': { fn: DurationRangeFilter, type: durationTimeFilterFn }, 'durationWithDaysMinMax': { fn: DurationRangeFilterWithDays, type: 'between' } }; // Let the table remove the filter if the string is empty fuzzyTextFilterFn.autoRemove = val => !val const IndeterminateCheckbox = React.forwardRef( ({ indeterminate, ...rest }, ref) => { const defaultRef = React.useRef() const resolvedRef = ref || defaultRef React.useEffect(() => { resolvedRef.current.indeterminate = indeterminate }, [resolvedRef, indeterminate]) return <input type="checkbox" ref={resolvedRef} {...rest}/> } ); // ViewTable table component function Table(props) { let {fetchData, pageCount: controlledPageCount, currentPage, dataFetchStatus, columns, data, defaultheader, optionalheader, tablename, defaultSortColumn, defaultpagesize, columnOrders, showAction, toggleBySorting, onColumnToggle, lsKeySortColumn , descendingColumn, ignoreSorting } = props; ignoreSorting = ignoreSorting ||[]; ignoreSorting = [...ignoreSorting,'action']; descendingColumn = descendingColumn || []; const checkDefaultSortColumnEmpty = () => { return !defaultSortColumn || !defaultSortColumn[0] || Object.keys(defaultSortColumn[0]).length === 0; } const checkDescendingColumnExists = (value) => { return descendingColumn.includes(value); } const checkToIgnoreSorting = (value) => { return ignoreSorting.includes(value); } const getFirstVisibleColumn = (selectedColumn, tempAllColumns) => { let selected = {}; let tempColumn = {}; let totalColumns = undefined; if (tempAllColumns && tempAllColumns.length > 0) { totalColumns = tempAllColumns; } if (totalColumns) { for (let i = 0; i < totalColumns.length; i++) { tempColumn = { ...totalColumns[i] }; if (tempColumn.Header && typeof tempColumn.Header === "string") { if (tempColumn.Header.toLowerCase() === selectedColumn.Header.toLowerCase()) { tempColumn.isVisible = selectedColumn.isVisible; } if (!checkToIgnoreSorting(tempColumn.Header.toLowerCase()) && tempColumn.isVisible) { selected = tempColumn; break; } } } } return selected; } if (checkDefaultSortColumnEmpty()) { let tempVisibleColumn = getFirstVisibleColumn({ Header: '' }, columns); defaultSortColumn = [{ id: tempVisibleColumn.Header, desc: checkDescendingColumnExists(tempVisibleColumn.Header.toLowerCase()) }]; } const filterTypes = React.useMemo( () => ({ // Add a new fuzzyTextFilterFn filter type. fuzzyText: fuzzyTextFilterFn, // Or, override the default text filter to use // "startWith" text: (rows, id, filterValue) => { return rows.filter(row => { const rowValue = row.values[id] return rowValue !== undefined ? String(rowValue) .toLowerCase() .startsWith(String(filterValue).toLowerCase()) : true }) }, }), [] ) const defaultColumn = React.useMemo( () => ({ // Let's set up our default Filter UI Filter: DefaultColumnFilter, minWidth: 60, maxWidth: 250 }), [] ) let tableParams = { columns, data, defaultColumn, filterTypes, initialState: { pageIndex: doServersideFilter?currentPage:0, pageSize: (defaultpagesize && defaultpagesize > 0) ? defaultpagesize : 10, sortBy: defaultSortColumn }, manualPagination: doServersideFilter, manualSortBy: doServersideFilter, manualFilters: doServersideFilter, //autoResetPage: false, //autoResetSortBy: false, // pageCount: controlledPageCount, getExportFileBlob, }; if (doServersideFilter) { tableParams.pageCount = controlledPageCount; } const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, setAllFilters, allColumns, getToggleHideAllColumnsProps, visibleColumns, state, page, preGlobalFilteredRows, setGlobalFilter, setHiddenColumns, //gotoPage, // setPageSize, selectedFlatRows, setColumnOrder, exportData, // pageCount, gotoPage, setPageSize, state: {sortBy, pageIndex, pageSize }, } = tblinstance = useTable( {...tableParams}, useFilters, useGlobalFilter, useSortBy, usePagination, useRowSelect, useColumnOrder, useExportData, useFlexLayout, useResizeColumns ); const currentColOrder = React.useRef(); let pageCount = doServersideFilter?controlledPageCount:data.length; tmpTableData = data; // while siwtch the task type or Su type, this will set the relavent default sort column if (currentTableName && currentTableName !== tablename) { state.sortBy = defaultSortColumn; } currentTableName = props.tablename; //if (!tableOptionsState) { tableOptionsState = _.cloneDeep(state); //} // Pass the table's state to the parent function if the parent function has set the callback function for it. if (props.setTableState) { props.setTableState(state); } const [loading, setLoading] = React.useState(false); setLoaderFunction = setLoading; React.useEffect(() => { fetchData({ state, setLoading }); }, [sortBy, fetchData, pageIndex, pageSize, filterTypes,]); React.useEffect(() => { setHiddenColumns( // columns.filter(column => !column.isVisible).map(column => column.accessor) columns.filter(column => !column.isVisible).map(column => column.id) ); // console.log('columns List', visibleColumns.map((d) => d.id)); const storedColOrder = UtilService.localStore({ type: 'get', key: tablename+'colOrder'}); if (storedColOrder) { setColumnOrder(storedColOrder) } else if (columnOrders && columnOrders.length) { if (showAction === 'true') { setColumnOrder(['Select', 'Action', ...columnOrders]); UtilService.localStore({ type: 'set', key: tablename+'colOrder', value: ['Select', 'Action', ...columnOrders]}); } else { setColumnOrder(['Select', ...columnOrders]); UtilService.localStore({ type: 'set', key: tablename+'colOrder', value: ['Select', ...columnOrders]}); } } setLoading(dataFetchStatus); }, [setHiddenColumns, columns]); let op = useRef(null); const [currentpage, setcurrentPage] = React.useState(0); const [selectedClickedRow, setSelectedClickedRow] = React.useState([]); const [currentrows, setcurrentRows] = React.useState(defaultpagesize); const [custompagevalue, setcustompagevalue] = React.useState(); const onPagination = (e) => { loadingStatus = true; setLoading(true); gotoPage(e.page); setcurrentPage(e.first); setcurrentRows(e.rows); setPageSize(e.rows) if ([10, 25, 50, 100].includes(e.rows)) { setcustompagevalue(); } }; const onCustomPage = (e) => { loadingStatus = true; setLoading(true); if (typeof custompagevalue === 'undefined' || custompagevalue == null) return; gotoPage(0); setcurrentPage(0); setcurrentRows(custompagevalue); setPageSize(custompagevalue); }; const onChangeCustompagevalue = (e) => { setcustompagevalue(e.target.value); } const onShowAllPage = (e) => { loadingStatus = true; setLoading(true); gotoPage(0); setcurrentPage(0); setcurrentRows(0); setPageSize(pageCount) setcustompagevalue(); }; const onColumnToggleViewTable = (selectedColumn, sortedColumn) => { let visibleColumn = {}; let viewColumn = {}; if (selectedColumn && selectedColumn.Header === sortedColumn.Header && !selectedColumn.isVisible) { visibleColumn = getFirstVisibleColumn(selectedColumn, allColumns); viewColumn = { Header: visibleColumn.Header, desc: checkDescendingColumnExists(visibleColumn.Header.toLowerCase())}; let tempdefaultSortColumn = [{ id: viewColumn.Header, desc: viewColumn.desc }]; if (lsKeySortColumn && lsKeySortColumn.trim().length > 0) { localStorage.setItem(lsKeySortColumn, JSON.stringify(tempdefaultSortColumn)); } } visibleColumn.Header = visibleColumn.Header || ""; return viewColumn; } const onToggleChange = (e) => { let lsToggleColumns = []; let selectedColumn = null; let sortedColumn = {}; let defaultVisible = false; if (e.target.id === '') { defaultVisible = e.target.checked; } // allColumns.forEach(acolumn => { for (const acolumn of allColumns) { let jsonobj = {}; let visible = (acolumn.Header === e.target.id) ? ((acolumn.isVisible) ? false : true) : e.target.id === '' ? defaultVisible : acolumn.isVisible; jsonobj['Header'] = acolumn.Header; jsonobj['isVisible'] = visible; lsToggleColumns.push(jsonobj) selectedColumn = (acolumn.Header === e.target.id) ? jsonobj : selectedColumn; if (acolumn.isSorted) { sortedColumn['Header'] = acolumn.Header; sortedColumn['isVisible'] = visible; } // Remove the column filters stored and clear the column filter, if the column is toogled to if (!visible) { if (storeFilter) { TableUtil.clearColumnFilter(currentTableName, acolumn.Header); } _.remove(tableOptionsState.filters, ['id', acolumn.Header]); setAllFilters(tableOptionsState.filters); } } // }); localStorage.setItem(tablename, JSON.stringify(lsToggleColumns)); if (onColumnToggleViewTable) { let columnTobeSorted = onColumnToggleViewTable(selectedColumn, sortedColumn); //onColumnToggle(selectedColumn, sortedColumn); columnTobeSorted.Header = columnTobeSorted.Header || ""; if (columnTobeSorted.Header.trim().length > 0) { tblinstance.toggleSortBy(columnTobeSorted.Header, columnTobeSorted.desc); } } } filteredData = _.map(rows, 'values'); if (parentCallbackFunction) { parentCallbackFunction(filteredData); } /** Assign current table instance to variable in parent class - just used for refresh the filter state*/ if (tableInstanceRef) { tableInstanceRef(tblinstance); } /* Select only rows than can be selected. This is required when ALL is selected */ selectedRows = _.filter(selectedFlatRows, selectedRow => { return (selectedRow.original.canSelect === undefined || selectedRow.original.canSelect) }); /* Take only the original values passed to the component */ selectedRows = _.map(selectedRows, 'original'); /* Callback the parent function if available to pass the selected records on selection */ if (parentCBonSelection && selectedRows != selectedClickedRow && selectedRows.length != 0) { parentCBonSelection(selectedRows) } const onSortBy = () => { sessionStorage.setItem("sortedData", tbldata); } /** * Clear all filters in table and reload the data */ const clearAllFilter = () => { // Call parent function during all clear if (clearAllFuncCallback) { clearAllFuncCallback(); } hasFilters = false; setAllFilters([]); tableOptionsState.filters = []; if (doServersideFilter) { filterCallback(tableOptionsState, setLoaderFunction); } if (storeFilter) { TableUtil.clearTableFilter(currentTableName); } } return ( <> <div style={{display:'flex',justifyContent:'space-between',height:'35px'}}> <div id="block_container" > {allowColumnSelection && <div style={{ textAlign: 'left', marginRight: '30px' }} title='Toggle Columns'> <i className="fa fa-columns col-filter-btn" label="Toggle Columns" onClick={(e) => op.current.toggle(e)} /> {showColumnFilter && <div style={{ position: "relative", top: "-25px", marginLeft: "50px", color: "#005b9f" }} onClick={() => clearAllFilter()} > <i class="fas fa-sync-alt" title="Clear All Filters"></i></div>} <OverlayPanel ref={op} id="overlay_panel" showCloseIcon={false} > <div> <div style={{ textAlign: 'center' }}> <label>Select column(s) to view</label> </div> <div style={{ float: 'left', backgroundColor: '#d1cdd936', width: '250px', height: '400px', overflow: 'auto', marginBottom: '10px', padding: '5px' }}> <div id="tagleid" > <div > <div style={{ marginBottom: '5px' }}> <IndeterminateCheckbox {...getToggleHideAllColumnsProps()} onClick={(e) => onToggleChange(e)} /> Select All </div> {allColumns.map(column => ( <div key={column.id} style={{ 'display': column.id !== 'actionpath' ? 'block' : 'none' }}> <input type="checkbox" {...column.getToggleHiddenProps()} id={(defaultheader[column.id]) ? defaultheader[column.id] : (optionalheader[column.id] ? optionalheader[column.id] : column.id)} onClick={(e) => onToggleChange(e)} /> { (defaultheader[column.id]) ? defaultheader[column.id] : (optionalheader[column.id] ? optionalheader[column.id] : column.id)} </div> ))} <br /> </div> </div> </div> </div> </OverlayPanel> </div> } <div style={{ textAlign: 'right' }}> {tbldata && tbldata.length > 0 && !isunittest && showGlobalFilter && <GlobalFilter preGlobalFilteredRows={preGlobalFilteredRows} globalFilter={state.globalFilter} setGlobalFilter={setGlobalFilter} /> } </div> {showTopTotal && !hasFilters && <div className="total_records_top_label"> <label >Total records ({pageCount})</label></div> } {showTopTotal && hasFilters && <div className="total_records_top_label" ><label >Filtered {filteredData.length} from {pageCount}</label></div>} </div> {showCSV && <div className="total_records_top_label" style={{ marginTop: '3px', marginRight: '5px' }} > <a href="#" onClick={() => { exportData("csv", false); }} title="Download CSV" style={{ verticalAlign: 'middle' }}> <i class="fas fa-file-csv" style={{ color: 'green', fontSize: '20px' }} ></i> </a> </div> /* <div className="total_records_top_label" > <a href="#" onClick={() => {exportData("pdf", false);}} title="Download PDF" style={{verticalAlign: 'middle'}}> <i class="fas fa-file-pdf" style={{color: 'red', fontSize: '20px'}}></i> </a> </div> */ } </div> <div className="tmss-table table_container"> <table {...getTableProps()} data-testid="viewtable" className="viewtable" > <thead> {headerGroups.map(headerGroup => ( <DragDropContext onDragStart={() => { currentColOrder.current = allColumns.map(column => column.id); }} onDragUpdate={(dragUpdateObj, b) => { const colOrder = [...currentColOrder.current]; const sIndex = dragUpdateObj.source.index; const dIndex = dragUpdateObj.destination && dragUpdateObj.destination.index; if(typeof sIndex === 'number' && typeof dIndex === "number") { colOrder.splice(sIndex, 1); colOrder.splice(dIndex, 0, dragUpdateObj.draggableId); setColumnOrder(colOrder); UtilService.localStore({ type: 'set', key: tablename+'colOrder', value: colOrder}); } }} > <Droppable droppableId="droppable" direction="horizontal"> {(droppableProvided, snapshot) => ( <tr {...headerGroup.getHeaderGroupProps()} ref={droppableProvided.innerRef}> {headerGroup.headers.map((column,index) => ( <Draggable key={column.id} draggableId={column.id} index={index} isDragDisabled={_.includes(fixedColumns, column.id)? true: false}> {(provided, snapshot) => { if (column.id !== 'actionpath') { return ( <th className={column.id} className={_.includes(fixedColumns, column.id)?'fixed-column-td':''} style={{display: 'flex'}} onClick={() => { if(!doServersideFilter) { if(!column.disableSortBy) { toggleBySorting({ 'id': column.id, desc: (column.isSortedDesc != undefined ? !column.isSortedDesc : false) }); } } }}> <div style={{display:'flex'}}> <div style={{display: 'grid',verticalAlign:'bottom'}}> <div {...column.getHeaderProps(column.getSortByToggleProps())} className={_.includes(fixedColumns, column.id)?'fixed-column':''}> <div {...provided.draggableProps} {...provided.dragHandleProps} // {...extraProps} ref={provided.innerRef} style={{ ...getItemStyle( snapshot, provided.draggableProps.style ) // ...style }}> {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>) : "" : "" } </div> </div> {/* Render the columns filter UI */} {column.Header !== 'actionpath' && // <div className={columnclassname[0][column.Header]}> <div {...column.getHeaderProps(column.getSortByToggleProps())} > {column.canFilter && column.Header !== 'Action' ? column.render('Filter') : null} </div> } </div> </div> {_.includes(fixedColumns, column.id)?<></>: <div {...column.getResizerProps()} className={`resizer ${ column.isResizing ? 'isResizing' : '' }`} > </div> } </th> ); } else { return ""; } }} </Draggable> ))} </tr> )} </Droppable> </DragDropContext> ))} {(doServersideFilter && loading) && <tr style={{height: "5px"}}><td colSpan={columns.length} style={{padding: "0px"}}> <div><ProgressBar mode="indeterminate" style={{ height: '5px' }}/></div> </td></tr>} </thead> {/* If want to to clear the existing data while loading, remove the commented line below */} {/* {((doServersideFilter && !loading) || !doServersideFilter) && */} <tbody {...getTableBodyProps()}> {page.map((row, i) => { prepareRow(row) return ( <tr {...row.getRowProps()}> {row.cells.map(cell => { if (cell.column.id !== 'actionpath') { // return <td {...cell.getCellProps()} className={cell.column.id+'_body'}> return <td className={cell.column.id+'_body'} className={_.includes(fixedColumns, cell.column.id)?'fixed-column-td':''}> {(cell.row.original.links || []).includes(cell.column.id) ? <a href={cell.row.original.linksURL[cell.column.id]}>{cell.render('Cell', cell.getCellProps())}</a> : cell.render('Cell', cell.getCellProps())} </td> } else { return ""; } } )} </tr> ); })} </tbody> {/* } */} </table> </div> <div>{(doServersideFilter && loading) && <ProgressBar mode="indeterminate" style={{ height: '5px' }}/>}</div> <div className="pagination p-grid" > {tableOptionsState.filters.length === 0 && <div className="total_records_bottom_label" ><label >Total records ({pageCount})</label></div> } {tableOptionsState.filters.length > 0 && <div className="total_records_bottom_label" ><label >Filtered {filteredData.length} from {pageCount}</label></div> } <div> <Paginator rowsPerPageOptions={[10, 25, 50, 100]} first={currentpage} rows={currentrows} totalRecords={doServersideFilter?pageCount:rows.length} onPageChange={onPagination}></Paginator> </div> <div> <InputNumber id="custompage" value={custompagevalue} onChange={onChangeCustompagevalue} min={0} style={{ width: '100px' }} /> <label >Records/Page</label> <Button onClick={onCustomPage}> Show </Button> <Button onClick={onShowAllPage} style={{ marginLeft: "1em" }}> Show All </Button> </div> </div> </> ) } // Define a custom filter filter function! function filterGreaterThan(rows, id, filterValue) { return rows.filter(row => { const rowValue = row.values[id] return rowValue >= filterValue }) } // This is an autoRemove method on the filter function that // when given the new filter value and returns true, the filter // will be automatically removed. Normally this is just an undefined // check, but here, we want to remove the filter if it's not a number filterGreaterThan.autoRemove = val => typeof val !== 'number' function ViewTable(props) { const history = useHistory(); tbldata = JSON.parse(sessionStorage.getItem("sortedData")) || props.data; data = tbldata; let pageCount = props.totalPage || data.length; showCSV = (props.showCSV) ? props.showCSV : false; doServersideFilter = (props.callBackFunction)?true:false; parentCallbackFunction = props.filterCallback; parentCBonSelection = props.onRowSelection; isunittest = props.unittest; columnclassname = props.columnclassname; loadingStatus = props.loadingStatus === undefined ? loadingStatus : props.loadingStatus; showTopTotal = props.showTopTotal === undefined ? true : props.showTopTotal; showGlobalFilter = props.showGlobalFilter === undefined ? true : props.showGlobalFilter; showColumnFilter = props.showColumnFilter === undefined ? true : props.showColumnFilter; allowColumnSelection = props.allowColumnSelection === undefined ? true : props.allowColumnSelection; allowRowSelection = props.allowRowSelection === undefined ? false : props.allowRowSelection; let pageUpdated = props.pageUpdated === undefined ? true : props.pageUpdated; // Default Header to show in table and other columns header will not show until user action on UI clearAllFuncCallback = props.clearAllFuncCallback; tableInstanceRef = props.tableInstanceRef; let defaultheader = props.defaultcolumns; let optionalheader = props.optionalcolumns; let defaultSortColumn = props.defaultSortColumn; storeFilter = props.storeFilter? props.storeFilter : false let tablename = (props.tablename) ? props.tablename : window.location.pathname; if (!defaultSortColumn) { defaultSortColumn = [{}]; } let defaultpagesize = (typeof props.defaultpagesize === 'undefined' || props.defaultpagesize == null) ? 10 : props.defaultpagesize; let columns = []; let defaultdataheader = Object.keys(defaultheader[0]); let optionaldataheader = Object.keys(optionalheader[0]); // Get Tooltips for each column if provided and used in filter components tableToolTipsState = {}; for(const headerId of defaultdataheader) { if (defaultheader[0][headerId].tooltip) { tableToolTipsState[defaultheader[0][headerId].name] = defaultheader[0][headerId].tooltip; } } for(const headerId of optionaldataheader) { if (optionalheader[0][headerId].tooltip) { tableToolTipsState[optionalheader[0][headerId].name] = optionalheader[0][headerId].tooltip; } } /* If allowRowSelection property is true for the component, add checkbox column as 1st column. If the record has property to select, enable the checkbox */ if (allowRowSelection) { columns.push({ Header: ({ getToggleAllRowsSelectedProps }) => { return ( <div> <IndeterminateCheckbox {...getToggleAllRowsSelectedProps()} style={{ width: '15px', height: '15px' }} /> </div> ) }, id: 'Select', accessor: props.keyaccessor, Cell: ({ row }) => { return ( <div> {(row.original.canSelect === undefined || row.original.canSelect) && <IndeterminateCheckbox {...row.getToggleRowSelectedProps()} attr-id={row.original.id} style={{ width: '15px', height: '15px' }} /> } {row.original.canSelect === false && <input type="checkbox" checked={false} disabled style={{ width: '15px', height: '15px' }}></input> } </div> ) }, disableFilters: true, disableSortBy: true, isVisible: true, }); } if (props.showaction) { columns.push({ Header: 'Action', id: 'Action', accessor: props.keyaccessor, Cell: props => <Link to={{pathname: props.cell.row.values['actionpath']}} className='p-link' onClick={(e) => navigateTo(e, props)} ><i className="fa fa-eye" style={{ cursor: 'pointer' }}></i></Link>, disableFilters: true, disableSortBy: true, //isVisible: defaultdataheader.includes(props.keyaccessor), isVisible: true }) } const navigateTo = ( cellProps) =>() => { if (cellProps.cell.row.values['actionpath']) { if (!props.viewInNewWindow) { return history.push({ pathname: cellProps.cell.row.values['actionpath'], state: { "id": cellProps.value, } }) } else { window.open(cellProps.cell.row.values['actionpath'], '_blank'); } } else { props.actionCallback(cellProps.cell.row.values); } } //Default Columns defaultdataheader.forEach(header => { const isString = typeof defaultheader[0][header] === 'string'; const disableSortBy = defaultheader[0][header].disableSortBy; const disableFilter = defaultheader[0][header].disableFilters; const filterFn = (showColumnFilter ? (isString ? (defaultheader[0][header].filter==='none'?"":DefaultColumnFilter) : (filterTypes[defaultheader[0][header].filter] && filterTypes[defaultheader[0][header].filter].fn ? filterTypes[defaultheader[0][header].filter].fn : (defaultheader[0][header].filter==='none'?"":DefaultColumnFilter))) : ""); const filtertype = (showColumnFilter ? (!isString && filterTypes[defaultheader[0][header].filter] && filterTypes[defaultheader[0][header].filter].type) ? filterTypes[defaultheader[0][header].filter].type : 'fuzzyText' : ""); columns.push({ Header: isString ? defaultheader[0][header] : defaultheader[0][header].name, id: isString ? defaultheader[0][header] : defaultheader[0][header].name, accessor: header, filter: filtertype, Filter: filterFn, disableSortBy: doServersideFilter?(typeof disableSortBy !== 'undefined' ? disableSortBy : true):(disableSortBy || false), disableFilters: doServersideFilter?typeof disableFilter !== 'undefined' ? disableFilter : true:false, //minResizeWidth: 50, //*** TO REMOVE - INCOMING CHANGE */ // filter: (showColumnFilter?((!isString && defaultheader[0][header].filter=== 'date') ? 'includes' : 'fuzzyText'):""), // Filter: (showColumnFilter?(isString ? DefaultColumnFilter : (filterTypes[defaultheader[0][header].filter] ? filterTypes[defaultheader[0][header].filter] : DefaultColumnFilter)):""), isVisible: true, Cell: props => { return <div style={{...props.style}}> {updatedCellvalue(header, props.value, defaultheader[0][header])} </div>}, }) }) //Optional Columns optionaldataheader.forEach(header => { const isString = typeof optionalheader[0][header] === 'string'; const disableSortBy = optionalheader[0][header].disableSortBy; const disableFilter = optionalheader[0][header].disableFilters; const filterFn = (showColumnFilter ? (isString ? (optionalheader[0][header].filter==='none'?"":DefaultColumnFilter) : (filterTypes[optionalheader[0][header].filter] && filterTypes[optionalheader[0][header].filter].fn ? filterTypes[optionalheader[0][header].filter].fn : (optionalheader[0][header].filter==='none'?"":DefaultColumnFilter))) : ""); const filtertype = (showColumnFilter ? (!isString && filterTypes[optionalheader[0][header].filter]) ? (filterTypes[optionalheader[0][header].filter].type || filterTypes[optionalheader[0][header].filter]) : 'fuzzyText' : ""); columns.push({ Header: isString ? optionalheader[0][header] : optionalheader[0][header].name, id: isString ? header : optionalheader[0][header].name, accessor: header, filter: filtertype, Filter: filterFn, disableSortBy: doServersideFilter?typeof disableSortBy !== 'undefined' ? disableSortBy : true:false, disableFilters: doServersideFilter?typeof disableFilter !== 'undefined' ? disableFilter : true:false, isVisible: false, Cell: props => <div style={{...props.style}}> {updatedCellvalue(header, props.value, optionalheader[0][header])} </div>, }) }); let togglecolumns = localStorage.getItem(tablename); if (togglecolumns) { togglecolumns = JSON.parse(togglecolumns); columns.forEach(column => { let tcolumn = _.find(togglecolumns, { Header: column.Header }); column['isVisible'] = (tcolumn) ? tcolumn.isVisible : column.isVisible; }); } function updatedCellvalue(key, value, properties) { try { if (typeof value == "boolean") { return value.toString(); } else if (typeof value == "string") { const format = properties ? properties.format : 'YYYY-MM-DD HH:mm:ss'; const dateval = moment(value, moment.ISO_8601).format(format); if (dateval !== 'Invalid date') { return dateval; } } } catch (err) { console.error('Error', err) } return value; }; /** * To fetch data from server side - Start */ // const [loading, setLoading] = React.useState(false); const [currentPage, setCurrentPage] = React.useState(0); const fetchData = React.useCallback( ({ state, setLoading }) => { loadServerData(state, setLoading, true); }, []); const loadServerData = (state, setLoading, onload) => { //setLoading(true); loadingStatus = true; setCurrentPage(state.pageIndex); if(props.callBackFunction) { if(storeFilter) { if (onload) { let filters = UtilService.localStore({ type: 'get', key: tablename }); UtilService.localStore({ type: 'set', key: tablename, value: filters}); } else { UtilService.localStore({ type: 'set', key: tablename, value: state.filters}); } } const promises = [props.callBackFunction(state)]; Promise.all(promises).then(async responses => { tbldata = responses[0][0]; if (tbldata) { //setData(tbldata); //setPageCount(Math.ceil(responses[0][1])); pageCount = await Math.ceil(responses[0][1]); if (setLoading) { setLoading(false); } loadingStatus = false; } }); } else { if(tbldata) { const startRow = state.pageSize * state.pageIndex; const endRow = startRow + state.pageSize; //setData(tbldata.slice(startRow, endRow)); //setPageCount(Math.ceil(tbldata.length)); data = tbldata.slice(startRow, endRow); pageCount = Math.ceil(tbldata.length); setLoading(false); loadingStatus = false; } } } // Set the filterCallback function to load on filter changes filterCallback = loadServerData; // Set the reloadCallback function in the parent if it has passed the callback function. if (props.setTableReloadFunction) { props.setTableReloadFunction(loadServerData); } // Callback function to load on option list values showFilterOption = props.showFilterOption; //If page not load with fresh data then set existing data, otherwise it will reset the checkbox selection in table if (!pageUpdated) { data = tmpTableData; } return ( <div> <Table fetchData={fetchData} pageCount={pageCount} currentPage={currentPage} dataFetchStatus={loadingStatus} columns={columns} data={data} defaultheader={defaultheader[0]} optionalheader={optionalheader[0]} showAction={props.showaction} defaultSortColumn={defaultSortColumn} tablename={tablename} defaultpagesize={defaultpagesize} columnOrders={props.columnOrders} toggleBySorting={(sortData) => {if(props.toggleBySorting){props.toggleBySorting(sortData)}}} onColumnToggle={props.onColumnToggle} lsKeySortColumn={props.lsKeySortColumn} descendingColumn={props.descendingColumn} ignoreSorting={props.ignoreSorting} setTableState={props.setTableState} /> </div> ) } export default ViewTable