github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/static/js/event-handlers.js (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 'use strict'; 18 19 function setupEventHandlers() { 20 $('#filter-input').on('keyup', filterInputHandler); 21 22 $('#run-filter-btn').on('click', runFilterBtnHandler); 23 $("#query-builder-btn").on("click", runFilterBtnHandler); 24 $("#live-tail-btn").on("click", runLiveTailBtnHandler); 25 26 $('#available-fields').on('click', availableFieldsClickHandler); 27 $('#available-fields .select-unselect-header').on('click','.select-unselect-checkbox', toggleAllAvailableFieldsHandler); 28 $('#available-fields .select-unselect-header').on('click','.select-unselect-checkmark', toggleAllAvailableFieldsHandler); 29 $('#available-fields .fields').on('click', '.available-fields-dropdown-item', availableFieldsSelectHandler); 30 31 $('#corner-popup').on('click', '.corner-btn-close', hideError); 32 33 $('#search-query-btn').on('click', searchSavedQueryHandler); 34 35 $('#query-language-btn').on('show.bs.dropdown', qLangOnShowHandler); 36 $('#query-language-btn').on('hide.bs.dropdown', qLangOnHideHandler); 37 $('#query-language-options .query-language-option').on('click', setQueryLangHandler); 38 39 $('#index-btn').on('show.bs.dropdown', indexOnShowHandler); 40 $('#index-btn').on('hide.bs.dropdown', indexOnHideHandler); 41 $('#available-indexes').on('click', '.index-dropdown-item', indexOnSelectHandler); 42 43 $('#logs-result-container').on('click', '.hide-column', hideColumnHandler); 44 45 $('#log-opt-single-btn').on('click', logOptionSingleHandler); 46 $('#log-opt-multi-btn').on('click', logOptionMultiHandler); 47 $('#log-opt-table-btn').on('click', logOptionTableHandler); 48 49 $('#date-picker-btn').on('show.bs.dropdown', showDatePickerHandler); 50 $('#date-picker-btn').on('hide.bs.dropdown', hideDatePickerHandler); 51 $('#reset-timepicker').on('click', resetDatePickerHandler); 52 53 $('.panelEditor-container #date-start').on('change', getStartDateHandler); 54 $('.panelEditor-container #date-end').on('change', getEndDateHandler); 55 $('.panelEditor-container #time-start').on('change', getStartTimeHandler); 56 $('.panelEditor-container #time-end').on('change', getEndTimeHandler); 57 $('.panelEditor-container #customrange-btn').on('click', customRangeHandler); 58 59 $('#date-start').on('change', getStartDateHandler); 60 $('#date-end').on('change', getEndDateHandler); 61 62 $('#time-start').on('change', getStartTimeHandler); 63 $('#time-end').on('change', getEndTimeHandler); 64 $('#customrange-btn').on('click', customRangeHandler); 65 66 $('.range-item').on('click', rangeItemHandler) 67 $('.db-range-item').on('click', dashboardRangeItemHandler) 68 69 $('.ui-widget input').on('keyup', saveqInputHandler); 70 71 $(window).bind('popstate', windowPopStateHandler); 72 } 73 74 75 function windowPopStateHandler(evt) { 76 if(location.href.includes("index.html")){ 77 let state = evt.originalEvent.state; 78 if (state !== null) { 79 data = getInitialSearchFilter(true, false); 80 } 81 resetDashboard(); 82 wsState = 'query'; 83 doSearch(data); 84 } 85 } 86 87 function showDatePickerHandler(evt){ 88 evt.stopPropagation(); 89 $('#daterangepicker').toggle(); 90 $(evt.currentTarget).toggleClass('active'); 91 } 92 93 function hideDatePickerHandler(){ 94 $('#date-picker-btn').removeClass('active'); 95 } 96 97 function resetDatePickerHandler(evt){ 98 evt.stopPropagation(); 99 resetCustomDateRange(); 100 $.each($(".range-item.active"), function () { 101 $(this).removeClass('active'); 102 }); 103 104 } 105 function getStartDateHandler(evt){ 106 let inputDate = new Date(this.value); 107 filterStartDate = inputDate.getTime(); 108 $(this).addClass("active"); 109 Cookies.set('customStartDate', this.value); 110 } 111 112 function getEndDateHandler(evt){ 113 let inputDate = new Date(this.value); 114 filterEndDate = inputDate.getTime(); 115 $(this).addClass("active"); 116 Cookies.set('customEndDate', this.value); 117 } 118 119 function getStartTimeHandler(){ 120 let selectedTime = $(this).val(); 121 let temp = ((Number(selectedTime.split(':')[0]) * 60 + Number(selectedTime.split(':')[1])) * 60) * 1000; 122 //check if filterStartDate is a number or now-* 123 if (!isNaN(filterStartDate)) { 124 filterStartDate = filterStartDate + temp; 125 } else { 126 let start = new Date(); 127 start.setUTCHours(0,0,0,0); 128 filterStartDate = start.getTime() + temp; 129 } 130 $(this).addClass("active"); 131 Cookies.set('customStartTime', selectedTime); 132 } 133 134 function getEndTimeHandler(){ 135 let selectedTime = $(this).val(); 136 let temp = ((Number(selectedTime.split(':')[0]) * 60 + Number(selectedTime.split(':')[1])) * 60) * 1000; 137 if (!isNaN(filterEndDate)) { 138 filterEndDate = filterEndDate + temp; 139 } else { 140 let start = new Date(); 141 start.setUTCHours(0,0,0,0); 142 filterEndDate = start.getTime() + temp; 143 } 144 $(this).addClass("active"); 145 Cookies.set('customEndTime', selectedTime); 146 } 147 148 function customRangeHandler(evt){ 149 $.each($(".range-item.active"), function () { 150 $(this).removeClass('active'); 151 }); 152 $.each($(".db-range-item.active"), function () { 153 $(this).removeClass('active'); 154 }); 155 datePickerHandler(filterStartDate, filterEndDate, "custom") 156 157 if(currentPanel) { 158 if(currentPanel.queryData) { 159 if(currentPanel.chartType === "Line Chart" || currentPanel.queryType === "metrics") { 160 currentPanel.queryData.start = filterStartDate.toString(); 161 currentPanel.queryData.end = filterEndDate.toString(); 162 } else { 163 currentPanel.queryData.startEpoch = filterStartDate 164 currentPanel.queryData.endEpoch = filterEndDate 165 } 166 } 167 } else if($(`#viewPanel-container`).css('display').toLowerCase() !== 'none') { 168 // if user is on view panel screen 169 // get panel-index by attribute 170 let panelIndex = ($(`#viewPanel-container .panel`).attr('panel-index')); 171 // if panel has some stored query data, reset it 172 if(localPanels[panelIndex].queryData) { 173 delete localPanels[panelIndex].queryRes 174 if(localPanels[panelIndex].chartType === "Line Chart" || localPanels[panelIndex].queryType === "metrics") { 175 localPanels[panelIndex].queryData.start = filterStartDate.toString(); 176 localPanels[panelIndex].queryData.end = filterEndDate.toString(); 177 } else { 178 localPanels[panelIndex].queryData.startEpoch = filterStartDate 179 localPanels[panelIndex].queryData.endEpoch = filterEndDate 180 } 181 } 182 displayPanelView(panelIndex); 183 } else if(!currentPanel) { 184 // if user is on dashboard screen 185 localPanels.forEach(panel => { 186 delete panel.queryRes 187 if(panel.queryData) { 188 if(panel.chartType === "Line Chart" || panel.queryType === "metrics") { 189 panel.queryData.start = filterStartDate.toString(); 190 panel.queryData.end = filterEndDate.toString(); 191 } else { 192 panel.queryData.startEpoch = filterStartDate 193 panel.queryData.endEpoch = filterEndDate 194 } 195 } 196 }) 197 displayPanels(); 198 } 199 } 200 201 function rangeItemHandler(evt){ 202 resetCustomDateRange(); 203 $.each($(".range-item.active"), function () { 204 $(this).removeClass('active'); 205 }); 206 $(evt.currentTarget).addClass('active'); 207 datePickerHandler($(this).attr('id'), "now", $(this).attr('id')) 208 } 209 210 function dashboardRangeItemHandler(evt){ 211 resetCustomDateRange(); 212 $.each($(".db-range-item.active"), function () { 213 $(this).removeClass('active'); 214 }); 215 $(evt.currentTarget).addClass('active'); 216 datePickerHandler($(this).attr('id'), "now", $(this).attr('id')) 217 218 // if user is on edit panel screen 219 if(currentPanel) { 220 if(currentPanel.queryData) { 221 if(currentPanel.chartType === "Line Chart" || currentPanel.queryType === "metrics") { 222 currentPanel.queryData.start = filterStartDate.toString(); 223 currentPanel.queryData.end = filterEndDate.toString(); 224 } else { 225 currentPanel.queryData.startEpoch = filterStartDate 226 currentPanel.queryData.endEpoch = filterEndDate 227 } 228 } 229 } else if($(`#viewPanel-container`).css('display').toLowerCase() !== 'none') { 230 // if user is on view panel screen 231 // get panel-index by attribute 232 let panelIndex = ($(`#viewPanel-container .panel`).attr('panel-index')); 233 // if panel has some stored query data, reset it 234 if(localPanels[panelIndex].queryData) { 235 delete localPanels[panelIndex].queryRes 236 if(localPanels[panelIndex].chartType === "Line Chart" || localPanels[panelIndex].queryType === "metrics") { 237 localPanels[panelIndex].queryData.start = filterStartDate.toString(); 238 localPanels[panelIndex].queryData.end = filterEndDate.toString(); 239 } else { 240 localPanels[panelIndex].queryData.startEpoch = filterStartDate 241 localPanels[panelIndex].queryData.endEpoch = filterEndDate 242 } 243 } 244 displayPanelView(panelIndex) 245 } else if(!currentPanel) { 246 // if user is on dashboard screen 247 localPanels.forEach(panel => { 248 delete panel.queryRes 249 if(panel.queryData) { 250 if(panel.chartType === "Line Chart" || panel.queryType === "metrics") { 251 panel.queryData.start = filterStartDate.toString(); 252 panel.queryData.end = filterEndDate.toString(); 253 } else { 254 panel.queryData.startEpoch = filterStartDate 255 panel.queryData.endEpoch = filterEndDate 256 } 257 } 258 }) 259 260 displayPanels(); 261 } 262 } 263 function resetCustomDateRange(){ 264 // clear custom selections 265 $('#date-start').val(""); 266 $('#date-end').val(""); 267 $('#time-start').val("00:00"); 268 $('#time-end').val("00:00"); 269 $('#date-start').removeClass('active'); 270 $('#date-end').removeClass('active'); 271 $('#time-start').removeClass('active'); 272 $('#time-end').removeClass('active'); 273 Cookies.remove('customStartDate'); 274 Cookies.remove('customEndDate'); 275 Cookies.remove('customStartTime'); 276 Cookies.remove('customEndTime'); 277 } 278 function hideColumnHandler(evt) { 279 evt.preventDefault(); 280 evt.stopPropagation(); 281 282 availableFieldsSelectHandler(evt); 283 } 284 285 function setQueryLangHandler(e) { 286 $('.query-language-option').removeClass('active'); 287 let currentTab = $("#custom-code-tab").tabs("option", "active"); 288 let selectedQueryLanguageId = $(this).attr("id").split("-")[1]; 289 if (selectedQueryLanguageId !== "3" && currentTab === 0) { 290 $("#custom-code-tab").tabs("option", "active", 1); 291 } else if (selectedQueryLanguageId !== "3" && currentTab === 1) { 292 $("#custom-code-tab").tabs("option", "disabled", [0]); 293 } else if (selectedQueryLanguageId === "3" && currentTab === 1) { 294 $("#custom-code-tab").tabs("option", "disabled", []); 295 } 296 $('#query-language-btn span').html($(this).html()); 297 displayQueryLangToolTip(selectedQueryLanguageId); 298 $(this).addClass('active'); 299 } 300 301 function qLangOnShowHandler() { 302 $("#query-language-btn").addClass("active"); 303 304 } 305 306 function qLangOnHideHandler() { 307 $('#query-language-btn').removeClass('active'); 308 } 309 310 function indexOnShowHandler(){ 311 $('#index-btn').addClass('active'); 312 if (Cookies.get('IndexList')) { 313 let allAvailableIndices = []; 314 let selectedIndexList = (Cookies.get('IndexList')).split(','); 315 // Get all available indices 316 317 $.each($(".index-dropdown-item"), function () { 318 allAvailableIndices.push($(this).data("index")); 319 }); 320 let allSelectedIndices = _.intersection(selectedIndexList, allAvailableIndices); 321 $.each($(".index-dropdown-item"), function () { 322 let indexName = $(this).data("index"); 323 if(allSelectedIndices.includes(indexName)){ 324 $(this).addClass('active'); 325 } 326 }); 327 selectedSearchIndex = allSelectedIndices.join(","); 328 Cookies.set('IndexList', allSelectedIndices.join(",")); 329 } 330 } 331 332 function indexOnHideHandler(){ 333 $('#index-btn').removeClass('active'); 334 } 335 336 function indexOnSelectHandler(evt) { 337 evt.stopPropagation(); 338 339 // If the user chooses any index from dropdown, un-highlight the "*" from the dropdown 340 if ($(this).data("index") !== "*"){ 341 $(`.index-dropdown-item[data-index="*"]`).removeClass('active'); 342 } 343 344 $(evt.currentTarget).toggleClass('active'); 345 let checkedIndices = []; 346 347 $.each($(".index-dropdown-item.active"), function () { 348 checkedIndices.push($(this).data("index")); 349 }); 350 selectedSearchIndex = checkedIndices.join(","); 351 Cookies.set('IndexList', selectedSearchIndex) 352 } 353 function runLiveTailBtnHandler(evt) { 354 $(".popover").hide(); 355 evt.preventDefault(); 356 liveTailState = true; 357 if ($("#live-tail-btn").text() === "Live Tail") { 358 resetDashboard(); 359 $("#live-tail-btn").html("Cancel Live Tail"); 360 logsRowData = []; 361 total_liveTail_searched = 0; 362 wsState = "query"; 363 data = getLiveTailFilter(false, false, 1800); 364 availColNames = []; 365 createLiveTailSocket(data); 366 } else { 367 $("#live-tail-btn").html("Live Tail"); 368 liveTailState = false; 369 wsState = "cancel"; 370 data = getLiveTailFilter(false, false, 1800); 371 doLiveTailCancel(data); 372 } 373 $("#daterangepicker").hide(); 374 } 375 376 function runFilterBtnHandler(evt) { 377 $('.popover').hide(); 378 evt.preventDefault(); 379 if ( 380 $("#run-filter-btn").text() === " " || 381 $("#query-builder-btn").text() === " " 382 ) { 383 384 resetDashboard(); 385 logsRowData = []; 386 wsState = "query"; 387 data = getSearchFilter(false, false); 388 availColNames = []; 389 doSearch(data); 390 } else { 391 wsState = "cancel"; 392 data = getSearchFilter(false, false); 393 doCancel(data); 394 } 395 $('#daterangepicker').hide(); 396 } 397 398 function filterInputHandler(evt) { 399 evt.preventDefault(); 400 if ( 401 evt.keyCode === 13 && 402 ($("#run-filter-btn").text() === " " || 403 $("#query-builder-btn").text() === " ") 404 ) { 405 resetDashboard(); 406 logsRowData = []; 407 data = getSearchFilter(false, false); 408 availColNames = []; 409 doSearch(data); 410 } 411 } 412 413 414 // prevent the available fields popup from closing when you toggle an available field 415 function availableFieldsClickHandler(evt) { 416 evt.stopPropagation(); 417 } 418 419 function availableFieldsSelectHandler(evt) { 420 421 let colName = evt.currentTarget.dataset.index; 422 let encColName = string2Hex(colName); 423 // don't toggle the timestamp column 424 if (colName !== "timestamp") { 425 // toggle the column visibility 426 $(`.toggle-${encColName}`).toggleClass('active'); 427 if ($(`.toggle-${encColName}`).hasClass('active')) { 428 // Update the selectedFieldsList everytime a field is selected 429 selectedFieldsList.push(colName); 430 } else{ 431 // Everytime the field is unselected, remove it from selectedFieldsList 432 for( let i = 0; i < selectedFieldsList.length; i++){ 433 434 if ( selectedFieldsList[i] === colName) { 435 selectedFieldsList.splice(i, 1); 436 i--; 437 } 438 } 439 } 440 } 441 442 let visibleColumns = 0; 443 let totalColumns = -1; 444 445 availColNames.forEach((colName, index) => { 446 if(selectedFieldsList.includes(colName)) { 447 448 visibleColumns++; 449 totalColumns++; 450 }else{ 451 452 } 453 }) 454 455 if (visibleColumns == 1) { 456 shouldCloseAllDetails = true; 457 } else { 458 if (shouldCloseAllDetails) { 459 shouldCloseAllDetails = false; 460 } 461 } 462 let el = $('#available-fields .select-unselect-header'); 463 464 // uncheck the toggle-all fields if the selected columns count is different 465 if (visibleColumns < totalColumns) { 466 let cmClass = el.find('.select-unselect-checkmark'); 467 cmClass.remove(); 468 } 469 // We do not count time and log column 470 if (visibleColumns == totalColumns-2) { 471 472 if (theme === "light"){ 473 el.append(`<img class="select-unselect-checkmark" src="assets/available-fields-check-light.svg">`); 474 }else{ 475 el.append(`<img class="select-unselect-checkmark" src="assets/index-selection-check.svg">`); 476 } 477 478 } 479 480 if ( $('#log-opt-single-btn').hasClass('active')){ 481 hideOrShowFieldsInLineViews(); 482 } else if ($('#log-opt-multi-btn').hasClass('active')){ 483 hideOrShowFieldsInLineViews(); 484 } else if ($('#log-opt-table-btn').hasClass('active')){ 485 hideOrShowFieldsInLineViews(); 486 updateColumns(); 487 } 488 gridOptions.api.sizeColumnsToFit(); 489 updatedSelFieldList = true 490 } 491 492 function toggleAllAvailableFieldsHandler(evt) { 493 processTableViewOption(); 494 let el = $('#available-fields .select-unselect-header'); 495 let isChecked = el.find('.select-unselect-checkmark'); 496 if (isChecked.length === 0) { 497 if (theme === "light"){ 498 el.append(`<img class="select-unselect-checkmark" src="assets/available-fields-check-light.svg">`); 499 }else{ 500 el.append(`<img class="select-unselect-checkmark" src="assets/index-selection-check.svg">`); 501 } 502 let tempFieldList = []; 503 availColNames.forEach((colName, index) => { 504 $(`.toggle-${string2Hex(colName)}`).addClass('active'); 505 if(index>1){ 506 tempFieldList.push(colName); 507 } 508 gridOptions.columnApi.setColumnVisible(colName, true); 509 }); 510 selectedFieldsList = tempFieldList; 511 } else{ 512 let cmClass = el.find('.select-unselect-checkmark'); 513 cmClass.remove(); 514 515 availColNames.forEach((colName, index) => { 516 517 $(`.toggle-${string2Hex(colName)}`).removeClass('active'); 518 gridOptions.columnApi.setColumnVisible(colName, false); 519 }); 520 selectedFieldsList = [] 521 } 522 // Always hide the logs column 523 gridOptions.columnApi.setColumnVisible("logs", false); 524 } 525 526 527 function hideOrShowFieldsInLineViews(){ 528 let allSelected = true; 529 availColNames.forEach((colName, index) => { 530 let encColName = string2Hex(colName); 531 if($(`.toggle-${encColName}`).hasClass('active')){ 532 $(`.cname-hide-${encColName}`).show(); 533 } else { 534 $(`.cname-hide-${encColName}`).hide(); 535 allSelected = false; 536 } 537 }) 538 let el = $('#available-fields .select-unselect-header'); 539 let isChecked = el.find('.select-unselect-checkmark'); 540 if (allSelected) { 541 if (isChecked.length === 0){ 542 if (theme === "light") { 543 el.append(`<img class="select-unselect-checkmark" src="assets/available-fields-check-light.svg">`); 544 } else { 545 el.append(`<img class="select-unselect-checkmark" src="assets/index-selection-check.svg">`); 546 } 547 } 548 } 549 else { 550 isChecked.remove(); 551 } 552 } 553 554 function logOptionSingleHandler() { 555 $('#logs-result-container').removeClass('multi'); 556 $('#views-container .btn-group .btn').removeClass('active'); 557 $('#log-opt-single-btn').addClass('active'); 558 logsColumnDefs.forEach(function (colDef, index) { 559 if (colDef.field === "logs"){ 560 colDef.cellStyle = null; 561 colDef.autoHeight = null; 562 } 563 }); 564 gridOptions.api.setColumnDefs(logsColumnDefs); 565 gridOptions.api.resetRowHeights() 566 567 availColNames.forEach((colName, index) => { 568 gridOptions.columnApi.setColumnVisible(colName, false); 569 }); 570 gridOptions.columnApi.setColumnVisible("logs", true); 571 572 gridOptions.columnApi.autoSizeColumn(gridOptions.columnApi.getColumn("logs"), false); 573 hideOrShowFieldsInLineViews(); 574 Cookies.set('log-view', 'single-line', {expires: 365}); 575 } 576 577 function logOptionMultiHandler() { 578 $('#logs-result-container').addClass('multi'); 579 $('#views-container .btn-group .btn').removeClass('active'); 580 $('#log-opt-multi-btn').addClass('active'); 581 582 logsColumnDefs.forEach(function (colDef, index) { 583 if (colDef.field === "logs"){ 584 585 colDef.cellStyle = {'white-space': 'normal'}; 586 colDef.autoHeight = true; 587 } 588 }); 589 gridOptions.api.setColumnDefs(logsColumnDefs); 590 591 availColNames.forEach((colName, index) => { 592 gridOptions.columnApi.setColumnVisible(colName, false); 593 }); 594 gridOptions.columnApi.setColumnVisible("logs", true); 595 596 gridOptions.columnApi.autoSizeColumn(gridOptions.columnApi.getColumn("logs"), false); 597 gridOptions.api.setRowData(logsRowData); 598 hideOrShowFieldsInLineViews(); 599 gridOptions.api.sizeColumnsToFit(); 600 Cookies.set('log-view', 'multi-line', {expires: 365}); 601 } 602 603 function logOptionTableHandler() { 604 processTableViewOption(); 605 updateColumns(); 606 } 607 608 function processTableViewOption() { 609 $('#logs-result-container').addClass('multi'); 610 $('#views-container .btn-group .btn').removeClass('active'); 611 $('#log-opt-table-btn').addClass('active'); 612 logsColumnDefs.forEach(function (colDef, index) { 613 if (colDef.field === "logs"){ 614 colDef.cellStyle = null; 615 colDef.autoHeight = null; 616 } 617 }); 618 gridOptions.api.setColumnDefs(logsColumnDefs); 619 gridOptions.api.resetRowHeights() 620 gridOptions.api.sizeColumnsToFit(); 621 Cookies.set('log-view', 'table', {expires: 365}); 622 } 623 624 function themePickerHandler(evt) { 625 626 if (Cookies.get('theme')){ 627 theme = Cookies.get('theme'); 628 } else { 629 Cookies.set('theme', 'light'); 630 theme = 'light'; 631 } 632 633 if(theme === 'light'){ 634 theme = 'dark'; 635 $(evt.currentTarget).removeClass('dark-theme'); 636 $(evt.currentTarget).addClass('light-theme'); 637 } else { 638 theme = 'light'; 639 $(evt.currentTarget).removeClass('light-theme'); 640 $(evt.currentTarget).addClass('dark-theme'); 641 } 642 643 $('body').attr('data-theme', theme); 644 645 646 Cookies.set('theme', theme, {expires: 365}); 647 } 648 649 function saveqInputHandler(evt) { 650 evt.preventDefault(); 651 $(this).addClass("active"); 652 } 653 654 function searchSavedQueryHandler(evt){ 655 evt.preventDefault(); 656 $('#empty-qsearch-response').hide() 657 let searchText = $('#sq-filter-input').val(); 658 if (searchText === ""){ 659 660 return; 661 662 }else{ 663 getSearchedQuery() 664 } 665 }