1/** 2 * Dashboard Analytics 3 */ 4 5'use strict'; 6 7(function () { 8 let cardColor, headingColor, fontFamily, labelColor; 9 cardColor = config.colors.cardColor; 10 labelColor = config.colors.textMuted; 11 headingColor = config.colors.headingColor; 12 13 // swiper loop and autoplay 14 // -------------------------------------------------------------------- 15 const swiperWithPagination = document.querySelector('#swiper-with-pagination-cards'); 16 if (swiperWithPagination) { 17 new Swiper(swiperWithPagination, { 18 loop: true, 19 autoplay: { 20 delay: 2500, 21 disableOnInteraction: false 22 }, 23 pagination: { 24 clickable: true, 25 el: '.swiper-pagination' 26 } 27 }); 28 } 29 30 // Average Daily Sales 31 // -------------------------------------------------------------------- 32 const averageDailySalesEl = document.querySelector('#averageDailySales'), 33 averageDailySalesConfig = { 34 chart: { 35 height: 105, 36 type: 'area', 37 toolbar: { 38 show: false 39 }, 40 sparkline: { 41 enabled: true 42 } 43 }, 44 markers: { 45 colors: 'transparent', 46 strokeColors: 'transparent' 47 }, 48 grid: { 49 show: false 50 }, 51 colors: [config.colors.success], 52 fill: { 53 type: 'gradient', 54 gradient: { 55 shadeIntensity: 1, 56 opacityFrom: 0.4, 57 gradientToColors: [config.colors.cardColor], 58 opacityTo: 0.1, 59 stops: [0, 100] 60 } 61 }, 62 dataLabels: { 63 enabled: false 64 }, 65 stroke: { 66 width: 2, 67 curve: 'smooth' 68 }, 69 series: [ 70 { 71 data: [500, 160, 930, 670] 72 } 73 ], 74 xaxis: { 75 show: true, 76 lines: { 77 show: false 78 }, 79 labels: { 80 show: false 81 }, 82 stroke: { 83 width: 0 84 }, 85 axisBorder: { 86 show: false 87 } 88 }, 89 yaxis: { 90 stroke: { 91 width: 0 92 }, 93 show: false 94 }, 95 tooltip: { 96 enabled: false 97 }, 98 responsive: [ 99 { 100 breakpoint: 1387, 101 options: { 102 chart: { 103 height: 80 104 } 105 } 106 }, 107 { 108 breakpoint: 1200, 109 options: { 110 chart: { 111 height: 123 112 } 113 } 114 } 115 ] 116 };
117 if (typeof averageDailySalesEl !== undefined && averageDailySalesEl !== null) { 118 const averageDailySales = new ApexCharts(averageDailySalesEl, averageDailySalesConfig); 119 averageDailySales.render(); 120 } 121 122 // Earning Reports Bar Chart 123 // -------------------------------------------------------------------- 124 const weeklyEarningReportsEl = document.querySelector('#weeklyEarningReports'), 125 weeklyEarningReportsConfig = { 126 chart: { 127 height: 161, 128 parentHeightOffset: 0, 129 type: 'bar', 130 toolbar: { 131 show: false 132 } 133 }, 134 plotOptions: { 135 bar: { 136 barHeight: '60%', 137 columnWidth: '38%', 138 startingShape: 'rounded', 139 endingShape: 'rounded', 140 borderRadius: 4, 141 distributed: true 142 } 143 }, 144 grid: { 145 show: false, 146 padding: { 147 top: -30, 148 bottom: 0, 149 left: -10, 150 right: -10 151 } 152 }, 153 colors: [ 154 config.colors_label.primary, 155 config.colors_label.primary, 156 config.colors_label.primary, 157 config.colors_label.primary, 158 config.colors.primary, 159 config.colors_label.primary, 160 config.colors_label.primary 161 ], 162 dataLabels: { 163 enabled: false 164 }, 165 series: [ 166 { 167 data: [40, 65, 50, 45, 90, 55, 70] 168 } 169 ], 170 legend: { 171 show: false 172 }, 173 xaxis: { 174 categories: ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'], 175 axisBorder: { 176 show: false 177 }, 178 axisTicks: { 179 show: false 180 }, 181 labels: { 182 style: { 183 colors: labelColor, 184 fontSize: '13px', 185 fontFamily: fontFamily 186 } 187 } 188 }, 189 yaxis: { 190 labels: { 191 show: false 192 } 193 }, 194 tooltip: { 195 enabled: false 196 }, 197 responsive: [ 198 { 199 breakpoint: 1025, 200 options: { 201 chart: { 202 height: 199 203 } 204 } 205 } 206 ], 207 states: { 208 hover: { 209 filter: { 210 type: 'none' 211 } 212 }, 213 active: { 214 filter: { 215 type: 'none' 216 } 217 } 218 } 219 }; 220 if (typeof weeklyEarningReportsEl !== undefined && weeklyEarningReportsEl !== null) { 221 const weeklyEarningReports = new ApexCharts(weeklyEarningReportsEl, weeklyEarningReportsConfig); 222 weeklyEarningReports.render(); 223 } 224 225 // Support Tracker - Radial Bar Chart 226 // -------------------------------------------------------------------- 227 const supportTrackerEl = document.querySelector('#supportTracker'), 228 supportTrackerOptions = { 229 series: [85], 230 labels: ['Completed Task'], 231 chart: { 232 height: 337, 233 type: 'radialBar' 234 }, 235 plotOptions: { 236 radialBar: { 237 offsetY: 10, 238 startAngle: -140, 239 endAngle: 130, 240 hollow: { 241 size: '65%' 242 }, 243 track: { 244 background: cardColor, 245 strokeWidth: '100%' 246 }, 247 dataLabels: { 248 name: { 249 offsetY: -20, 250 color: labelColor, 251 fontSize: '13px', 252 fontWeight: '400', 253 fontFamily: fontFamily 254 }, 255 value: { 256 offsetY: 10, 257 color: headingColor, 258 fontSize: '38px', 259 fontWeight: '400', 260 fontFamily: fontFamily 261 } 262 } 263 } 264 }, 265 colors: [config.colors.primary], 266 fill: { 267 type: 'gradient', 268 gradient: { 269 shade: 'dark', 270 shadeIntensity: 0.5, 271 gradientToColors: [config.colors.primary], 272 inverseColors: true, 273 opacityFrom: 1, 274 opacityTo: 0.6, 275 stops: [30, 70, 100] 276 } 277 }, 278 stroke: { 279 dashArray: 10 280 }, 281 grid: { 282 padding: { 283 top: -20, 284 bottom: 5 285 } 286 }, 287 states: { 288 hover: { 289 filter: { 290 type: 'none' 291 } 292 }, 293 active: { 294 filter: { 295 type: 'none' 296 } 297 } 298 }, 299 responsive: [ 300 { 301 breakpoint: 1025, 302 options: { 303 chart: { 304 height: 330 305 } 306 } 307 }, 308 { 309 breakpoint: 769, 310 options: { 311 chart: { 312 height: 280 313 } 314 } 315 } 316 ] 317 }; 318 if (typeof supportTrackerEl !== undefined && supportTrackerEl !== null) { 319 const supportTracker = new ApexCharts(supportTrackerEl, supportTrackerOptions); 320 supportTracker.render(); 321 } 322 323 // Total Earning Chart - Bar Chart 324 // -------------------------------------------------------------------- 325 const totalEarningChartEl = document.querySelector('#totalEarningChart'), 326 totalEarningChartOptions = { 327 chart: { 328 height: 175, 329 parentHeightOffset: 0, 330 stacked: true, 331 type: 'bar', 332 toolbar: { show: false } 333 }, 334 series: [ 335 { 336 name: 'Earning', 337 data: [300, 200, 350, 150, 250, 325, 250, 270] 338 }, 339 { 340 name: 'Expense', 341 data: [-180, -225, -180, -280, -125, -200, -125, -150] 342 } 343 ], 344 tooltip: { 345 enabled: false 346 }, 347 plotOptions: { 348 bar: { 349 horizontal: false, 350 columnWidth: '40%', 351 borderRadius: 7, 352 startingShape: 'rounded', 353 endingShape: 'rounded', 354 borderRadiusApplication: 'around', 355 borderRadiusWhenStacked: 'last' 356 } 357 }, 358 359 colors: [config.colors.primary, config.colors.secondary], 360 dataLabels: { 361 enabled: false 362 }, 363 stroke: { 364 curve: 'smooth', 365 width: 5, 366 lineCap: 'round', 367 colors: [cardColor] 368 }, 369 legend: { 370 show: false 371 }, 372 colors: [config.colors.primary, config.colors.secondary], 373 fill: { 374 opacity: 1 375 }, 376 grid: { 377 show: false, 378 padding: { 379 top: -40, 380 bottom: -40, 381 left: -10, 382 right: -2 383 } 384 }, 385 xaxis: { 386 labels: { 387 show: false 388 }, 389 axisTicks: { 390 show: false 391 }, 392 axisBorder: { 393 show: false 394 } 395 }, 396 yaxis: { 397 labels: { 398 show: false 399 } 400 }, 401 responsive: [ 402 { 403 breakpoint: 1700, 404 options: { 405 plotOptions: { 406 bar: { 407 columnWidth: '43%' 408 } 409 } 410 } 411 }, 412 { 413 breakpoint: 1441, 414 options: { 415 plotOptions: { 416 bar: { 417 columnWidth: '50%' 418 } 419 } 420 } 421 }, 422 { 423 breakpoint: 1300, 424 options: { 425 plotOptions: { 426 bar: { 427 borderRadius: 6, 428 columnWidth: '60%' 429 } 430 } 431 } 432 }, 433 { 434 breakpoint: 1200, 435 options: { 436 plotOptions: { 437 bar: { 438 borderRadius: 6, 439 columnWidth: '30%' 440 } 441 } 442 } 443 }, 444 { 445 breakpoint: 991, 446 options: { 447 plotOptions: { 448 bar: { 449 borderRadius: 6, 450 columnWidth: '35%' 451 } 452 } 453 } 454 }, 455 { 456 breakpoint: 850, 457 options: { 458 plotOptions: { 459 bar: { 460 columnWidth: '50%' 461 } 462 } 463 } 464 }, 465 { 466 breakpoint: 768, 467 options: { 468 plotOptions: { 469 bar: { 470 columnWidth: '30%' 471 } 472 } 473 } 474 }, 475 { 476 breakpoint: 476, 477 options: { 478 plotOptions: { 479 bar: { 480 columnWidth: '43%' 481 } 482 } 483 } 484 }, 485 { 486 breakpoint: 394, 487 options: { 488 plotOptions: { 489 bar: { 490 columnWidth: '58%' 491 } 492 } 493 } 494 } 495 ], 496 states: { 497 hover: { 498 filter: { 499 type: 'none' 500 } 501 }, 502 active: { 503 filter: { 504 type: 'none' 505 } 506 } 507 } 508 }; 509 if (typeof totalEarningChartEl !== undefined && totalEarningChartEl !== null) { 510 const totalEarningChart = new ApexCharts(totalEarningChartEl, totalEarningChartOptions); 511 totalEarningChart.render(); 512 } 513 514 // For Datatable 515 // -------------------------------------------------------------------- 516 const dt_project_table = document.querySelector('.datatable-project'); 517 518 if (dt_project_table) { 519 let tableTitle = document.createElement('h5'); 520 tableTitle.classList.add('card-title', 'mb-0', 'text-md-start', 'text-center', 'pt-md-0', 'pt-6'); 521 tableTitle.innerHTML = 'Project List'; 522 var dt_project = new DataTable(dt_project_table, { 523 ajax: assetsPath + 'json/user-profile.json', // JSON file to add data 524 columns: [ 525 { data: 'id' }, 526 { data: 'id', orderable: false, render: DataTable.render.select() }, 527 { data: 'project_name' }, 528 { data: 'project_leader' }, 529 { data: 'id' }, 530 { data: 'status' }, 531 { data: 'id' } 532 ], 533 columnDefs: [ 534 { 535 // For Responsive 536 className: 'control', 537 searchable: false, 538 orderable: false, 539 responsivePriority: 2, 540 targets: 0, 541 render: function (data, type, full, meta) { 542 return ''; 543 } 544 }, 545 { 546 // For Checkboxes 547 targets: 1, 548 orderable: false, 549 searchable: false, 550 responsivePriority: 3, 551 checkboxes: true, 552 render: function () { 553 return '<input type="checkbox" class="dt-checkboxes form-check-input">'; 554 }, 555 checkboxes: { 556 selectAllRender: '<input type="checkbox" class="form-check-input">' 557 } 558 }, 559 { 560 // Avatar image/badge, Name and post 561 targets: 2, 562 responsivePriority: 4, 563 render: function (data, type, full, meta) { 564 var userImg = full['project_img'], 565 name = full['project_name'], 566 date = full['date']; 567 var output; 568 if (userImg) { 569 // For Avatar image 570 output = 571 '<img src="' + assetsPath + 'img/icons/brands/' + userImg + '" alt="Avatar" class="rounded-circle">'; 572 } else { 573 // For Avatar badge 574 var stateNum = Math.floor(Math.random() * 6);
575 var states = ['success', 'danger', 'warning', 'info', 'primary', 'secondary']; 576 var state = states[stateNum], 577 initials = name.match(/\b\w/g) || []; 578 initials = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase(); 579 output = '<span class="avatar-initial rounded-circle bg-label-' + state + '">' + initials + '</span>'; 580 } 581 // Creates full output for row 582 var rowOutput = 583 '<div class="d-flex justify-content-left align-items-center">' + 584 '<div class="avatar-wrapper">' + 585 '<div class="avatar avatar-sm me-3">' + 586 output + 587 '</div>' + 588 '</div>' + 589 '<div class="d-flex flex-column gap-50">' + 590 '<span class="text-truncate fw-medium text-heading">' + 591 name + 592 '</span>' + 593 '<small class="text-truncate">' + 594 date + 595 '</small>' + 596 '</div>' + 597 '</div>'; 598 return rowOutput; 599 } 600 }, 601 { 602 // Task 603 targets: 3, 604 render: function (data, type, full, meta) { 605 var task = full['project_leader']; 606 return '<span class="text-heading">' + task + '</span>'; 607 } 608 }, 609 { 610 // Teams 611 targets: 4, 612 orderable: false, 613 searchable: false, 614 render: function (data, type, full, meta) { 615 const team = full['team']; 616 let teamItem = ''; 617 let teamCount = 0; 618 // Iterate through team members and generate the list items 619 for (let i = 0; i < team.length; i++) { 620 teamItem += ` 621 <li data-bs-toggle="tooltip" data-popup="tooltip-custom" data-bs-placement="top" title="Kim Karlos" class="avatar avatar-sm pull-up"> 622 <img class="rounded-circle" src="${assetsPath}img/avatars/${team[i]}" alt="Avatar"> 623 </li> 624 `; 625 teamCount++; 626 if (teamCount > 2) break; 627 } 628 // Check if there are more than 2 team members, and add the remaining avatars 629 if (teamCount > 2) { 630 const remainingAvatars = team.length - 3; 631 if (remainingAvatars > 0) { 632 teamItem += ` 633 <li class="avatar avatar-sm"> 634 <span class="avatar-initial rounded-circle pull-up" data-bs-toggle="tooltip" data-bs-placement="top" title="${remainingAvatars} more">+${remainingAvatars}</span> 635 </li> 636 `; 637 } 638 } 639 // Combine the team items into the final output 640 const teamOutput = ` 641 <div class="d-flex align-items-center"> 642 <ul class="list-unstyled d-flex align-items-center avatar-group mb-0 z-2"> 643 ${teamItem} 644 </ul> 645 </div> 646 `; 647 return teamOutput; 648 } 649 }, 650 { 651 // Label 652 targets: -2, 653 render: function (data, type, full, meta) { 654 const statusNumber = full['status']; 655 return ` 656 <div class="d-flex align-items-center"> 657 <div class="progress w-100 me-3" style="height: 6px;"> 658 <div class="progress-bar" style="width: ${statusNumber}" aria-valuenow="${statusNumber}" aria-valuemin="0" aria-valuemax="100"></div> 659 </div> 660 <span class="text-heading">${statusNumber}</span> 661 </div> 662 `; 663 } 664 }, 665 { 666 // Actions 667 targets: -1, 668 searchable: false, 669 title: 'Action', 670 orderable: false, 671 render: function (data, type, full, meta) { 672 return ( 673 '<div class="d-inline-block">' + 674 '<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect rounded-pill dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="icon-base ti tabler-dots-vertical icon-22px"></i></a>' + 675 '<div class="dropdown-menu dropdown-menu-end m-0">' + 676 '<a href="javascript:;" class="dropdown-item">
676Details</a>' + 677 '<a href="javascript:;" class="dropdown-item">Archive</a>' + 678 '<div class="dropdown-divider"></div>' + 679 '<a href="javascript:;" class="dropdown-item text-danger delete-record">Delete</a>' + 680 '</div>' + 681 '</div>' 682 ); 683 } 684 } 685 ], 686 select: { 687 style: 'multi', 688 selector: 'td:nth-child(2)' 689 }, 690 order: [[2, 'desc']], 691 layout: { 692 topStart: { 693 rowClass: 'row mx-md-3 my-0 justify-content-between', 694 features: [tableTitle] 695 }, 696 topEnd: { 697 search: { 698 placeholder: 'Search Project', 699 text: '_INPUT_' 700 } 701 }, 702 bottomStart: { 703 rowClass: 'row mx-3 justify-content-between', 704 features: ['info'] 705 }, 706 bottomEnd: 'paging' 707 }, 708 displayLength: 5, 709 language: { 710 paginate: { 711 next: '<i class="icon-base ti tabler-chevron-right scaleX-n1-rtl icon-18px"></i>', 712 previous: '<i class="icon-base ti tabler-chevron-left scaleX-n1-rtl icon-18px"></i>', 713 first: '<i class="icon-base ti tabler-chevrons-left scaleX-n1-rtl icon-18px"></i>', 714 last: '<i class="icon-base ti tabler-chevrons-right scaleX-n1-rtl icon-18px"></i>' 715 } 716 }, 717 // For responsive popup 718 responsive: { 719 details: { 720 display: DataTable.Responsive.display.modal({ 721 header: function (row) { 722 const data = row.data(); 723 return 'Details of ' + data['project_name']; 724 } 725 }), 726 type: 'column', 727 renderer: function (api, rowIdx, columns) { 728 const data = columns 729 .map(function (col) { 730 return col.title !== '' // Do not show row in modal popup if title is blank (for check box) 731 ? `<tr data-dt-row="${col.rowIndex}" data-dt-column="${col.columnIndex}"> 732 <td>${col.title}:</td> 733 <td>${col.data}</td> 734 </tr>` 735 : ''; 736 }) 737 .join(''); 738 739 if (data) { 740 const div = document.createElement('div'); 741 div.classList.add('table-responsive'); 742 const table = document.createElement('table'); 743 div.appendChild(table); 744 table.classList.add('table'); 745 const tbody = document.createElement('tbody'); 746 tbody.innerHTML = data; 747 table.appendChild(tbody); 748 return div; 749 } 750 return false; 751 } 752 } 753 } 754 }); 755 //? The 'delete-record' class is necessary for the functionality of the following code. 756 document.addEventListener('click', function (e) { 757 if (e.target.classList.contains('delete-record')) { 758 dt_project.row(e.target.closest('tr')).remove().draw(); 759 const modalEl = document.querySelector('.dtr-bs-modal'); 760 if (modalEl && modalEl.classList.contains('show')) { 761 const modal = bootstrap.Modal.getInstance(modalEl); 762 modal?.hide(); 763 } 764 } 765 }); 766 } 767 768 // Filter form control to default size 769 // ? setTimeout used for project-list table initialization 770 setTimeout(() => { 771 const elementsToModify = [ 772 { selector: '.dt-search .form-control', classToRemove: 'form-control-sm' }, 773 { selector: '.dt-length .form-select', classToRemove: 'form-select-sm', classToAdd: 'ms-0' }, 774 { selector: '.dt-length', classToAdd: 'mb-md-6 mb-0' }, 775 { selector: '.dt-buttons', classToAdd: 'justify-content-center' }, 776 { selector: '.dt-layout-table', classToRemove: 'row mt-2' }, 777 { selector: '.dt-layout-end', classToAdd: 'gap-md-2 gap-0 mt-0' }, 778 { selector: '.dt-layout-full', classToRemove: 'col-md col-12', classToAdd: 'table-responsive' } 779 ]; 780 781 // Delete record 782 elementsToModify.forEach(({ selector, classToRemove, classToAdd }) => { 783 document.querySelectorAll(selector).forEach(element => { 784 if (classToRemove) { 785 classToRemove.split(' ').forEach(className => element.classList.remove(className)); 786 } 787 if (classToAdd) { 788 classToAdd.split(' ').forEach(className => element.classList.add(className)); 789 } 790 }); 791 }); 792 }, 100); 793})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.