@@ -2,6 +2,7 @@ import * as React from 'react';
22import { SortByDirection , Th , Thead , Tr } from '@patternfly/react-table' ;
33import _ from 'lodash' ;
44import { Column , ColumnGroup , ColumnsId , getColumnGroups , getFullColumnName } from '../../utils/columns' ;
5+ import './netflow-table-header.css' ;
56
67export type HeadersState = {
78 nestedHeaders : ColumnGroup [ ] ;
@@ -14,28 +15,93 @@ export const NetflowTableHeader: React.FC<{
1415 sortId : ColumnsId ;
1516 sortDirection : SortByDirection ;
1617 columns : Column [ ] ;
18+ setColumns : ( v : Column [ ] ) => void ;
1719 tableWidth : number ;
18- } > = ( { onSort, sortId, sortDirection, columns, tableWidth } ) => {
20+ isDark ?: boolean ;
21+ } > = ( { onSort, sortId, sortDirection, columns, setColumns, tableWidth, isDark } ) => {
22+ const draggedElement = React . useRef < HTMLElement > ( ) ;
23+
1924 const [ headersState , setHeadersState ] = React . useState < HeadersState > ( {
2025 nestedHeaders : [ ] ,
2126 useNested : false ,
2227 headers : [ ]
2328 } ) ;
2429
30+ const onDragStart = React . useCallback ( ( e : React . DragEvent < HTMLElement > ) => {
31+ const target = e . currentTarget ;
32+ target . classList . add ( 'dragged' ) ;
33+ draggedElement . current = target ;
34+ } , [ ] ) ;
35+
36+ const clearDragEffects = ( ) => {
37+ document . querySelectorAll ( '.netobserv-header' ) . forEach ( e => {
38+ if ( e . classList . contains ( 'dragged' ) ) {
39+ e . classList . remove ( 'dragged' ) ;
40+ }
41+
42+ if ( e . classList . contains ( 'dropzone' ) ) {
43+ e . classList . remove ( 'dropzone' ) ;
44+ }
45+ } ) ;
46+ } ;
47+
48+ const onDrop = React . useCallback (
49+ ( e : React . DragEvent < HTMLElement > ) => {
50+ if ( ! e . currentTarget || ! draggedElement . current ) {
51+ console . error ( 'onDrop called while currentTarget or draggedElement ref missing' ) ;
52+ return ;
53+ }
54+
55+ if (
56+ ( e . currentTarget . classList . contains ( 'nested' ) && draggedElement . current . classList . contains ( 'nested' ) ) ||
57+ ( e . currentTarget . classList . contains ( 'column' ) && draggedElement . current . classList . contains ( 'column' ) )
58+ ) {
59+ const srcIndex = Number ( draggedElement . current . getAttribute ( 'data-index' ) ) ;
60+ const srcColSpan = Number ( draggedElement . current ! . getAttribute ( 'colSpan' ) ) ;
61+ const dstIndex = Number ( e . currentTarget . getAttribute ( 'data-index' ) ) ;
62+
63+ const result = [ ...columns ] ;
64+ const removed = result . splice ( srcIndex , srcColSpan ) ;
65+ result . splice ( dstIndex , 0 , ...removed ) ;
66+ setColumns ( result ) ;
67+ }
68+
69+ e . preventDefault ( ) ;
70+ } ,
71+ [ columns , setColumns ]
72+ ) ;
73+
2574 const getNestedTableHeader = React . useCallback (
2675 ( nh : ColumnGroup ) => {
2776 return (
2877 < Th
78+ className = { `netobserv-header nested ${ isDark ? 'dark' : '' } ` }
2979 data-test = { `nested-th-${ nh . title || 'empty' } ` }
80+ data-index = { columns . indexOf ( nh . columns [ 0 ] ) }
3081 key = { `nested-${ nh . title } -${ headersState . nestedHeaders . indexOf ( nh ) } ` }
82+ id = { `nested-${ headersState . nestedHeaders . indexOf ( nh ) } ` }
3183 hasRightBorder = { _ . last ( headersState . nestedHeaders ) !== nh }
3284 colSpan = { nh . columns . length }
85+ draggable
86+ onDragStart = { onDragStart }
87+ onDragOver = { e => {
88+ if ( draggedElement . current ?. classList . contains ( 'nested' ) ) {
89+ e . currentTarget . classList . add ( 'dropzone' ) ;
90+ }
91+ e . preventDefault ( ) ;
92+ } }
93+ onDragLeave = { e => {
94+ e . currentTarget . classList . remove ( 'dropzone' ) ;
95+ e . preventDefault ( ) ;
96+ } }
97+ onDrop = { onDrop }
98+ onDragEnd = { clearDragEffects }
3399 >
34100 { nh . title }
35101 </ Th >
36102 ) ;
37103 } ,
38- [ headersState . nestedHeaders ]
104+ [ columns , headersState . nestedHeaders , isDark , onDragStart , onDrop ]
39105 ) ;
40106
41107 const getTableHeader = React . useCallback (
@@ -44,9 +110,12 @@ export const NetflowTableHeader: React.FC<{
44110 headersState . useNested && headersState . nestedHeaders . find ( nh => _ . last ( nh . columns ) === c ) !== undefined ;
45111 return (
46112 < Th
113+ className = { `netobserv-header column ${ isDark ? 'dark' : '' } ` }
47114 data-test = { `th-${ c . id } ` }
115+ data-index = { columns . indexOf ( c ) }
48116 hasRightBorder = { showBorder }
49117 key = { c . id }
118+ id = { c . id }
50119 sort = { {
51120 sortBy : {
52121 index : columns . findIndex ( c => c . id === sortId ) ,
@@ -55,6 +124,21 @@ export const NetflowTableHeader: React.FC<{
55124 onSort : ( event , index , direction ) => onSort ( c . id , direction ) ,
56125 columnIndex : columns . indexOf ( c )
57126 } }
127+ colSpan = { 1 }
128+ draggable
129+ onDragStart = { onDragStart }
130+ onDragOver = { e => {
131+ if ( draggedElement . current ?. classList . contains ( 'column' ) ) {
132+ e . currentTarget . classList . add ( 'dropzone' ) ;
133+ }
134+ e . preventDefault ( ) ;
135+ } }
136+ onDragLeave = { e => {
137+ e . currentTarget . classList . remove ( 'dropzone' ) ;
138+ e . preventDefault ( ) ;
139+ } }
140+ onDrop = { onDrop }
141+ onDragEnd = { clearDragEffects }
58142 modifier = "wrap"
59143 style = { { width : `${ Math . floor ( ( 100 * c . width ) / tableWidth ) } %` } }
60144 info = { c . tooltip ? { tooltip : c . tooltip } : undefined }
@@ -63,7 +147,18 @@ export const NetflowTableHeader: React.FC<{
63147 </ Th >
64148 ) ;
65149 } ,
66- [ columns , headersState . nestedHeaders , headersState . useNested , onSort , sortDirection , sortId , tableWidth ]
150+ [
151+ columns ,
152+ headersState . nestedHeaders ,
153+ headersState . useNested ,
154+ isDark ,
155+ onDragStart ,
156+ onDrop ,
157+ onSort ,
158+ sortDirection ,
159+ sortId ,
160+ tableWidth
161+ ]
67162 ) ;
68163
69164 React . useEffect ( ( ) => {
0 commit comments