github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/static/js/dashboards-home.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 let dbgridDiv = null; 21 let dbRowData = []; 22 23 async function getAllDashboards() { 24 let serverResponse = [] 25 await $.ajax({ 26 method: 'get', 27 url: 'api/dashboards/listall', 28 headers: { 29 'Content-Type': 'application/json; charset=utf-8', 30 'Accept': '*/*' 31 }, 32 crossDomain: true, 33 dataType: 'json', 34 }).then(function (res) { 35 serverResponse = res; 36 }) 37 return serverResponse 38 } 39 40 async function getAllDefaultDashboards() { 41 let serverResponse = [] 42 await $.ajax({ 43 method: 'get', 44 url: 'api/dashboards/defaultlistall', 45 headers: { 46 'Content-Type': 'application/json; charset=utf-8', 47 'Accept': '*/*' 48 }, 49 crossDomain: true, 50 dataType: 'json', 51 }).then(function (res) { 52 serverResponse = res; 53 }) 54 return serverResponse 55 } 56 async function getAllFavoriteDashboards() { 57 let serverResponse = [] 58 await $.ajax({ 59 method: 'get', 60 url: 'api/dashboards/listfavorites', 61 headers: { 62 'Content-Type': 'application/json; charset=utf-8', 63 'Accept': '*/*' 64 }, 65 crossDomain: true, 66 dataType: 'json', 67 }).then(function (res) { 68 serverResponse = res; 69 }) 70 return serverResponse 71 } 72 73 function createDashboard() { 74 $('.popupOverlay, .popupContent').addClass('active'); 75 $('#new-dashboard-modal').show(); 76 $('#delete-db-prompt').hide(); 77 78 function createDashboardWithInput() { 79 var inputdbname = $("#db-name").val(); 80 var inputdbdescription = $("#db-description").val(); 81 var timeRange = "Last 1 Hour"; 82 var refresh = ""; 83 84 if (!inputdbname) { 85 $('.error-tip').addClass('active'); 86 $('.popupOverlay, .popupContent').addClass('active'); 87 $('#new-dashboard-modal').show(); 88 } else { 89 $('#save-dbbtn').off('click'); 90 $(document).off('keypress'); 91 92 $.ajax({ 93 method: "post", 94 url: "api/dashboards/create", 95 headers: { 96 'Content-Type': 'application/json; charset=utf-8', 97 'Accept': '*/*' 98 }, 99 data: JSON.stringify(inputdbname), 100 dataType: 'json', 101 crossDomain: true, 102 }).then(function (res) { 103 $("#db-name").val(""); 104 $("#db-description").val(""); 105 $('.error-tip').removeClass('active'); 106 $('.popupOverlay, .popupContent').removeClass('active'); 107 108 var updateDashboard = { 109 "id": Object.keys(res)[0], 110 "name": Object.values(res)[0], 111 "details": { 112 "name": Object.values(res)[0], 113 "description": inputdbdescription, 114 "timeRange": timeRange, 115 "refresh": refresh, 116 } 117 } 118 119 $.ajax({ 120 method: "post", 121 url: "api/dashboards/update", 122 headers: { 123 'Content-Type': 'application/json; charset=utf-8', 124 'Accept': '*/*' 125 }, 126 data: JSON.stringify(updateDashboard), 127 dataType: 'json', 128 crossDomain: true, 129 }).then(function (msg) { 130 console.log("done:", msg) 131 }) 132 133 var queryString = "?id=" + Object.keys(res)[0]; 134 window.location.href = "../dashboard.html" + queryString; 135 }).catch(function (updateError) { 136 if (updateError.status === 409) { 137 $('.error-tip').text('Dashboard name already exists!'); 138 $('.error-tip').addClass('active'); 139 $('.popupOverlay, .popupContent').addClass('active'); 140 attachEventHandlers(); 141 } 142 }); 143 } 144 } 145 // method to attach event handlers to avoid redundant event handlers 146 function attachEventHandlers() { 147 $('#save-dbbtn').on('click', function () { 148 createDashboardWithInput(); 149 }); 150 151 $(document).on('keypress', function(event){ 152 if(event.keyCode == '13'){ 153 event.preventDefault(); 154 createDashboardWithInput(); 155 } 156 }); 157 158 $('#cancel-dbbtn, .popupOverlay').on('click', function () { 159 $("#db-name").val(""); 160 $("#db-description").val(""); 161 $('.popupOverlay, .popupContent').removeClass('active'); 162 $('.error-tip').removeClass('active'); 163 }); 164 } 165 166 // Attach event handlers initially 167 attachEventHandlers(); 168 } 169 170 function createSiglensDashboard(inputdbname) { 171 var inputdbdescription = "A pre-created Dashboard to monitor the cluster"; 172 var timeRange = "Last 1 Hour" 173 174 $.ajax({ 175 method: "post", 176 url: "api/dashboards/create", 177 headers: { 178 'Content-Type': 'application/json; charset=utf-8', 179 'Accept': '*/*' 180 }, 181 data: JSON.stringify(inputdbname), 182 dataType: 'json', 183 crossDomain: true, 184 }).then(function (res) { 185 var updateDashboard = { 186 "id": Object.keys(res)[0], 187 "name": Object.values(res)[0], 188 "details": { 189 "name": Object.values(res)[0], 190 "description": inputdbdescription, 191 "timeRange": timeRange, 192 } 193 } 194 $.ajax({ 195 method: "post", 196 url: "api/dashboards/update", 197 headers: { 198 'Content-Type': 'application/json; charset=utf-8', 199 'Accept': '*/*' 200 }, 201 data: JSON.stringify(updateDashboard), 202 dataType: 'json', 203 crossDomain: true, 204 }).then(function (msg) { 205 console.log("done:", msg) 206 }) 207 }); 208 } 209 210 class btnRenderer { 211 init(params) { 212 const starOutlineURL = 'url("../assets/star-outline.svg")'; 213 const starFilledURL = 'url("../assets/star-filled.svg")'; 214 215 this.eGui = document.createElement('span'); 216 this.eGui.innerHTML = `<div id="dashboard-grid-btn"> 217 218 <button class='btn' id="viewbutton" title="Open dashboard"></button> 219 <button class="btn-simple" id="delbutton" title="Delete dashboard"></button> 220 <button class="btn-duplicate" id="duplicateButton" title="Duplicate dashboard"></button> 221 <button class="star-icon" id="favbutton" title="Mark as favorite" ></button> 222 </div>`; 223 this.vButton = this.eGui.querySelector('.btn'); 224 this.dButton = this.eGui.querySelector('.btn-simple'); 225 this.duplicateButton = this.eGui.querySelector('.btn-duplicate'); 226 this.starIcon=this.eGui.querySelector('.star-icon'); 227 this.starIcon.style.backgroundImage = favoriteDBsSet.has(params.data.uniqId) ? starFilledURL : starOutlineURL; 228 229 let defaultDashboardIds = [ 230 "10329b95-47a8-48df-8b1d-0a0a01ec6c42", 231 "a28f485c-4747-4024-bb6b-d230f101f852", 232 "bd74f11e-26c8-4827-bf65-c0b464e1f2a4", 233 "53cb3dde-fd78-4253-808c-18e4077ef0f1" 234 ]; 235 236 if (defaultDashboardIds.includes(params.data.uniqId)) { 237 this.dButton.disabled = true; 238 this.dButton.title = "Delete disabled"; 239 this.dButton.classList.add('default-dashboard-delete'); 240 } 241 242 function view() { 243 $.ajax({ 244 method: 'get', 245 url: 'api/dashboards/' + params.data.uniqId, 246 headers: { 247 'Content-Type': 'application/json; charset=utf-8', 248 Accept: '*/*', 249 }, 250 crossDomain: true, 251 dataType: 'json', 252 }).then(function (res) { 253 var queryString = "?id=" + params.data.uniqId; 254 window.location.href = "../dashboard.html" + queryString; 255 }); 256 } 257 258 function deletedb() { 259 $.ajax({ 260 method: 'get', 261 url: 'api/dashboards/delete/' + params.data.uniqId, 262 headers: { 263 'Content-Type': 'application/json; charset=utf-8', 264 Accept: '*/*', 265 }, 266 crossDomain: true, 267 }).then(function () { 268 let deletedRowID = params.data.rowId; 269 dbgridOptions.api.applyTransaction({ 270 remove: [{ rowId: deletedRowID }], 271 }); 272 }); 273 } 274 275 function duplicatedb() { 276 $.ajax({ 277 method: 'get', 278 url: 'api/dashboards/' + params.data.uniqId, 279 headers: { 280 'Content-Type': 'application/json; charset=utf-8', 281 Accept: '*/*', 282 }, 283 crossDomain: true, 284 dataType: 'json', 285 }).then(function (res) { 286 let duplicatedDBName = res.name + "-Copy"; 287 let duplicatedDescription = res.description; 288 let duplicatedPanels = res.panels; 289 let duplicateTimeRange = res.timeRange; 290 let duplicateRefresh = res.refresh; 291 let uniqIDdb; 292 $.ajax({ 293 method: "post", 294 url: "api/dashboards/create", 295 headers: { 296 'Content-Type': 'application/json; charset=utf-8', 297 'Accept': '*/*' 298 }, 299 data: JSON.stringify(duplicatedDBName), 300 dataType: 'json', 301 crossDomain: true, 302 }).then((res) => { 303 uniqIDdb = Object.keys(res)[0]; 304 $.ajax( 305 { 306 method: 'POST', 307 url: '/api/dashboards/update', 308 data: JSON.stringify({ 309 "id": uniqIDdb, 310 "name": duplicatedDBName, 311 "details": { 312 "name": duplicatedDBName, 313 "description": duplicatedDescription, 314 "panels": duplicatedPanels, 315 "timeRange": duplicateTimeRange, 316 "refresh": duplicateRefresh, 317 } 318 }) 319 } 320 ) 321 }).then(function () { 322 dbgridOptions.api.applyTransaction({ 323 add: [{ 324 dbname: duplicatedDBName, 325 uniqId: uniqIDdb, 326 }], 327 }); 328 }) 329 }) 330 } 331 function toggleFavorite() { 332 $.ajax({ 333 method: 'put', 334 url: 'api/dashboards/favorite/' + params.data.uniqId, 335 headers: { 336 'Content-Type': 'application/json; charset=utf-8', 337 Accept: '*/*', 338 }, 339 crossDomain: true, 340 }).then((response) => { 341 // Update the favorite status based on the response 342 params.data.favorite = response.isFavorite; 343 if(params.data.favorite) { 344 this.starIcon.style.backgroundImage = starFilledURL; 345 } else { 346 this.starIcon.style.backgroundImage = starOutlineURL; 347 } 348 }); 349 } 350 function showPrompt() { 351 $('#delete-db-prompt').css('display', 'flex'); 352 $('.popupOverlay, .popupContent').addClass('active'); 353 $('#new-dashboard-modal').hide(); 354 355 $('#cancel-db-prompt, .popupOverlay').click(function () { 356 $('.popupOverlay, .popupContent').removeClass('active'); 357 $('#delete-db-prompt').hide(); 358 }); 359 360 $('#delete-dbbtn').click(function () { 361 deletedb(); 362 $('.popupOverlay, .popupContent').removeClass('active'); 363 $('#delete-db-prompt').hide(); 364 }); 365 } 366 367 this.vButton.addEventListener('click', view); 368 this.dButton.addEventListener('click', showPrompt); 369 this.duplicateButton.addEventListener('click', duplicatedb); 370 this.starIcon.addEventListener('click',toggleFavorite.bind(this)); 371 } 372 373 getGui() { 374 return this.eGui; 375 } 376 refresh(params) { 377 // Use the URL of the SVG files for star icons 378 const starOutlineURL = 'url("../assets/star-outline.svg")'; 379 const starFilledURL = 'url("../assets/star-filled.svg")'; 380 381 this.starIcon.style.backgroundImage = params.data.favorite ? starFilledURL : starOutlineURL; 382 return false; 383 } 384 } 385 386 let dashboardColumnDefs = [ 387 { 388 field: "rowId", 389 hide: true 390 }, 391 { 392 headerName: "Dashboard Name", 393 field: "dbname", 394 sortable: true, 395 cellClass: "", 396 cellRenderer: (params) => { 397 var link = document.createElement('a'); 398 link.href = '#'; 399 link.innerText = params.value; 400 link.addEventListener('click', (e) => { 401 e.preventDefault(); 402 view() 403 }); 404 return link; 405 406 function view() { 407 $.ajax({ 408 method: 'get', 409 url: 'api/dashboards/' + params.data.uniqId, 410 headers: { 411 'Content-Type': 'application/json; charset=utf-8', 412 Accept: '*/*', 413 }, 414 crossDomain: true, 415 dataType: 'json', 416 }).then(function (res) { 417 var queryString = "?id=" + params.data.uniqId; 418 window.location.href = "../dashboard.html" + queryString; 419 }); 420 } 421 } 422 423 }, 424 { 425 cellRenderer: btnRenderer, 426 width: 40, 427 }, 428 429 ]; 430 431 // let the grid know which columns and what data to use 432 const dbgridOptions = { 433 columnDefs: dashboardColumnDefs, 434 rowData: dbRowData, 435 animateRows: true, 436 rowHeight: 54, 437 defaultColDef: { 438 icons: { 439 sortAscending: '<i class="fa fa-sort-alpha-up"/>', 440 sortDescending: '<i class="fa fa-sort-alpha-down"/>', 441 }, 442 }, 443 enableCellTextSelection: true, 444 suppressScrollOnNewData: true, 445 suppressAnimationFrame: true, 446 getRowId: (params) => params.data.rowId, 447 onGridReady(params) { 448 this.gridApi = params.api; // To access the grids API 449 }, 450 }; 451 452 453 function displayDashboards(res, flag) { 454 let favorites = []; 455 let nonFavorites = []; 456 457 for (let [key, value] of Object.entries(res)) { 458 if (favoriteDBsSet.has(key)) { 459 favorites.push([key, value]); 460 } else { 461 nonFavorites.push([key, value]); 462 } 463 } 464 favorites.sort((a, b) => b[1].localeCompare(a[1])); 465 nonFavorites.sort((a, b) => b[1].localeCompare(a[1])); 466 let resArray = [...favorites, ...nonFavorites]; 467 res = Object.fromEntries(resArray); 468 if (flag == -1) { 469 // show search results 470 let dbFilteredRowData = []; 471 if (dbgridDiv === null) { 472 dbgridDiv = document.querySelector('#dashboard-grid'); 473 new agGrid.Grid(dbgridDiv, dbgridOptions); 474 } 475 dbgridOptions.api.setColumnDefs(dashboardColumnDefs); 476 let idx = 0; 477 let newRow = new Map() 478 $.each(res, function (key, value) { 479 newRow.set("rowId", idx) 480 newRow.set("uniqId", key) 481 newRow.set("dbname", value) 482 483 dbFilteredRowData = _.concat(dbFilteredRowData, Object.fromEntries(newRow)); 484 idx = idx + 1; 485 }) 486 dbgridOptions.api.setRowData(dbFilteredRowData); 487 dbgridOptions.api.sizeColumnsToFit(); 488 } else { 489 if (dbgridDiv === null) { 490 dbgridDiv = document.querySelector('#dashboard-grid'); 491 new agGrid.Grid(dbgridDiv, dbgridOptions); 492 } 493 dbgridOptions.api.setColumnDefs(dashboardColumnDefs); 494 let idx = 0; 495 let newRow = new Map() 496 $.each(res, function (key, value) { 497 newRow.set("rowId", idx) 498 newRow.set("uniqId", key) 499 newRow.set("dbname", value) 500 501 dbRowData = _.concat(dbRowData, Object.fromEntries(newRow)); 502 idx = idx + 1; 503 }) 504 dbgridOptions.api.setRowData(dbRowData); 505 dbgridOptions.api.sizeColumnsToFit(); 506 } 507 } 508 509 function searchDB() { 510 let searchText = $('.search-db-input').val(); 511 var tokens = searchText.toLowerCase() 512 .split(' ') 513 .filter(function (token) { 514 return token.trim() !== ''; 515 }); 516 517 let dbNames = []; 518 dbRowData.forEach(rowData => { 519 dbNames.push(rowData.dbname) 520 }) 521 522 let dbFilteredRowsObject = {}; 523 if (tokens.length) { 524 var searchTermRegex = new RegExp(tokens.join('|'), 'gi'); 525 var filteredList = dbNames.filter(function (dbName, i) { 526 if (dbName.match(searchTermRegex)) { 527 let uniqIdDB = dbRowData[i].uniqId; 528 dbFilteredRowsObject[`${uniqIdDB}`] = dbRowData[i].dbname; 529 } 530 return dbName.match(searchTermRegex); 531 }); 532 533 if (Object.keys(dbFilteredRowsObject).length === 0) { 534 displayDashboards(dbFilteredRowsObject, -1); 535 showDBNotFoundMsg(); 536 } else { 537 $('#dashboard-grid-container').show(); 538 $('#empty-response').hide(); 539 displayDashboards(dbFilteredRowsObject, -1); 540 } 541 } 542 } 543 544 function displayOriginalDashboards() { 545 let searchText = $('.search-db-input').val(); 546 547 if (searchText.length === 0) { 548 if (dbgridDiv === null) { 549 dbgridDiv = document.querySelector('#dashboard-grid'); 550 new agGrid.Grid(dbgridDiv, dbgridOptions); 551 } 552 $('#dashboard-grid-container').show(); 553 $('#empty-response').hide(); 554 dbgridOptions.api.setColumnDefs(dashboardColumnDefs); 555 dbgridOptions.api.setRowData(dbRowData); 556 dbgridOptions.api.sizeColumnsToFit(); 557 } 558 } 559 560 function showDBNotFoundMsg() { 561 $('#dashboard-grid-container').hide(); 562 $('#empty-response').show(); 563 } 564 let favoriteDBsSet; 565 566 $(document).ready(async function () { 567 if (Cookies.get('theme')) { 568 theme = Cookies.get('theme'); 569 $('body').attr('data-theme', theme); 570 } 571 $('.theme-btn').on('click', themePickerHandler); 572 573 let normalDBs = await getAllDashboards(); 574 let allDefaultDBs = await getAllDefaultDashboards(); 575 let allDBs = {...normalDBs, ...allDefaultDBs} 576 let favoriteDBs = await getAllFavoriteDashboards(); 577 // Convert the array of favorite dashboards to a Set for faster lookup 578 favoriteDBsSet = new Set(Object.keys(favoriteDBs)); 579 displayDashboards(allDBs) 580 581 $('#create-db-btn').click(createDashboard); 582 $('#run-search').click(searchDB); 583 $('.search-db-input').on('keyup', displayOriginalDashboards); 584 585 let stDate = "now-1h"; 586 let endDate = "now"; 587 datePickerHandler(stDate, endDate, stDate); 588 } 589 );