github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/static/js/common.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  
    18  'use strict';
    19  
    20  // @todo - get rid of these global variables
    21  
    22  let timestampDateFmt = 'MMM Do, YYYY @ HH:mm:ss';
    23  let defaultColumnCount = 2;
    24  let dataTable = null;
    25  let aggsDataTable = null;
    26  let shouldCloseAllDetails = false;
    27  let filterStartDate = "now-15m";
    28  let filterEndDate = "now";
    29  let displayStart = moment().subtract(15, 'minutes').valueOf();
    30  let displayEnd = moment().valueOf();
    31  let selectedSearchIndex = '*';
    32  let canScrollMore = true;
    33  let scrollFrom = 0;
    34  let totalRrcCount = 0;
    35  let pageScrollPos = 0;
    36  let scrollPageNo = 1;
    37  let availColNames = [];
    38  let startQueryTime;
    39  let renderTime = 0;
    40  let wsState = 'query';
    41  let newUri = null;
    42  let socket = null;
    43  let myUrl = window.location.protocol + "//" + window.location.host + window.location.pathname;
    44  let data = null;
    45  let theme = 'light';
    46  let selectedFieldsList = [];
    47  let updatedSelFieldList = false;
    48  let aggsColumnDefs = [];
    49  let segStatsRowData = [];
    50  let GBCountChart, LogLinesCountChart, TotalVolumeChart;
    51  let queryStr = '*';
    52  let panelChart;
    53  let metricsDatasets;
    54  let liveTailState = false;
    55  let tt;
    56  let lockReconnect = false;
    57  let totalMatchLogs = 0;
    58  let firstBoxSet = new Set();
    59  let secondBoxSet = new Set();
    60  let thirdBoxSet = new Set();
    61  let measureFunctions = [];
    62  let measureInfo = [];
    63  let isTimechart = false;
    64  let isQueryBuilderSearch = false;
    65  let sortByTimestampAtDefault = true;
    66  
    67  
    68  let aggGridOptions = {
    69      columnDefs: aggsColumnDefs,
    70      rowData: [],
    71      animateRows: true,
    72      defaultColDef: {
    73          flex: 1,
    74          minWidth: 100,
    75          resizable: true,
    76          sortable: true,
    77          icons: {
    78              sortAscending: '<i class="fa fa-sort-alpha-up"/>',
    79              sortDescending: '<i class="fa fa-sort-alpha-down"/>',
    80          },
    81          cellRenderer: params => params.value ? params.value : 'null',
    82      },
    83      icons: {
    84          sortAscending: '<i class="fa fa-sort-alpha-up"/>',
    85          sortDescending: '<i class="fa fa-sort-alpha-down"/>',
    86      }
    87  };
    88  
    89  {{ .CommonExtraFunctions }}
    90  
    91  function showError(errorMsg) {
    92      $("#logs-result-container").hide();
    93      $("#agg-result-container").hide();
    94      $("#data-row-container").hide();
    95      $('#empty-response').hide();
    96      let currentTab = $("#custom-chart-tab").tabs("option", "active");
    97      if (currentTab == 0) {
    98        $("#logs-view-controls").show();
    99      } else {
   100        $("#logs-view-controls").hide();
   101      }
   102      $("#custom-chart-tab").show();
   103      $('#corner-popup .corner-text').html(errorMsg);
   104      $('#corner-popup').show();
   105      $('body').css('cursor', 'default');
   106      $('#run-filter-btn').html(' ');
   107      $("#run-filter-btn").removeClass("cancel-search");
   108      $('#run-filter-btn').removeClass('active');
   109       $("#query-builder-btn").html(" ");
   110       $("#query-builder-btn").removeClass("cancel-search");
   111       $("#query-builder-btn").removeClass("active");
   112      $("#live-tail-btn").html("Live Tail");
   113      $("#live-tail-btn").removeClass("active");
   114      $('#run-metrics-query-btn').removeClass('active');
   115  
   116      wsState = 'query';
   117  }
   118  
   119  function showInfo(infoMsg) {
   120      $('#corner-popup .corner-text').html(infoMsg);
   121      $('#corner-popup').show();
   122      $('#corner-popup').css('position', 'absolute');
   123      $('#corner-popup').css('bottom', '3rem');
   124      $('body').css('cursor', 'default');
   125      $('#run-filter-btn').html(' ');
   126      $("#run-filter-btn").removeClass("cancel-search");
   127      $('#run-filter-btn').removeClass('active');
   128      $("#query-builder-btn").html(" ");
   129      $("#query-builder-btn").removeClass("cancel-search");
   130      $("#query-builder-btn").removeClass("active");
   131      $("#live-tail-btn").html("Live Tail");
   132      $("#live-tail-btn").removeClass("active");
   133      wsState = 'query';
   134  }
   135  
   136  function hideError() {
   137      $('#corner-popup').hide();
   138  }
   139  
   140  function decodeJwt(token) {
   141      let base64Payload = token.split(".")[1];
   142      let payload = decodeURIComponent(
   143          atob(base64Payload)
   144              .split("")
   145              .map(function (c) {
   146                  return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
   147              })
   148              .join("")
   149      );
   150      return JSON.parse(payload);
   151  }
   152  
   153  function resetDashboard() {
   154      resetAvailableFields();
   155      $("#LogResultsGrid").html('');
   156      $("#measureAggGrid").html('');
   157      gridDiv = null;
   158      eGridDiv = null;
   159  }
   160  
   161  function string2Hex(tmp) {
   162      let str = '';
   163      for (let i = 0; i < tmp.length; i++) {
   164          str += tmp[i].charCodeAt(0).toString(16);
   165      }
   166      return str;
   167  }
   168  
   169  function addQSParm(name, value) {
   170      let re = new RegExp("([?&]" + name + "=)[^&]+", "");
   171  
   172      function add(sep) {
   173          myUrl += sep + name + "=" + encodeURIComponent(value);
   174      }
   175  
   176      function change() {
   177          myUrl = myUrl.replace(re, "$1" + encodeURIComponent(value));
   178      }
   179      if (myUrl.indexOf("?") === -1) {
   180          add("?");
   181      } else {
   182          if (re.test(myUrl)) {
   183              change();
   184          } else {
   185              add("&");
   186          }
   187      }
   188  }
   189  
   190  function resetQueryResAttr(res, panelId){
   191      if (panelId == -1 && currentPanel) // if the query has been made from the editPanelScreen
   192          currentPanel.queryRes = res;
   193      else {
   194          for (let i = 0; i < localPanels.length; i++) {
   195              if (localPanels[i].panelId == panelId) {
   196                  localPanels[i].queryRes = res;
   197                  break;
   198              }
   199          }
   200      }
   201  }
   202  
   203  function renderPanelLogsQueryRes(data, panelId, logLinesViewType, res) {
   204      //if data source is metrics
   205        if(!res.qtype) {
   206          panelProcessEmptyQueryResults("Unsupported chart type. Please select a different chart type.",panelId);
   207          return;
   208      }
   209      if(res.hits){
   210          if (panelId == -1) { // for panel on the editPanelScreen page
   211              $(".panelDisplay #panelLogResultsGrid").show();
   212              $(".panelDisplay #empty-response").empty();
   213              $('.panelDisplay #corner-popup').hide();
   214              $(".panelDisplay #empty-response").hide();
   215              $('.panelDisplay .panEdit-panel').hide();
   216          } else { // for panels on the dashboard page
   217              $(`#panel${panelId} #panelLogResultsGrid`).show();
   218              $(`#panel${panelId} #empty-response`).empty();
   219              $(`#panel${panelId} #corner-popup`).hide();
   220              $(`#panel${panelId} #empty-response`).hide();
   221              $(`#panel${panelId} .panEdit-panel`).hide();
   222          }
   223          //for aggs-query and segstats-query
   224          if (res.measure && (res.qtype === "aggs-query" || res.qtype === "segstats-query")) {
   225              let columnOrder = []
   226              if (res.groupByCols) {
   227                  columnOrder = _.uniq(_.concat(
   228                      res.groupByCols));
   229              }
   230              if (res.measureFunctions) {
   231                  columnOrder = _.uniq(_.concat(
   232                      columnOrder, res.measureFunctions));
   233              }
   234              renderPanelAggsGrid(columnOrder, res.measure,panelId)
   235          }//for logs-query
   236          else if(res.hits && res.hits.records !== null && res.hits.records.length >= 1) {
   237              renderPanelLogsGrid(res.allColumns, res.hits.records, panelId, logLinesViewType);
   238          }
   239          allResultsDisplayed--;
   240          if(allResultsDisplayed <= 0 || panelId === -1) {
   241              $('body').css('cursor', 'default');
   242          }
   243      }
   244      canScrollMore = res.can_scroll_more;
   245      scrollFrom = res.total_rrc_count;
   246      if (res.hits.totalMatched.value === 0 || (!res.bucketCount &&  (res.qtype === "aggs-query" || res.qtype === "segstats-query"))) {
   247          panelProcessEmptyQueryResults("", panelId);
   248      }
   249  
   250      wsState = 'query'
   251      if (canScrollMore === false) {
   252          scrollFrom = 0;
   253      }
   254  }
   255  
   256  function runPanelLogsQuery(data, panelId,currentPanel,queryRes) {
   257      return new Promise(function(resolve, reject) {
   258          $('body').css('cursor', 'progress');
   259          if (queryRes) {
   260              renderChartByChartType(data,queryRes,panelId,currentPanel)
   261          }
   262          else {
   263              $.ajax({
   264                  method: 'post',
   265                  url: 'api/search/' + panelId,
   266                  headers: {
   267                      'Content-Type': 'application/json; charset=utf-8',
   268                      'Accept': '*/*'
   269                  },
   270                  crossDomain: true,
   271                  dataType: 'json',
   272                  data: JSON.stringify(data)
   273              })
   274                  .then((res) => {
   275                      resetQueryResAttr(res, panelId);
   276                      renderChartByChartType(data,res,panelId,currentPanel);
   277                      resolve();
   278                  })
   279                  .catch(function (xhr, err) {
   280                      if (xhr.status === 400) {
   281                          panelProcessSearchError(xhr, panelId);
   282                      }currentPanel
   283                      $('body').css('cursor', 'default');
   284                      $(`#panel${panelId} .panel-body #panel-loading`).hide();
   285                      reject();
   286                  })
   287          }
   288      })
   289  }
   290  
   291  function panelProcessEmptyQueryResults(errorMsg, panelId) {
   292      let msg;
   293      if (errorMsg !== "") {
   294          msg = errorMsg;
   295      } else {
   296          msg = "Your query returned no data, adjust your query.";
   297      }
   298      if (panelId == -1) {
   299          $(`.panelDisplay .big-number-display-container`).hide();
   300          $(`.panelDisplay .big-number-display-container`).empty();
   301          $('.panelDisplay .panEdit-panel').hide();
   302          $('#corner-popup').hide();
   303          $('.panelDisplay #panelLogResultsGrid').hide();
   304          $('.panelDisplay #empty-response').show();
   305          let el = $('.panelDisplay #empty-response');
   306          $('.panelDisplay #empty-response').empty();
   307  
   308          el.append(`<span>${msg}</span>`);
   309      } else {
   310          $(`#panel${panelId} #panelLogResultsGrid`).hide();
   311          $(`#panel${panelId} #empty-response`).show();
   312          $(`#panel${panelId} #corner-popup`).hide();
   313          $(`#panel${panelId} .panEdit-panel`).hide();
   314          $(`#panel${panelId} .big-number-display-container`).hide();
   315          $(`#panel${panelId} #empty-response`).show();
   316          let el = $(`#panel${panelId} #empty-response`);
   317          $(`#panel${panelId} #empty-response`).empty();
   318          el.append(`<span>${msg}</span>`);
   319      }
   320      $('body').css('cursor', 'default');
   321      $(`#panel${panelId} .panel-body #panel-loading`).hide();
   322  }
   323  
   324  function panelProcessSearchError(res, panelId) {
   325      if (res.can_scroll_more === false) {
   326          showPanelInfo(`You've reached maximum scroll limit (10,000).`);
   327      }
   328  
   329      if (panelId == -1) {
   330          $(`.panelDisplay .big-number-display-container`).hide();
   331          $(`.panelDisplay .big-number-display-container`).empty();
   332          $('.panelDisplay .panEdit-panel').hide();
   333          $('.panelDisplay #corner-popup').show();
   334          $('.panelDisplay #panelLogResultsGrid').hide();
   335          $('.panelDisplay #empty-response').hide();
   336          let el = $('.panelDisplay #corner-popup');
   337          $('.panelDisplay #corner-popup').empty();
   338  
   339          el.append(`<span>${res.responseText}</span>`);
   340      } else {
   341          $(`#panel${panelId} #panelLogResultsGrid`).hide();
   342          $(`#panel${panelId} #empty-response`).show();
   343          $(`#panel${panelId} #corner-popup`).show();
   344          $(`#panel${panelId} .panEdit-panel`).hide();
   345          $(`#panel${panelId} .big-number-display-container`).hide();
   346          $(`#panel${panelId} #empty-response`).hide();
   347          let el = $(`#panel${panelId} #corner-popup`);
   348          $(`#panel${panelId} #corner-popup`).empty();
   349          el.append(`<span>${res.responseText}</span>`);
   350      }
   351      wsState = 'query';
   352  
   353  }
   354  
   355  function resetPanelContainer(firstQUpdate) {
   356      if (firstQUpdate) {
   357          $('#empty-response').hide();
   358          $('#panelLogResultsGrid').show();
   359          $(`.panelDisplay .big-number-display-container`).hide();
   360  
   361          hideError();
   362      }
   363  }
   364  
   365  function resetPanelGrid() {
   366      panelLogsRowData = [];
   367      panelGridDiv == null
   368  }
   369  
   370  function showPanelInfo(infoMsg) {
   371      $('#corner-popup .corner-text').html(infoMsg);
   372      $('#corner-popup').show();
   373      $('#corner-popup').css('position', 'absolute');
   374      $('#corner-popup').css('bottom', '3rem');
   375      $('body').css('cursor', 'default');
   376  
   377      wsState = 'query';
   378  }
   379  
   380  function getQueryParamsData(scrollingTrigger) {
   381      let sFrom = 0;
   382      let queryLanguage = $('.queryInput-container #query-language-btn span').html();
   383  
   384      if (scrollingTrigger) {
   385          sFrom = scrollFrom;
   386      }
   387      let data = {
   388          'state': wsState,
   389          'searchText': queryStr,
   390          'startEpoch': filterStartDate,
   391          'endEpoch': filterEndDate,
   392          'indexName': selectedSearchIndex,
   393          'from': sFrom,
   394          'queryLanguage' : queryLanguage,
   395      }
   396      return data;
   397  }
   398  
   399  function getCookie(cname) {
   400      let name = cname + "=";
   401      let decodedCookie = decodeURIComponent(document.cookie);
   402      let ca = decodedCookie.split(';');
   403      for (let i = 0; i < ca.length; i++) {
   404          let c = ca[i];
   405          while (c.charAt(0) == ' ') {
   406              c = c.substring(1);
   407          }
   408          if (c.indexOf(name) == 0) {
   409              return c.substring(name.length, c.length);
   410          }
   411      }
   412      return "";
   413  }
   414  
   415  function renderPanelAggsQueryRes(data, panelId, chartType, dataType, panelIndex, res) {
   416      resetQueryResAttr(res, panelId);
   417      //if data source is metrics
   418      if(!res.qtype && chartType != "number") {
   419          panelProcessEmptyQueryResults("Unsupported chart type. Please select a different chart type.",panelId)
   420      }
   421      if (res.qtype === "logs-query") {
   422          panelProcessEmptyQueryResults("", panelId);
   423      }
   424      
   425      if (res.qtype === "aggs-query" || res.qtype === "segstats-query") {
   426          if (panelId == -1) { // for panel on the editPanelScreen page
   427              $(".panelDisplay #panelLogResultsGrid").hide();
   428              $(".panelDisplay #empty-response").empty();
   429              $('.panelDisplay #corner-popup').hide();
   430              $(".panelDisplay #empty-response").hide();
   431              $('.panelDisplay .panEdit-panel').show();
   432              $(`.panelDisplay .big-number-display-container`).empty();
   433  	        $(`.panelDisplay .big-number-display-container`).hide();
   434          } else { // for panels on the dashboard page
   435              $(`#panel${panelId} #panelLogResultsGrid`).hide();
   436              $(`#panel${panelId} #empty-response`).empty();
   437              $(`#panel${panelId} #corner-popup`).hide();
   438              $(`#panel${panelId} #empty-response`).hide();
   439              $(`#panel${panelId} .panEdit-panel`).show();
   440              $(`.panelDisplay .big-number-display-container`).empty();
   441  	        $(`.panelDisplay .big-number-display-container`).hide();
   442          }
   443  
   444          let columnOrder = []
   445          if (res.groupByCols) {
   446              columnOrder = _.uniq(_.concat(
   447                  res.groupByCols));
   448          }
   449  
   450          if (res.measureFunctions) {
   451              columnOrder = _.uniq(_.concat(
   452                  columnOrder, res.measureFunctions));
   453          }
   454  
   455          if (res.errors) {
   456              panelProcessEmptyQueryResults(res.errors[0], panelId);
   457          } else {
   458              let resultVal;
   459              if (chartType === "number") {
   460                  resultVal = Object.values(res.measure[0].MeasureVal)[0];
   461              }
   462  
   463              if ((chartType === "Pie Chart" || chartType === "Bar Chart") && (res.hits.totalMatched === 0 || res.hits.totalMatched.value === 0)) {
   464                  panelProcessEmptyQueryResults("", panelId);
   465              } else if (chartType === "number" && (resultVal === undefined || resultVal === null)) {
   466                  panelProcessEmptyQueryResults("", panelId);
   467              } else {
   468                  // for number, bar and pie charts
   469                  if(panelId ===-1)
   470                      renderPanelAggsGrid(columnOrder, res.measure,panelId);
   471  
   472                  panelChart = renderBarChart(columnOrder, res.measure, panelId, chartType, dataType, panelIndex);
   473              }
   474          }
   475          allResultsDisplayed--;
   476          if(allResultsDisplayed <= 0 || panelId === -1) {
   477              $('body').css('cursor', 'default');
   478          }
   479      }
   480  }
   481  
   482  function runPanelAggsQuery(data, panelId, chartType, dataType, panelIndex, queryRes) {
   483      $('body').css('cursor', 'progress');
   484      if (queryRes) {
   485          renderPanelAggsQueryRes(data, panelId, chartType, dataType, panelIndex, queryRes)
   486      } else {
   487          $.ajax({
   488              method: 'post',
   489              url: 'api/search/' + panelId,
   490              headers: {
   491                  'Content-Type': 'application/json; charset=utf-8',
   492                  'Accept': '*/*'
   493              },
   494              crossDomain: true,
   495              dataType: 'json',
   496              data: JSON.stringify(data)
   497          })
   498              .then(function (res) {
   499                  renderPanelAggsQueryRes(data, panelId, chartType, dataType, panelIndex, res)
   500              })
   501              .catch(function (xhr, err) {
   502                  if (xhr.status === 400) {
   503                      panelProcessSearchError(xhr, panelId);
   504                  }
   505                  $('body').css('cursor', 'default');
   506              })
   507      }
   508  }
   509  
   510  function runMetricsQuery(data, panelId, currentPanel, queryRes) {
   511      $('body').css('cursor', 'progress');
   512      if (queryRes) {
   513          renderChartByChartType(data,queryRes,panelId,currentPanel)
   514      } else {
   515          $.ajax({
   516              method: 'post',
   517              url: 'promql/api/ui/query',
   518              headers: {
   519                  'Content-Type': 'application/json; charset=utf-8',
   520                  'Accept': '*/*'
   521              },
   522              crossDomain: true,
   523              dataType: 'json',
   524              data: JSON.stringify(data)
   525          })
   526              .then((res) => {
   527                  renderChartByChartType(data,res,panelId,currentPanel)
   528              })
   529              .catch(function (xhr, err) {
   530                  if (xhr.status === 400) {
   531                      panelProcessSearchError(xhr, panelId);
   532                  }
   533                  $('body').css('cursor', 'default')
   534              })
   535      }  
   536  }
   537  
   538  function processMetricsSearchResult(res, startTime, panelId, chartType, panelIndex,dataType) {
   539      resetQueryResAttr(res, panelId);
   540      let bigNumVal = null;
   541      if (panelId == -1) { // for panel on the editPanelScreen page
   542          $(".panelDisplay #panelLogResultsGrid").hide();
   543          $(".panelDisplay #empty-response").empty();
   544          $('.panelDisplay #corner-popup').hide();
   545          $(".panelDisplay #empty-response").hide();
   546          $('.panelDisplay .panEdit-panel').show();
   547      } else { // for panels on the dashboard page
   548          $(`#panel${panelId} #panelLogResultsGrid`).hide();
   549          $(`#panel${panelId} #empty-response`).empty();
   550          $(`#panel${panelId} #corner-popup`).hide();
   551          $(`#panel${panelId} #empty-response`).hide();
   552          $(`#panel${panelId} .panEdit-panel`).show();
   553      }
   554  
   555      if (res.aggStats && Object.keys(res.aggStats).length === 0) {
   556          panelProcessEmptyQueryResults("", panelId);
   557          $('body').css('cursor', 'default');
   558  	    $(`#panel${panelId} .panel-body #panel-loading`).hide();
   559      } else {
   560          if (chartType === 'number'){
   561              $.each(res, function (key, value) {
   562                  var series = value;
   563                  $.each(series, function (key, value) {
   564                      var tsmap = value
   565                      $.each(tsmap, function (key, value) {
   566                          if (value > 0){
   567                              bigNumVal = value
   568                          }
   569                      })
   570                  })         
   571              });   
   572              if(bigNumVal === undefined || bigNumVal === null){
   573                  panelProcessEmptyQueryResults("", panelId);
   574              }else{
   575                  displayBigNumber(bigNumVal.toString(), panelId, dataType, panelIndex);
   576                  allResultsDisplayed--;
   577                  if(allResultsDisplayed <= 0 || panelId === -1) {
   578                      $('body').css('cursor', 'default');
   579                  }
   580                  $(`#panel${panelId} .panel-body #panel-loading`).hide();   
   581              } 
   582          } else {
   583              hideError();
   584              const colors = createMetricsColorsArray();
   585              let seriesArray = [];
   586              let label = [];
   587              $.each(res, function (key, value) {
   588                  var series = value;
   589                  $.each(series, function (key, value) {
   590                      seriesArray.push({ seriesName: key, values: value });
   591                      label = [];
   592                      $.each(value, function (k, v) {
   593                          label.push(k);
   594                      })
   595                  })
   596                  let gridLineColor;
   597                  let tickColor;
   598                  if ($('body').attr('data-theme') == "light") {
   599                      gridLineColor = "#DCDBDF";
   600                      tickColor = "#160F29";
   601                  }
   602                  else {
   603                      gridLineColor = "#383148";
   604                      tickColor = "#FFFFFF"
   605                  }
   606                  metricsDatasets = seriesArray.map((o, i) => {
   607                      return {
   608                          name: o.seriesName,
   609                          data: Object.values(o.values),
   610                          type: chartType,
   611                          lineStyle: {
   612                              color: colors[i],
   613                              width: 2,
   614                              type: 'solid',
   615                              backgroundColor: colors[i],
   616                              borderColor: colors[i],
   617                          }, itemStyle: {
   618                              color: colors[i],
   619                              width: 2,
   620                              type: 'solid',
   621                              backgroundColor: colors[i],
   622                              borderColor: colors[i],
   623                          },
   624                      }
   625                  }
   626                  );
   627              })
   628              let labels = label;
   629  
   630              renderLineChart(seriesArray, metricsDatasets, labels, panelId, chartType, -1);
   631              allResultsDisplayed--;
   632              if(allResultsDisplayed <= 0 || panelId === -1) {
   633                  $('body').css('cursor', 'default');
   634              }
   635          }
   636      }
   637  }
   638  
   639  function processMetricsSearchError() {
   640      showError(`Your query returned no data, adjust your query.`);
   641  }
   642  
   643  function createMetricsColorsArray() {
   644      let root = document.querySelector(':root');
   645      let rootStyles = getComputedStyle(root);
   646      let colorArray = [];
   647      for (let i = 1; i <= 20; i++) {
   648          colorArray.push(rootStyles.getPropertyValue(`--graph-line-color-${i}`));
   649      }
   650      return colorArray;
   651  }
   652  
   653  function loadCustomDateTimeFromEpoch(startEpoch, endEpoch) {
   654      let dateVal = new Date(startEpoch);
   655      $('#date-start').val(dateVal.toISOString().substring(0,10));
   656      $('#date-start').addClass('active');
   657      $('.panelEditor-container #date-start').val(dateVal.toISOString().substring(0,10));
   658      $('.panelEditor-container #date-start').addClass('active');
   659      let hours = addZero(dateVal.getUTCHours());
   660      let mins = addZero(dateVal.getUTCMinutes());
   661      $('#time-start').val(hours+':'+mins);
   662      $('#time-start').addClass('active');
   663      $('.panelEditor-container #time-start').val(hours+':'+mins);
   664      $('.panelEditor-container #time-start').addClass('active');
   665  
   666      dateVal = new Date(endEpoch);
   667      $('#date-end').val(dateVal.toISOString().substring(0,10));
   668      $('#date-end').addClass('active');
   669      $('.panelEditor-container #date-end').val(dateVal.toISOString().substring(0,10));
   670      $('.panelEditor-container #date-end').addClass('active');
   671      hours = addZero(dateVal.getUTCHours());
   672      mins = addZero(dateVal.getUTCMinutes());
   673      $('#time-end').val(hours+':'+mins);
   674      $('#time-end').addClass('active');
   675      $('.panelEditor-container #time-end').val(hours+':'+mins);
   676      $('.panelEditor-container #time-end').addClass('active');
   677  }
   678  
   679  function addZero(i) {
   680      if (i < 10) {i = "0" + i}
   681      return i;
   682  }
   683  
   684  function setTimePicker() {
   685      // set time picker of next page with updated time
   686      let stDate = Cookies.get('startEpoch') || "now-1h";
   687      let endDate = Cookies.get('endEpoch') || "now";
   688      if (stDate && endDate) {
   689          if(endDate === "now") {
   690              filterStartDate = stDate;
   691              filterEndDate =  endDate;
   692              $('.inner-range #' + filterStartDate).addClass('active');
   693              datePickerHandler(filterStartDate, filterEndDate, filterStartDate)
   694          } else {
   695              if (!isNaN(stDate)) {
   696                  stDate = Number(stDate);
   697                  endDate = Number(endDate);
   698                  datePickerHandler(stDate, endDate, "custom");
   699                  loadCustomDateTimeFromEpoch(stDate, endDate);
   700                  filterStartDate = stDate;
   701                  filterEndDate =  endDate;
   702              }
   703          }
   704      }
   705  }
   706  
   707  // my org page
   708  function showToastMyOrgPage(msg) {
   709      let toast =
   710          `<div class="div-toast">
   711          ${msg}
   712          <button type="button" aria-label="Close" class="toast-close">✖</button>
   713      <div>`
   714      $('body').prepend(toast);
   715      $('.toast-close').on('click', removeToast);
   716      setTimeout(removeToast, 3000);
   717  }
   718  
   719  function showSendTestDataUpdateToast(msg) {
   720      let toast =
   721          `<div class="test-data-toast">
   722          ${msg}
   723          <button type="button" aria-label="Close" class="toast-close">✖</button>
   724      <div>`
   725      $('body').prepend(toast);
   726      $('.toast-close').on('click', removeToast);
   727      setTimeout(removeToast, 3000);
   728  }
   729  
   730  function showSendTestDataUpdateToast(msg) {
   731      let toast =
   732          `<div class="test-data-toast">
   733          ${msg}
   734          <button type="button" aria-label="Close" class="toast-close">✖</button>
   735      <div>`
   736      $('body').prepend(toast);
   737      $('.toast-close').on('click', removeToast);
   738      setTimeout(removeToast, 3000);
   739  }
   740  
   741  function removeToast() {
   742      $('.div-toast').remove();
   743      $('.test-data-toast').remove();
   744      $('.ret-days-toast').remove();
   745      $('.usage-stats-toast').remove();
   746  }
   747  
   748  function showDeleteIndexToast(msg) {
   749      let toast =
   750          `<div class="usage-stats-toast">
   751          ${msg}
   752          <button type="button" aria-label="Close" class="toast-close">✖</button>
   753      <div>`
   754      $('.index-header').append(toast);
   755      $('.toast-close').on('click', removeToast);
   756      setTimeout(removeToast, 3000);
   757  }
   758  
   759  function showRetDaysUpdateToast(msg) {
   760      let toast =
   761          `<div class="ret-days-toast">
   762          ${msg}
   763          <button type="button" aria-label="Close" class="toast-close">✖</button>
   764      <div>`
   765      $('body').prepend(toast);
   766      $('.toast-close').on('click', removeToast);
   767      setTimeout(removeToast, 3000);
   768  }
   769  
   770  
   771  
   772  
   773  
   774  function myOrgSendTestData(token) {
   775      $('#test-data-btn').on('click', (e) => {
   776          if (selectedLogSource === 'Send Test Data') {
   777              var testDataBtn = document.getElementById("test-data-btn");
   778              // Disable testDataBtn
   779              testDataBtn.disabled = true;
   780              sendTestData(e, token);
   781          }
   782          else {
   783              showSendTestDataUpdateToast('Select Test Data');
   784          }
   785      })
   786  }
   787  
   788  function getIngestUrl() {
   789      return new Promise((resolve, reject) => {
   790          $.ajax({
   791              method: 'get',
   792              url: '/api/config',
   793              crossDomain: true,
   794              dataType: 'json',
   795              credentials: 'include'
   796          })
   797          .then((res) => {
   798              resolve(res.IngestUrl);
   799          })
   800          .catch((err) => {
   801              console.log(err);
   802              reject(err);
   803          });
   804      });
   805  }
   806  
   807  //renders the response from logs or metrics query to respective selected chart type
   808  function renderChartByChartType(data,queryRes,panelId,currentPanel){
   809      if(!currentPanel.chartType){
   810          panelProcessEmptyQueryResults("Please select a suitable chart type.",panelId)
   811      }
   812      switch (currentPanel.chartType) {
   813          case "Data Table":
   814          case "loglines":
   815              $('.panelDisplay .panEdit-panel').hide();
   816              renderPanelLogsQueryRes(data, panelId,currentPanel.logLinesViewType,queryRes);
   817              break;
   818          case "Bar Chart":
   819          case "Pie Chart":
   820              renderPanelAggsQueryRes(data, panelId, currentPanel.chartType, currentPanel.dataType, currentPanel.panelIndex, queryRes)
   821              break;
   822          case "Line Chart":
   823              let startTime = (new Date()).getTime();
   824              processMetricsSearchResult(queryRes, startTime, panelId, currentPanel.chartType, currentPanel.panelIndex,"")
   825              break;
   826          case "number":
   827              
   828              if (currentPanel.unit === "" || currentPanel.dataType === "none" || currentPanel.dataType === ""){
   829                  currentPanel.unit = "misc"
   830                  currentPanel.dataType = "none"
   831              }
   832              if (currentPanel.queryType == 'metrics'){
   833                  let startTime = (new Date()).getTime();
   834                  processMetricsSearchResult(queryRes, startTime, panelId, currentPanel.chartType, currentPanel.panelIndex,currentPanel.dataType)
   835              }else{
   836                  renderPanelAggsQueryRes(data, panelId, currentPanel.chartType, currentPanel.dataType, currentPanel.panelIndex, queryRes)
   837              }
   838              break;
   839      }
   840  }