@@ -69,6 +69,11 @@ $(document).ready(function () {
69
69
]
70
70
} ) ;
71
71
72
+ const hostnameColumnName = 'hostname' ;
73
+ const queueNameColumnName = 'queueName' ;
74
+ const tableIdColumnName = 'tableId' ;
75
+ const durationColumnName = 'duration' ;
76
+
72
77
// Create a table for running compactors
73
78
runningTable = $ ( '#runningTable' ) . DataTable ( {
74
79
"ajax" : {
@@ -94,7 +99,8 @@ $(document).ready(function () {
94
99
}
95
100
] ,
96
101
"columns" : [ {
97
- "data" : "server"
102
+ "data" : "server" ,
103
+ "name" : hostnameColumnName
98
104
} ,
99
105
{
100
106
"data" : "kind"
@@ -103,10 +109,12 @@ $(document).ready(function () {
103
109
"data" : "status"
104
110
} ,
105
111
{
106
- "data" : "queueName"
112
+ "data" : "queueName" ,
113
+ "name" : queueNameColumnName
107
114
} ,
108
115
{
109
- "data" : "tableId"
116
+ "data" : "tableId" ,
117
+ "name" : tableIdColumnName
110
118
} ,
111
119
{
112
120
"data" : "numFiles"
@@ -132,7 +140,8 @@ $(document).ready(function () {
132
140
"data" : "lastUpdate"
133
141
} ,
134
142
{
135
- "data" : "duration"
143
+ "data" : "duration" ,
144
+ "name" : durationColumnName
136
145
} ,
137
146
{ // more column settings
138
147
"class" : "details-control" ,
@@ -143,6 +152,127 @@ $(document).ready(function () {
143
152
]
144
153
} ) ;
145
154
155
+ function handleFilterKeyup ( input , feedbackElement , columnName ) {
156
+ if ( isValidRegex ( input ) || input === '' ) { // if valid, apply the filter
157
+ feedbackElement . hide ( ) ;
158
+ $ ( this ) . removeClass ( 'is-invalid' ) ;
159
+ const isRegex = true ;
160
+ const smartEnabled = false ;
161
+ runningTable
162
+ . column ( `${ columnName } :name` )
163
+ . search ( input , isRegex , smartEnabled )
164
+ . draw ( ) ;
165
+ } else { // if invalid, show the warning
166
+ feedbackElement . show ( ) ;
167
+ $ ( this ) . addClass ( 'is-invalid' ) ;
168
+ }
169
+ }
170
+
171
+ $ ( '#hostname-filter' ) . on ( 'keyup' , function ( ) {
172
+ handleFilterKeyup . call ( this , this . value , $ ( '#hostname-feedback' ) , hostnameColumnName ) ;
173
+ } ) ;
174
+
175
+ $ ( '#queue-filter' ) . on ( 'keyup' , function ( ) {
176
+ handleFilterKeyup . call ( this , this . value , $ ( '#queue-feedback' ) , queueNameColumnName ) ;
177
+ } ) ;
178
+
179
+ $ ( '#tableid-filter' ) . on ( 'keyup' , function ( ) {
180
+ handleFilterKeyup . call ( this , this . value , $ ( '#tableid-feedback' ) , tableIdColumnName ) ;
181
+ } ) ;
182
+
183
+ $ ( '#duration-filter' ) . on ( 'keyup' , function ( ) {
184
+ runningTable . draw ( ) ;
185
+ } ) ;
186
+
187
+ // Clear Filters button handler
188
+ $ ( '#clear-filters' ) . on ( 'click' , function ( ) {
189
+ $ ( this ) . prop ( 'disabled' , true ) ; // disable the clear button
190
+
191
+ // set the filter inputs to empty and trigger the keyup event to clear the filters
192
+ $ ( '#hostname-filter' ) . val ( '' ) . trigger ( 'keyup' ) ;
193
+ $ ( '#queue-filter' ) . val ( '' ) . trigger ( 'keyup' ) ;
194
+ $ ( '#tableid-filter' ) . val ( '' ) . trigger ( 'keyup' ) ;
195
+ $ ( '#duration-filter' ) . val ( '' ) . trigger ( 'keyup' ) ;
196
+
197
+ $ ( this ) . prop ( 'disabled' , false ) ; // re-enable the clear
198
+ } ) ;
199
+
200
+ // Custom filter function for duration
201
+ $ . fn . dataTable . ext . search . push ( function ( settings , data , dataIndex ) {
202
+ if ( settings . nTable . id !== 'runningTable' ) {
203
+ return true ;
204
+ }
205
+
206
+ const durationColIndex = runningTable . column ( `${ durationColumnName } :name` ) . index ( ) ;
207
+ const durationStr = data [ durationColIndex ] ;
208
+ const durationSeconds = parseDuration ( durationStr ) ;
209
+
210
+ const input = $ ( '#duration-filter' ) . val ( ) . trim ( ) ;
211
+ if ( input === '' ) {
212
+ $ ( '#duration-feedback' ) . hide ( ) ;
213
+ return true ;
214
+ }
215
+
216
+ const match = validateDurationInput ( input ) ;
217
+ if ( ! match ) {
218
+ $ ( '#duration-feedback' ) . show ( ) ;
219
+ return false ;
220
+ }
221
+
222
+ $ ( '#duration-feedback' ) . hide ( ) ;
223
+ const operator = match [ 1 ] ;
224
+ const value = parseInt ( match [ 2 ] ) ;
225
+ const unit = match [ 3 ] ;
226
+ const filterSeconds = convertToSeconds ( value , unit ) ;
227
+
228
+ switch ( operator ) {
229
+ case '>' :
230
+ return durationSeconds > filterSeconds ;
231
+ case '>=' :
232
+ return durationSeconds >= filterSeconds ;
233
+ case '<' :
234
+ return durationSeconds < filterSeconds ;
235
+ case '<=' :
236
+ return durationSeconds <= filterSeconds ;
237
+ default :
238
+ console . error ( `Unexpected operator "${ operator } " encountered in duration filter.` ) ;
239
+ return true ;
240
+ }
241
+ } ) ;
242
+
243
+ // Helper function to convert duration strings to seconds
244
+ function convertToSeconds ( value , unit ) {
245
+ switch ( unit . toLowerCase ( ) ) {
246
+ case 's' :
247
+ return value ;
248
+ case 'm' :
249
+ return value * 60 ;
250
+ case 'h' :
251
+ return value * 3600 ;
252
+ case 'd' :
253
+ return value * 86400 ;
254
+ default :
255
+ console . error ( `Unexpected unit "${ unit } " encountered in duration filter. Defaulting to seconds.` ) ;
256
+ return value ;
257
+ }
258
+ }
259
+
260
+ // Helper function to validate duration input. Makes sure that the input is in the format of '<operator> <value> <unit>'
261
+ function validateDurationInput ( input ) {
262
+ return input . match ( / ^ ( [ < > ] = ? ) \s * ( \d + ) ( [ s m h d ] ) $ / i) ;
263
+ }
264
+
265
+ /**
266
+ * @param {number } durationStr duration in milliseconds
267
+ * @returns duration in seconds
268
+ */
269
+ function parseDuration ( durationStr ) {
270
+ // Assuming durationStr is in milliseconds
271
+ const milliseconds = parseInt ( durationStr , 10 ) ;
272
+ const seconds = milliseconds / 1000 ;
273
+ return seconds ;
274
+ }
275
+
146
276
// Create a table for compaction coordinator
147
277
coordinatorTable = $ ( '#coordinatorTable' ) . DataTable ( {
148
278
"ajax" : {
@@ -344,3 +474,13 @@ function refreshRunning() {
344
474
// user paging is not reset on reload
345
475
ajaxReloadTable ( runningTable ) ;
346
476
}
477
+
478
+ // Helper function to validate regex
479
+ function isValidRegex ( input ) {
480
+ try {
481
+ new RegExp ( input ) ;
482
+ return true ;
483
+ } catch ( e ) {
484
+ return false ;
485
+ }
486
+ }
0 commit comments