github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/static/js/query-builder.js (about) 1 "use strict"; 2 let chart; 3 $(function () { 4 $("#custom-code-tab").tabs(); 5 $("#custom-chart-tab").tabs(); 6 $('#logs-view-controls').hide(); 7 }); 8 $("#custom-code-tab").tabs({ 9 activate: function (event, ui) { 10 let currentResTab = $("#custom-chart-tab").tabs("option", "active"); 11 if(currentResTab == 1){ 12 timeChart(); 13 } 14 let currentTab = $("#custom-code-tab").tabs("option", "active"); 15 if (currentTab == 0) { 16 // Query Builder Tab 17 let filterValue = $("#filter-input").val(); 18 if (filterValue != "") $("#query-input").val(filterValue); 19 if (filterValue == "") $("#query-input").val('*') 20 if(!isQueryBuilderSearch){ 21 // Clear input boxes of the query builder when a query is searched from the free text 22 $(".tags-list").empty(); 23 [firstBoxSet, secondBoxSet, thirdBoxSet] = [new Set(), new Set(), new Set()]; 24 $("#aggregations, #aggregate-attribute-text, #search-filter-text").show(); 25 } 26 $(".query-language-option").removeClass("active"); 27 $("#query-language-options #option-3").addClass("active"); 28 $("#query-language-btn span").html("Splunk QL"); 29 displayQueryLangToolTip("3"); 30 }else{ 31 // Free Text Tab 32 let filterValue = $("#query-input").val(); 33 if (filterValue != "") $("#filter-input").val(filterValue); 34 } 35 }, 36 }); 37 $("#custom-chart-tab").tabs({ 38 activate: function (event, ui) { 39 let currentTab = $("#custom-chart-tab").tabs("option", "active"); 40 if (currentTab == 0) { 41 $("#logs-view-controls").show(); 42 } else { 43 $("#logs-view-controls").hide(); 44 timeChart(); 45 } 46 }, 47 }); 48 //querybuilder and run-filter-btn text: 49 //search -> " " 50 //run -> " " 51 //cancel -> " " 52 //running -> " " 53 $(document).ready(function () { 54 $("#add-con").on("click", filterStart); 55 $("#filter-box-1").on("click", filterStart); 56 $("#add-con-second").on("click", secondFilterStart); 57 $("#filter-box-2").on("click", secondFilterStart); 58 $("#add-con-third").on("click", ThirdFilterStart); 59 $("#filter-box-3").on("click", ThirdFilterStart); 60 $("#completed").on("click", filterComplete); 61 $("#completed-second").on("click", secondFilterComplete); 62 $("#cancel-enter").on("click", cancelInfo); 63 $("#cancel-enter-second").on("click", secondCancelInfo); 64 $("#cancel-enter-third").on("click", ThirdCancelInfo); 65 66 $("#add-con").show(); 67 $("#add-con-second").show(); 68 $("#completed").hide(); 69 $("#completed-second").hide(); 70 $("#cancel-enter").hide(); 71 $("#cancel-enter-second").hide(); 72 $("#add-filter").hide(); 73 $("#add-filter-second").hide(); 74 if (thirdBoxSet.size > 0) $("#aggregations").hide(); 75 else $("#aggregations").show(); 76 if (secondBoxSet.size > 0) $("#aggregate-attribute-text").hide(); 77 else $("#aggregate-attribute-text").show(); 78 if (firstBoxSet.size > 0) $("#search-filter-text").hide(); 79 else $("#search-filter-text").show(); 80 setShowColumnInfoDialog(); 81 timeChart(); 82 }); 83 84 const tags = document.getElementById("tags"); 85 const tagSecond = document.getElementById("tags-second"); 86 const tagThird = document.getElementById("tags-third"); 87 tags.addEventListener("click", function (event) { 88 // If the clicked element has the class 'delete-button' 89 if (event.target.classList.contains("delete-button")) { 90 // Remove the parent element (the tag) 91 let str = event.target.parentNode.textContent; 92 firstBoxSet.delete(str.substring(0, str.length - 1)); 93 event.target.parentNode.remove(); 94 getSearchText(); 95 if (firstBoxSet.size > 0) $("#search-filter-text").hide(); 96 else $("#search-filter-text").show(); 97 cancelInfo(event); 98 } 99 }); 100 tagSecond.addEventListener("click", function (event) { 101 // If the clicked element has the class 'delete-button' 102 if (event.target.classList.contains("delete-button")) { 103 // Remove the parent element (the tag) 104 let str = event.target.parentNode.textContent; 105 secondBoxSet.delete(str.substring(0, str.length - 1)); 106 event.target.parentNode.remove(); 107 getSearchText(); 108 if (secondBoxSet.size > 0) $("#aggregate-attribute-text").hide(); 109 else $("#aggregate-attribute-text").show(); 110 secondCancelInfo(event); 111 } 112 }); 113 tagThird.addEventListener("click", function (event) { 114 // If the clicked element has the class 'delete-button' 115 if (event.target.classList.contains("delete-button")) { 116 // Remove the parent element (the tag) 117 let str = event.target.parentNode.textContent; 118 thirdBoxSet.delete(str.substring(0, str.length - 1)); 119 event.target.parentNode.remove(); 120 getSearchText(); 121 if (thirdBoxSet.size > 0) $("#aggregations").hide(); 122 else $("#aggregations").show(); 123 ThirdCancelInfo(event); 124 } 125 }); 126 $(document).mouseup(function (e) { 127 var firstCon = $("#add-filter"); 128 var secondCon = $("#add-filter-second"); 129 var thirdCon = $("#add-filter-third"); 130 var dropInfo = $(".ui-autocomplete"); 131 if ( 132 !firstCon.is(e.target) && 133 firstCon.has(e.target).length === 0 && 134 !dropInfo.is(e.target) && 135 dropInfo.has(e.target).length === 0 && 136 !secondCon.is(e.target) && 137 secondCon.has(e.target).length === 0 && 138 !thirdCon.is(e.target) && 139 thirdCon.has(e.target).length === 0 140 ) { 141 cancelInfo(e); 142 secondCancelInfo(e); 143 ThirdCancelInfo(e); 144 } 145 }); 146 var calculations = ["min", "max", "count", "avg", "sum"]; 147 var numericColumns = []; 148 var ifCurIsNum = false; 149 var availSymbol = []; 150 let valuesOfColumn = new Set(); 151 let paramFirst; 152 let columnsNames = []; 153 let previousStartEpoch = null; 154 let previousEndEpoch = null; 155 let previousIndexName = null; 156 157 async function filterStart(evt) { 158 evt.preventDefault(); 159 $("#column-first").attr("type", "text"); 160 $("#add-con").hide(); 161 $("#cancel-enter").show(); 162 $("#add-filter").show(); 163 $("#add-filter").css({ visibility: "visible" }); 164 $("#filter-box-1").addClass("select-box"); 165 // fetch columns if empty or startTime, endTime or Index is changed 166 if ( 167 columnsNames.length === 0 || 168 filterStartDate !== previousStartEpoch || 169 filterEndDate !== previousEndEpoch || 170 selectedSearchIndex !== previousIndexName 171 ) { 172 await getColumns(); 173 previousStartEpoch = filterStartDate; 174 previousEndEpoch = filterEndDate; 175 previousIndexName = selectedSearchIndex; 176 } 177 $("#column-first") 178 .autocomplete({ 179 source: columnsNames.sort(), 180 minLength: 0, 181 maxheight: 100, 182 select: function (event, ui) { 183 $("#symbol").attr("type", "text"); 184 //when the column name is not a number, the symbols can only be = && != 185 availSymbol = ["=", "!="]; 186 valuesOfColumn.clear(); 187 let curIsNum = false; 188 for (let i = 0; i < columnsNames.length; i++) { 189 if (ui.item.value == numericColumns[i]) { 190 curIsNum = true; 191 availSymbol = ["=", "!=", "<=", ">=", ">", "<"]; 192 break; 193 } 194 } 195 ifCurIsNum = curIsNum; 196 $("#symbol").val(""); 197 $("#value-first").val(""); 198 //check if complete btn can click 199 checkFirstBox(0); 200 let chooseColumn = ui.item.value.trim(); 201 getValuesofColumn(chooseColumn); 202 203 $("#symbol") 204 .autocomplete({ 205 source: availSymbol, 206 minLength: 0, 207 select: function (event, ui) { 208 //check if complete btn can click 209 checkFirstBox(1); 210 $("#value-first").attr("type", "text"); 211 $("#completed").show(); 212 valuesOfColumn.clear(); 213 }, 214 }) 215 .on("focus", function () { 216 if (!$(this).val().trim()) $(this).keydown(); 217 }); 218 }, 219 }) 220 .on("focus", function () { 221 if (!$(this).val().trim()) $(this).keydown(); 222 }); 223 $("#column-first").focus(); 224 } 225 function secondFilterStart(evt) { 226 evt.preventDefault(); 227 $("#filter-box-2").addClass("select-box"); 228 $("#column-second").attr("type", "text"); 229 $("#add-con-second").hide(); 230 $("#cancel-enter-second").show(); 231 $("#add-filter-second").show(); 232 $("#add-filter-second").css({ visibility: "visible" }); 233 $("#column-second").focus(); 234 } 235 async function ThirdFilterStart(evt) { 236 evt.preventDefault(); 237 $("#filter-box-3").addClass("select-box"); 238 $("#column-third").attr("type", "text"); 239 $("#add-con-third").hide(); 240 $("#add-filter-third").show(); 241 $("#add-filter-third").css({ visibility: "visible" }); 242 // fetch columns if empty or startTime, endTime or index is changed 243 if ( 244 columnsNames.length === 0 || 245 filterStartDate !== previousStartEpoch || 246 filterEndDate !== previousEndEpoch || 247 selectedSearchIndex !== previousIndexName 248 ) { 249 await getColumns(); 250 previousStartEpoch = filterStartDate; 251 previousEndEpoch = filterEndDate; 252 previousIndexName = selectedSearchIndex; 253 } 254 $("#column-third") 255 .autocomplete({ 256 source: columnsNames.sort(), 257 minLength: 0, 258 maxheight: 100, 259 select: function (event, ui) { 260 event.preventDefault(); 261 let tag = document.createElement("li"); 262 if (ui.item.value !== "") { 263 if (thirdBoxSet.has(ui.item.value)) { 264 alert("Duplicate filter!"); 265 return; 266 } else thirdBoxSet.add(ui.item.value); 267 // Set the text content of the tag to 268 // the trimmed value 269 tag.innerText = ui.item.value; 270 // Add a delete button to the tag 271 tag.innerHTML += '<button class="delete-button">x</button>'; 272 // Append the tag to the tags list 273 tagThird.appendChild(tag); 274 var dom = $("#tags-third"); 275 var x = dom[0].scrollWidth; 276 dom[0].scrollLeft = x; 277 $("#column-third").val(""); 278 $(this).blur(); 279 getSearchText(); 280 } 281 if(thirdBoxSet.size > 0) $("#aggregations").hide(); 282 else $("#aggregations").show(); 283 $("#column-third").focus(); 284 return false; 285 }, 286 }) 287 .on("focus", function () { 288 if (!$(this).val().trim()) $(this).keydown(); 289 }); 290 $("#column-third").focus(); 291 } 292 /** 293 * check first box 294 * @param {*} obj 295 */ 296 function checkContent(obj){ 297 if($(obj).val() === '' || $(obj).val() === null){ 298 $("#completed").attr('disabled', true); 299 }else{ 300 $("#completed").attr("disabled", false); 301 } 302 } 303 function checkFirstBox(curSelect){ 304 let num = 0; 305 if ( 306 ($("#column-first").val() == null || 307 $("#column-first").val().trim() == "") && curSelect != 0 308 ) num++; 309 if (($("#symbol").val() == null || $("#symbol").val().trim() == "") && curSelect != 1) num++; 310 if (($("#value-first").val() == null || $("#value-first").val().trim() == "") && curSelect != 2) num++; 311 if(num != 0){ 312 $("#completed").attr("disabled", true); 313 } else { 314 $("#completed").attr("disabled", false); 315 } 316 } 317 function checkSecondContent(obj) { 318 if ($(obj).val() === "" || $(obj).val() === null) { 319 $("#completed-second").attr("disabled", true); 320 } else { 321 $("#completed-second").attr("disabled", false); 322 } 323 } 324 /** 325 * first box complete one filter info 326 * @param {*} evt 327 */ 328 function filterComplete(evt) { 329 evt.preventDefault(); 330 let val = $("#value-first").val().trim(); 331 if ( 332 $("#column-first").val() == null || 333 $("#column-first").val().trim() == "" || 334 $("#symbol").val() == null || 335 $("#symbol").val().trim() == "" || 336 $("#value-first").val() == null || 337 $("#value-first").val().trim() == "" 338 ) { 339 alert("Please select one of the values below"); 340 return; 341 } 342 $("#filter-box-1").removeClass("select-box"); 343 let tagContent = $("#column-first").val().trim() + $("#symbol").val().trim(); 344 if (ifCurIsNum) tagContent += val; 345 else tagContent += '"' + val + '"'; 346 $("#column-first").val(""); 347 $("#symbol").val(""); 348 $("#value-first").val(""); 349 $("#column-first").attr("type", "hidden"); 350 $("#symbol").attr("type", "hidden"); 351 $("#value-first").attr("type", "hidden"); 352 $("#completed").hide(); 353 $("#cancel-enter").hide(); 354 $("#add-filter").hide(); 355 $("#add-con").show(); 356 let tag = document.createElement("li"); 357 if (tagContent !== "") { 358 if (firstBoxSet.has(tagContent)) { 359 alert("Duplicate filter!"); 360 return; 361 } else firstBoxSet.add(tagContent); 362 // Set the text content of the tag to 363 // the trimmed value 364 tag.innerText = tagContent; 365 // Add a delete button to the tag 366 tag.innerHTML += '<button class="delete-button">x</button>'; 367 // Append the tag to the tags list 368 tags.appendChild(tag); 369 var dom = $("#tags"); 370 var x = dom[0].scrollWidth; 371 dom[0].scrollLeft = x; 372 getSearchText(); 373 if (firstBoxSet.size > 0) $("#search-filter-text").hide(); 374 else $("#search-filter-text").show(); 375 } 376 } 377 function secondFilterComplete(evt) { 378 evt.preventDefault(); 379 if ( 380 $("#column-second").val() == null || 381 $("#column-second").val().trim() == "" || 382 $("#value-second").val() == null || 383 $("#value-second").val().trim() == "" 384 ) { 385 alert("Please select one of the values below"); 386 return; 387 } 388 $("#filter-box-2").removeClass("select-box"); 389 let tagContent = 390 $("#column-second").val().trim() + 391 "(" + 392 $("#value-second").val().trim() + 393 ")"; 394 $("#column-second").val(""); 395 $("#value-second").val(""); 396 $("#column-second").attr("type", "hidden"); 397 $("#value-second").attr("type", "hidden"); 398 $("#completed-second").hide(); 399 $("#cancel-enter-second").hide(); 400 $("#add-filter-second").hide(); 401 $("#add-con-second").show(); 402 let tag = document.createElement("li"); 403 if (tagContent !== "") { 404 if (secondBoxSet.has(tagContent)) { 405 alert("Duplicate filter!"); 406 return; 407 } else secondBoxSet.add(tagContent); 408 // Set the text content of the tag to 409 // the trimmed value 410 tag.innerText = tagContent; 411 // Add a delete button to the tag 412 tag.innerHTML += '<button class="delete-button">x</button>'; 413 // Append the tag to the tags list 414 tagSecond.appendChild(tag); 415 var dom = $("#tags-second"); 416 var x = dom[0].scrollWidth; 417 dom[0].scrollLeft = x; 418 getSearchText(); 419 if (secondBoxSet.size > 0) $("#aggregate-attribute-text").hide(); 420 else $("#aggregate-attribute-text").show(); 421 } 422 } 423 function getSearchText() { 424 let filterValue = getQueryBuilderCode(); 425 if (filterValue != "") { 426 $("#query-input").val(filterValue); 427 } 428 if (filterValue === "Searches with a Search Criteria must have an Aggregate Attribute") { 429 $("#query-builder-btn").addClass("stop-search").prop('disabled', true); 430 } else { 431 $("#query-builder-btn").removeClass("stop-search").prop('disabled', false); 432 } 433 } 434 435 function cancelInfo(evt) { 436 evt.preventDefault(); 437 evt.stopPropagation(); 438 $("#filter-box-1").removeClass("select-box"); 439 $("#column-first").val(""); 440 $("#symbol").val(""); 441 $("#value-first").val(""); 442 $("#column-first").attr("type", "hidden"); 443 $("#symbol").attr("type", "hidden"); 444 $("#value-first").attr("type", "hidden"); 445 $("#completed").hide(); 446 $("#add-filter").hide(); 447 $("#cancel-enter").hide(); 448 $("#add-con").show(); 449 } 450 function secondCancelInfo(evt) { 451 evt.preventDefault(); 452 evt.stopPropagation(); 453 $("#filter-box-2").removeClass("select-box"); 454 $("#column-second").val(""); 455 $("#value-second").val(""); 456 $("#column-second").attr("type", "hidden"); 457 $("#value-second").attr("type", "hidden"); 458 $("#completed-second").hide(); 459 $("#add-filter-second").hide(); 460 $("#cancel-enter-second").hide(); 461 $("#add-con-second").show(); 462 } 463 function ThirdCancelInfo(event) { 464 event.preventDefault(); 465 event.stopPropagation(); 466 $("#filter-box-3").removeClass("select-box"); 467 $("#column-third").val(""); 468 $("#add-filter-third").hide(); 469 $("#column-third").attr("type", "hidden"); 470 $("#add-con-third").show(); 471 } 472 /** 473 * first input box 474 */ 475 476 $("#column-second") 477 .autocomplete({ 478 source: calculations.sort(), 479 minLength: 0, 480 maxheight: 100, 481 select: async function (event, ui) { 482 $("#value-second").attr("type", "text"); 483 $("#completed-second").show(); 484 $("#value-second").val(""); 485 if (columnsNames.length === 0 || numericColumns.length ==0) await getColumns(); 486 let columnInfo = columnsNames; 487 if (ui.item.value != "count") columnInfo = numericColumns; 488 $("#completed-second").attr("disabled", true); 489 $("#value-second") 490 .autocomplete({ 491 source: columnInfo.sort(), 492 minLength: 0, 493 select: function (event, ui) { 494 let secVal = $("#column-second").val(); 495 if (secVal == null || secVal.trim() == "") $("#completed-second").attr("disabled", true); 496 else $("#completed-second").attr("disabled", false); 497 } 498 }) 499 .on("focus", function () { 500 if (!$(this).val().trim()) $(this).keydown(); 501 }); 502 }, 503 }) 504 .on("focus", function () { 505 if (!$(this).val().trim()) $(this).keydown(); 506 }); 507 /** 508 * get cur column names from back-end for first input box 509 * 510 */ 511 async function getColumns() { 512 const data = { 513 state: "query", 514 searchText: "*", 515 startEpoch: filterStartDate, 516 endEpoch: filterEndDate, 517 indexName: selectedSearchIndex, 518 from: 0, 519 size: 1, 520 queryLanguage: "Splunk QL", 521 }; 522 523 const res = await $.ajax({ 524 method: "post", 525 url: "api/search/", 526 headers: { 527 "Content-Type": "application/json; charset=utf-8", 528 Accept: "*/*", 529 }, 530 crossDomain: true, 531 dataType: "json", 532 data: JSON.stringify(data), 533 }); 534 535 if (res) { 536 columnsNames = res.allColumns.filter(column => column !== '_index' && column !== 'timestamp'); // remove '_index' and 'timestamp' column from query builder 537 getNumericColumns(res); 538 } 539 } 540 /** 541 * get numeric column names from back-end for second input box (aggregation) 542 * 543 */ 544 function getNumericColumns(data) { 545 function areAllNumerical(values) { 546 return values.every(value => typeof value === 'number'); 547 } 548 numericColumns = []; 549 for (const column of data.allColumns) { 550 // Skip the "timestamp" column 551 if (column === "timestamp") continue; 552 553 const values = data.hits.records.map(record => record[column]); 554 555 if (areAllNumerical(values)) { 556 numericColumns.push(column); 557 } 558 } 559 } 560 /** 561 * get values of cur column names from back-end for first input box 562 * 563 */ 564 function getValuesofColumn(chooseColumn) { 565 valuesOfColumn.clear(); 566 let param = { 567 state: "query", 568 searchText: `SELECT DISTINCT ${chooseColumn} FROM \`${selectedSearchIndex}\``, 569 startEpoch: filterStartDate, 570 endEpoch: filterEndDate, 571 indexName: selectedSearchIndex, 572 queryLanguage: "SQL", 573 from: 0, 574 size: 1000, 575 }; 576 startQueryTime = new Date().getTime(); 577 $.ajax({ 578 method: "post", 579 url: "api/search", 580 headers: { 581 "Content-Type": "application/json; charset=utf-8", 582 Accept: "*/*", 583 }, 584 crossDomain: true, 585 dataType: "json", 586 data: JSON.stringify(param), 587 }).then((res) => { 588 if (res && res.hits && res.hits.records) { 589 for (let i = 0; i < res.hits.records.length; i++) { 590 let cur = res.hits.records[i][chooseColumn]; 591 if (typeof cur == "string") valuesOfColumn.add(cur); 592 else valuesOfColumn.add(cur.toString()); 593 } 594 } 595 let arr = Array.from(valuesOfColumn); 596 $("#value-first") 597 .autocomplete({ 598 source: arr.sort(), 599 minLength: 0, 600 select: function (event, ui) { 601 //check if complete btn can click 602 checkFirstBox(2); 603 valuesOfColumn.clear(); 604 }, 605 }) 606 .on("focus", function () { 607 if (!$(this).val().trim()) $(this).keydown(); 608 }); 609 }); 610 } 611 function setShowColumnInfoDialog(){ 612 $("#show-record-popup").dialog({ 613 autoOpen: false, 614 resizable: false, 615 title: false, 616 maxHeight: 307, 617 height: 307, 618 width: 464, 619 modal: true, 620 position: { 621 my: "center", 622 at: "center", 623 of: window, 624 }, 625 buttons: { 626 Cancel: { 627 class: "cancelqButton cancel-record-btn", 628 text: "Cancel", 629 click: function () { 630 $("#show-record-popup").dialog("close"); 631 }, 632 }, 633 } 634 }); 635 $("#show-record-intro-btn").on("click", function () { 636 $("#show-record-popup").dialog("open"); 637 $(".ui-widget-overlay").addClass("opacity-75"); 638 // return false; 639 }); 640 } 641 function convertTimestamp(timestampString) { 642 var timestamp = parseInt(timestampString); 643 var date = new Date(timestamp); 644 645 var year = date.getFullYear(); 646 var month = ("0" + (date.getMonth() + 1)).slice(-2); 647 var day = ("0" + date.getDate()).slice(-2); 648 649 var hours = ("0" + date.getHours()).slice(-2); 650 var minutes = ("0" + date.getMinutes()).slice(-2); 651 var seconds = ("0" + date.getSeconds()).slice(-2); 652 653 var readableDate = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds; 654 return readableDate; 655 } 656 const resizeObserver = new ResizeObserver((entries) => { 657 if (chart != null && chart != "" && chart != undefined) { 658 let height = document 659 .getElementById("custom-code-tab") 660 .getBoundingClientRect().height; 661 let width = document 662 .getElementById("columnChart") 663 .getBoundingClientRect().width; 664 chart.resize({ 665 height: window.innerHeight - height - 60, 666 width: width - 20, 667 }); 668 } 669 }); 670 resizeObserver.observe(document.getElementById("columnChart")); 671 function timeChart() { 672 if (isTimechart) { 673 $("#columnChart").show(); 674 $("#hideGraph").hide(); 675 }else{ 676 $("#columnChart").hide(); 677 $("#hideGraph").show(); 678 return; 679 } 680 // Extract data for ECharts 681 var timestamps = measureInfo.map((item) => convertTimestamp(item.GroupByValues[0])); 682 var seriesData = measureFunctions.map(function (measureFunction) { 683 return { 684 name: measureFunction, 685 type: "bar", 686 data: measureInfo.map(function (item) { 687 return item.MeasureVal[measureFunction] || 0; 688 }), 689 }; 690 }); 691 692 // ECharts configuration 693 var option = { 694 tooltip: { 695 trigger: "item", 696 formatter: function (params) { 697 return params.seriesName + ": " + params.value; 698 }, 699 }, 700 legend: { 701 textStyle: { 702 color: "#6e7078", 703 fontSize: 12, 704 }, 705 data: measureFunctions, 706 type: "scroll", // Enable folding functionality 707 orient: "vertical", 708 right: 10, 709 top: "middle", 710 align: "left", 711 height: "70%", 712 width: 150, 713 }, 714 grid: { 715 left: 10, 716 right: 220, 717 containLabel: true, 718 }, 719 xAxis: { 720 type: "category", 721 data: timestamps, 722 scale: true, 723 splitLine: { show: false }, 724 }, 725 yAxis: { 726 type: "value", 727 scale: true, 728 splitLine: { show: false }, 729 }, 730 series: seriesData, 731 }; 732 733 // Initialize ECharts 734 let charId = document.getElementById("columnChart"); 735 if (chart != null && chart != "" && chart != undefined) { 736 echarts.dispose(chart); 737 } 738 chart = echarts.init(charId); 739 // Set the configuration to the chart 740 chart.setOption(option); 741 let height = document 742 .getElementById("custom-code-tab") 743 .getBoundingClientRect().height; 744 let width = document 745 .getElementById("columnChart") 746 .getBoundingClientRect().width; 747 chart.resize({ 748 height: window.innerHeight - height - 60, 749 width: width - 20, 750 }); 751 }