diff --git a/SAS/TMSS/frontend/tmss_webapp/package.json b/SAS/TMSS/frontend/tmss_webapp/package.json index 36c5a54e803ee8f26341c1f4dbe90fdd65c31e3d..b2ab4d9cd7dbf242a366dea5e6ebbb6e42a5fc04 100644 --- a/SAS/TMSS/frontend/tmss_webapp/package.json +++ b/SAS/TMSS/frontend/tmss_webapp/package.json @@ -36,6 +36,7 @@ "prop-types": "^15.7.2", "react": "^16.13.1", "react-app-polyfill": "^1.0.6", + "react-beautiful-dnd": "^13.1.0", "react-beforeunload": "^2.4.0", "react-bootstrap": "^1.0.1", "react-bootstrap-datetimepicker": "0.0.22", diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js index 129b8232bf12d6353bc1507d27f1b17a1821b683..c45f8731d806714c7c43c1626bac45a2dbe5d9a2 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/components/ViewTable.js @@ -23,7 +23,7 @@ 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"; @@ -56,8 +56,21 @@ 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 + +const getItemStyle = ({ isDragging, isDropAnimating }, draggableStyle) => ({ + ...draggableStyle, + // some basic styles to make the items look a bit nicer + userSelect: "none", + ...(!isDragging && { transform: "translate(0,0)" }), + ...(isDropAnimating && { transitionDuration: "0.001s" }) + + // styles we need to apply on draggables +}); + function GlobalFilter({ preGlobalFilteredRows, globalFilter, @@ -1805,6 +1818,7 @@ function Table(props) { useColumnOrder, useExportData ); + 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 @@ -2045,31 +2059,78 @@ function Table(props) { <table {...getTableProps()} data-testid="viewtable" className="viewtable" > <thead> {headerGroups.map(headerGroup => ( - <tr {...headerGroup.getHeaderGroupProps()}> - {headerGroup.headers.map(column => ( - <th onClick={() => { + <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); + } + }} + > + <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={!column.accessor} + > + {(provided, snapshot) => { + return ( + <th onClick={() => { if(!doServersideFilter) { - toggleBySorting({ 'id': column.id, desc: (column.isSortedDesc != undefined ? !column.isSortedDesc : false) }) + toggleBySorting({ 'id': column.id, desc: (column.isSortedDesc != undefined ? !column.isSortedDesc : false) }); } - }}> - <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>) : "" - : "" - } - </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> - ))} - </tr> + }}> + <div {...column.getHeaderProps(column.getSortByToggleProps())} > + <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]}> + {column.canFilter && column.Header !== 'Action' ? column.render('Filter') : null} + </div> + } + </th> + ); + }} + </Draggable> + ))} + </tr> + )} + </Droppable> + </DragDropContext> ))} {(doServersideFilter && loading) && <tr style={{height: "5px"}}><td colSpan={columns.length} style={{padding: "0px"}}>