@acorex/modules 19.3.6 → 19.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import { createAllQueryView, AXPEntityCommandScope, AXPEntityQueryType, AXP_HOME
3
3
  import * as i3$1 from '@acorex/platform/layout/builder';
4
4
  import { AXPWidgetsCatalog, AXPValueWidgetComponent, cloneProperty, AXPWidgetGroupEnum, AXPLayoutWidgetComponent, AXPLayoutBuilderModule, AXPWidgetRendererDirective } from '@acorex/platform/layout/builder';
5
5
  import { AXMEntityCrudServiceImpl, AXPEntityService, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
6
- import { AXP_APPEARANCE_PROPERTY_GROUP, AXP_STYLING_PROPERTY_GROUP, AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_BEHAVIOR_PROPERTY_GROUP, AXP_BG_COLOR_PROPERTY, plainTextDefaultProperty, AXP_DATA_PROPERTY_GROUP, AXP_COLOR_PROPERTY, AXPWidgetsModule } from '@acorex/platform/widgets';
6
+ import { AXP_APPEARANCE_PROPERTY_GROUP, AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_BEHAVIOR_PROPERTY_GROUP, AXP_BG_COLOR_PROPERTY, plainTextDefaultProperty, AXP_DATA_PROPERTY_GROUP, AXP_COLOR_PROPERTY, AXPWidgetsModule } from '@acorex/platform/widgets';
7
7
  import * as i0 from '@angular/core';
8
8
  import { Injectable, inject, Injector, computed, ChangeDetectionStrategy, Component, ChangeDetectorRef, signal, viewChild, ElementRef, HostListener, output, InjectionToken, effect, HostBinding, NgModule, input, contentChild, afterNextRender, model, ViewEncapsulation } from '@angular/core';
9
9
  import { AXBarChartComponent } from '@acorex/charts/bar-chart';
@@ -454,20 +454,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
454
454
  */
455
455
  class AXPBarChartWidgetViewComponent extends AXPValueWidgetComponent {
456
456
  constructor() {
457
- super(...arguments);
457
+ super();
458
458
  this.barChartData = computed(() => this.getValue());
459
459
  this.barChartOptions = computed(() => this.options());
460
+ this.setOptions({
461
+ ...this.options(),
462
+ showXAxis: true,
463
+ showYAxis: true,
464
+ barWidth: 80,
465
+ cornerRadius: 4,
466
+ showGrid: true,
467
+ showDataLabels: false,
468
+ showTooltip: true,
469
+ animationEasing: 'cubic-out',
470
+ animationDuration: 800,
471
+ });
460
472
  }
461
473
  handleBarClick(event) {
462
474
  //console.log(event);
463
475
  }
464
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPBarChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
476
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPBarChartWidgetViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
465
477
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: AXPBarChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-bar-chart [data]=\"barChartData()\" [options]=\"barChartOptions()\" (barClick)=\"handleBarClick($event)\"></ax-bar-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXBarChartComponent, selector: "ax-bar-chart", inputs: ["data", "options"], outputs: ["barClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
466
478
  }
467
479
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPBarChartWidgetViewComponent, decorators: [{
468
480
  type: Component,
469
481
  args: [{ imports: [AXBarChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-bar-chart [data]=\"barChartData()\" [options]=\"barChartOptions()\" (barClick)=\"handleBarClick($event)\"></ax-bar-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
470
- }] });
482
+ }], ctorParameters: () => [] });
471
483
 
472
484
  var barChartWidget_component = /*#__PURE__*/Object.freeze({
473
485
  __proto__: null,
@@ -514,61 +526,7 @@ const AXPBarChartWidget = {
514
526
  },
515
527
  visible: true,
516
528
  },
517
- // ====== Layout & Dimensions ======
518
- {
519
- name: 'width',
520
- title: '@dashboard:widgets.bar-chart.width',
521
- group: AXP_STYLING_PROPERTY_GROUP,
522
- schema: {
523
- defaultValue: null,
524
- dataType: 'number',
525
- interface: {
526
- name: 'width',
527
- path: 'options.width',
528
- type: AXPWidgetsCatalog.number,
529
- options: {
530
- minValue: 0,
531
- maxValue: 1200,
532
- },
533
- },
534
- },
535
- visible: true,
536
- },
537
- {
538
- name: 'height',
539
- title: '@dashboard:widgets.bar-chart.height',
540
- group: AXP_STYLING_PROPERTY_GROUP,
541
- schema: {
542
- defaultValue: 300,
543
- dataType: 'number',
544
- interface: {
545
- name: 'height',
546
- path: 'options.height',
547
- type: AXPWidgetsCatalog.number,
548
- options: {
549
- minValue: 0,
550
- maxValue: 800,
551
- },
552
- },
553
- },
554
- visible: true,
555
- },
556
529
  // ====== X Axis Settings ======
557
- {
558
- name: 'showXAxis',
559
- title: '@dashboard:widgets.bar-chart.show-x-axis',
560
- group: AXP_APPEARANCE_PROPERTY_GROUP,
561
- schema: {
562
- defaultValue: true,
563
- dataType: 'boolean',
564
- interface: {
565
- name: 'showXAxis',
566
- path: 'options.showXAxis',
567
- type: AXPWidgetsCatalog.toggle,
568
- },
569
- },
570
- visible: true,
571
- },
572
530
  {
573
531
  name: 'xAxisLabel',
574
532
  title: '@dashboard:widgets.bar-chart.x-axis-label',
@@ -585,21 +543,6 @@ const AXPBarChartWidget = {
585
543
  visible: true,
586
544
  },
587
545
  // ====== Y Axis Settings ======
588
- {
589
- name: 'showYAxis',
590
- title: '@dashboard:widgets.bar-chart.show-y-axis',
591
- group: AXP_APPEARANCE_PROPERTY_GROUP,
592
- schema: {
593
- defaultValue: true,
594
- dataType: 'boolean',
595
- interface: {
596
- name: 'showYAxis',
597
- path: 'options.showYAxis',
598
- type: AXPWidgetsCatalog.toggle,
599
- },
600
- },
601
- visible: true,
602
- },
603
546
  {
604
547
  name: 'yAxisLabel',
605
548
  title: '@dashboard:widgets.bar-chart.y-axis-label',
@@ -615,145 +558,218 @@ const AXPBarChartWidget = {
615
558
  },
616
559
  visible: true,
617
560
  },
561
+ /* Commented out properties
562
+ // ====== Layout & Dimensions ======
563
+ {
564
+ name: 'width',
565
+ title: '@dashboard:widgets.bar-chart.width',
566
+ group: AXP_STYLING_PROPERTY_GROUP,
567
+ schema: {
568
+ defaultValue: null,
569
+ dataType: 'number',
570
+ interface: {
571
+ name: 'width',
572
+ path: 'options.width',
573
+ type: AXPWidgetsCatalog.number,
574
+ options: {
575
+ minValue: 0,
576
+ maxValue: 1200,
577
+ },
578
+ },
579
+ },
580
+ visible: true,
581
+ },
582
+ {
583
+ name: 'height',
584
+ title: '@dashboard:widgets.bar-chart.height',
585
+ group: AXP_STYLING_PROPERTY_GROUP,
586
+ schema: {
587
+ defaultValue: 300,
588
+ dataType: 'number',
589
+ interface: {
590
+ name: 'height',
591
+ path: 'options.height',
592
+ type: AXPWidgetsCatalog.number,
593
+ options: {
594
+ minValue: 0,
595
+ maxValue: 800,
596
+ },
597
+ },
598
+ },
599
+ visible: true,
600
+ },
601
+ // ====== X Axis Settings ======
602
+ {
603
+ name: 'showXAxis',
604
+ title: '@dashboard:widgets.bar-chart.show-x-axis',
605
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
606
+ schema: {
607
+ defaultValue: true,
608
+ dataType: 'boolean',
609
+ interface: {
610
+ name: 'showXAxis',
611
+ path: 'options.showXAxis',
612
+ type: AXPWidgetsCatalog.toggle,
613
+ },
614
+ },
615
+ visible: true,
616
+ },
617
+ // ====== Y Axis Settings ======
618
+ {
619
+ name: 'showYAxis',
620
+ title: '@dashboard:widgets.bar-chart.show-y-axis',
621
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
622
+ schema: {
623
+ defaultValue: true,
624
+ dataType: 'boolean',
625
+ interface: {
626
+ name: 'showYAxis',
627
+ path: 'options.showYAxis',
628
+ type: AXPWidgetsCatalog.toggle,
629
+ },
630
+ },
631
+ visible: true,
632
+ },
618
633
  // ====== Bar Appearance ======
619
634
  {
620
- name: 'barWidth',
621
- title: '@dashboard:widgets.bar-chart.bar-width',
622
- group: AXP_APPEARANCE_PROPERTY_GROUP,
623
- schema: {
624
- defaultValue: 80,
625
- dataType: 'number',
626
- interface: {
627
- name: 'barWidth',
628
- path: 'options.barWidth',
629
- type: AXPWidgetsCatalog.number,
630
- options: {
631
- placeholder: '1-100',
632
- minValue: 1,
633
- maxValue: 100,
634
- },
635
- },
635
+ name: 'barWidth',
636
+ title: '@dashboard:widgets.bar-chart.bar-width',
637
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
638
+ schema: {
639
+ defaultValue: 80,
640
+ dataType: 'number',
641
+ interface: {
642
+ name: 'barWidth',
643
+ path: 'options.barWidth',
644
+ type: AXPWidgetsCatalog.number,
645
+ options: {
646
+ placeholder: '1-100',
647
+ minValue: 1,
648
+ maxValue: 100,
649
+ },
636
650
  },
637
- visible: true,
651
+ },
652
+ visible: true,
638
653
  },
639
654
  {
640
- name: 'cornerRadius',
641
- title: '@dashboard:widgets.bar-chart.corner-radius',
642
- group: AXP_APPEARANCE_PROPERTY_GROUP,
643
- schema: {
644
- defaultValue: 4,
645
- dataType: 'number',
646
- interface: {
647
- name: 'cornerRadius',
648
- path: 'options.cornerRadius',
649
- type: AXPWidgetsCatalog.number,
650
- options: {
651
- placeholder: '0-20',
652
- minValue: 0,
653
- maxValue: 20,
654
- },
655
- },
655
+ name: 'cornerRadius',
656
+ title: '@dashboard:widgets.bar-chart.corner-radius',
657
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
658
+ schema: {
659
+ defaultValue: 4,
660
+ dataType: 'number',
661
+ interface: {
662
+ name: 'cornerRadius',
663
+ path: 'options.cornerRadius',
664
+ type: AXPWidgetsCatalog.number,
665
+ options: {
666
+ placeholder: '0-20',
667
+ minValue: 0,
668
+ maxValue: 20,
669
+ },
656
670
  },
657
- visible: true,
671
+ },
672
+ visible: true,
658
673
  },
659
674
  // ====== Grid Settings ======
660
675
  {
661
- name: 'showGrid',
662
- title: '@dashboard:widgets.bar-chart.show-grid',
663
- group: AXP_APPEARANCE_PROPERTY_GROUP,
664
- schema: {
665
- defaultValue: true,
666
- dataType: 'boolean',
667
- interface: {
668
- name: 'showGrid',
669
- path: 'options.showGrid',
670
- type: AXPWidgetsCatalog.toggle,
671
- },
676
+ name: 'showGrid',
677
+ title: '@dashboard:widgets.bar-chart.show-grid',
678
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
679
+ schema: {
680
+ defaultValue: true,
681
+ dataType: 'boolean',
682
+ interface: {
683
+ name: 'showGrid',
684
+ path: 'options.showGrid',
685
+ type: AXPWidgetsCatalog.toggle,
672
686
  },
673
- visible: true,
687
+ },
688
+ visible: true,
674
689
  },
675
690
  {
676
- name: 'showDataLabels',
677
- title: '@dashboard:widgets.bar-chart.show-data-labels',
678
- group: AXP_APPEARANCE_PROPERTY_GROUP,
679
- schema: {
680
- defaultValue: true,
681
- dataType: 'boolean',
682
- interface: {
683
- name: 'showDataLabels',
684
- path: 'options.showDataLabels',
685
- type: AXPWidgetsCatalog.toggle,
686
- },
691
+ name: 'showDataLabels',
692
+ title: '@dashboard:widgets.bar-chart.show-data-labels',
693
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
694
+ schema: {
695
+ defaultValue: true,
696
+ dataType: 'boolean',
697
+ interface: {
698
+ name: 'showDataLabels',
699
+ path: 'options.showDataLabels',
700
+ type: AXPWidgetsCatalog.toggle,
687
701
  },
688
- visible: true,
702
+ },
703
+ visible: true,
689
704
  },
690
705
  // ====== Tooltip Settings ======
691
706
  {
692
- name: 'showTooltip',
693
- title: '@dashboard:widgets.bar-chart.show-tooltip',
694
- group: AXP_APPEARANCE_PROPERTY_GROUP,
695
- schema: {
696
- defaultValue: true,
697
- dataType: 'boolean',
698
- interface: {
699
- name: 'showTooltip',
700
- path: 'options.showTooltip',
701
- type: AXPWidgetsCatalog.toggle,
702
- },
707
+ name: 'showTooltip',
708
+ title: '@dashboard:widgets.bar-chart.show-tooltip',
709
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
710
+ schema: {
711
+ defaultValue: true,
712
+ dataType: 'boolean',
713
+ interface: {
714
+ name: 'showTooltip',
715
+ path: 'options.showTooltip',
716
+ type: AXPWidgetsCatalog.toggle,
703
717
  },
704
- visible: true,
718
+ },
719
+ visible: true,
705
720
  },
706
721
  // ====== Animation Settings ======
707
722
  {
708
- name: 'animationEasing',
709
- title: '@dashboard:widgets.bar-chart.animation-easing',
710
- group: AXP_APPEARANCE_PROPERTY_GROUP,
711
- schema: {
712
- defaultValue: 'cubic-out',
713
- dataType: 'string',
714
- interface: {
715
- name: 'animationEasing',
716
- path: 'options.animationEasing',
717
- type: AXPWidgetsCatalog.select,
718
- options: {
719
- dataSource: [
720
- { value: 'linear', text: 'Linear' },
721
- { value: 'ease', text: 'Ease' },
722
- { value: 'ease-in', text: 'Ease In' },
723
- { value: 'ease-out', text: 'Ease Out' },
724
- { value: 'ease-in-out', text: 'Ease In Out' },
725
- { value: 'cubic', text: 'Cubic' },
726
- { value: 'cubic-in', text: 'Cubic In' },
727
- { value: 'cubic-out', text: 'Cubic Out' },
728
- { value: 'cubic-in-out', text: 'Cubic In Out' },
729
- ],
730
- textField: 'text',
731
- valueField: 'value',
732
- },
733
- },
723
+ name: 'animationEasing',
724
+ title: '@dashboard:widgets.bar-chart.animation-easing',
725
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
726
+ schema: {
727
+ defaultValue: 'cubic-out',
728
+ dataType: 'string',
729
+ interface: {
730
+ name: 'animationEasing',
731
+ path: 'options.animationEasing',
732
+ type: AXPWidgetsCatalog.select,
733
+ options: {
734
+ dataSource: [
735
+ { value: 'linear', text: 'Linear' },
736
+ { value: 'ease', text: 'Ease' },
737
+ { value: 'ease-in', text: 'Ease In' },
738
+ { value: 'ease-out', text: 'Ease Out' },
739
+ { value: 'ease-in-out', text: 'Ease In Out' },
740
+ { value: 'cubic', text: 'Cubic' },
741
+ { value: 'cubic-in', text: 'Cubic In' },
742
+ { value: 'cubic-out', text: 'Cubic Out' },
743
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
744
+ ],
745
+ textField: 'text',
746
+ valueField: 'value',
747
+ },
734
748
  },
735
- visible: true,
749
+ },
750
+ visible: true,
736
751
  },
737
752
  {
738
- name: 'animationDuration',
739
- title: '@dashboard:widgets.bar-chart.animation-duration',
740
- group: AXP_APPEARANCE_PROPERTY_GROUP,
741
- schema: {
742
- defaultValue: 800,
743
- dataType: 'number',
744
- interface: {
745
- name: 'animationDuration',
746
- path: 'options.animationDuration',
747
- type: AXPWidgetsCatalog.number,
748
- options: {
749
- placeholder: '0-2000',
750
- minValue: 0,
751
- maxValue: 2000,
752
- },
753
- },
753
+ name: 'animationDuration',
754
+ title: '@dashboard:widgets.bar-chart.animation-duration',
755
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
756
+ schema: {
757
+ defaultValue: 800,
758
+ dataType: 'number',
759
+ interface: {
760
+ name: 'animationDuration',
761
+ path: 'options.animationDuration',
762
+ type: AXPWidgetsCatalog.number,
763
+ options: {
764
+ placeholder: '0-2000',
765
+ minValue: 0,
766
+ maxValue: 2000,
767
+ },
754
768
  },
755
- visible: true,
769
+ },
770
+ visible: true,
756
771
  },
772
+ */
757
773
  ],
758
774
  components: {
759
775
  view: {
@@ -1126,20 +1142,31 @@ const AXPClockCalendarWidget = {
1126
1142
  */
1127
1143
  class AXPDonutChartWidgetViewComponent extends AXPValueWidgetComponent {
1128
1144
  constructor() {
1129
- super(...arguments);
1145
+ super();
1130
1146
  this.donutChartData = computed(() => this.getValue());
1131
1147
  this.donutChartOptions = computed(() => this.options());
1148
+ this.setOptions({
1149
+ ...this.options(),
1150
+ width: 300,
1151
+ height: 300,
1152
+ showDataLabels: false,
1153
+ donutWidth: 35,
1154
+ cornerRadius: 4,
1155
+ showTooltip: true,
1156
+ animationEasing: 'cubic-out',
1157
+ animationDuration: 800,
1158
+ });
1132
1159
  }
1133
1160
  handleDonutChartSegmentClick(event) {
1134
1161
  //console.log(event);
1135
1162
  }
1136
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPDonutChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1163
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPDonutChartWidgetViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1137
1164
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: AXPDonutChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-donut-chart\n [data]=\"donutChartData()\"\n [options]=\"donutChartOptions()\"\n (segmentClick)=\"handleDonutChartSegmentClick($event)\"\n></ax-donut-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXDonutChartComponent, selector: "ax-donut-chart", inputs: ["data", "options"], outputs: ["segmentClick", "segmentHover"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1138
1165
  }
1139
1166
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPDonutChartWidgetViewComponent, decorators: [{
1140
1167
  type: Component,
1141
1168
  args: [{ imports: [AXDonutChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-donut-chart\n [data]=\"donutChartData()\"\n [options]=\"donutChartOptions()\"\n (segmentClick)=\"handleDonutChartSegmentClick($event)\"\n></ax-donut-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
1142
- }] });
1169
+ }], ctorParameters: () => [] });
1143
1170
 
1144
1171
  var donutChartWidget_component = /*#__PURE__*/Object.freeze({
1145
1172
  __proto__: null,
@@ -1175,100 +1202,101 @@ const AXPDonutChartWidget = {
1175
1202
  },
1176
1203
  visible: true,
1177
1204
  },
1205
+ /* Commented out properties
1178
1206
  // ====== Size & Layout ======
1179
1207
  {
1180
- name: 'width',
1181
- title: '@dashboard:widgets.donut-chart.width',
1182
- group: AXP_STYLING_PROPERTY_GROUP,
1183
- schema: {
1184
- defaultValue: 300,
1185
- dataType: 'number',
1186
- interface: {
1187
- name: 'width',
1188
- path: 'options.width',
1189
- type: AXPWidgetsCatalog.number,
1190
- options: {
1191
- minValue: 200,
1192
- maxValue: 1200,
1193
- },
1194
- },
1208
+ name: 'width',
1209
+ title: '@dashboard:widgets.donut-chart.width',
1210
+ group: AXP_STYLING_PROPERTY_GROUP,
1211
+ schema: {
1212
+ defaultValue: 300,
1213
+ dataType: 'number',
1214
+ interface: {
1215
+ name: 'width',
1216
+ path: 'options.width',
1217
+ type: AXPWidgetsCatalog.number,
1218
+ options: {
1219
+ minValue: 200,
1220
+ maxValue: 1200,
1221
+ },
1195
1222
  },
1196
- visible: true,
1223
+ },
1224
+ visible: true,
1197
1225
  },
1198
1226
  {
1199
- name: 'height',
1200
- title: '@dashboard:widgets.donut-chart.height',
1201
- group: AXP_STYLING_PROPERTY_GROUP,
1202
- schema: {
1203
- defaultValue: 300,
1204
- dataType: 'number',
1205
- interface: {
1206
- name: 'height',
1207
- path: 'options.height',
1208
- type: AXPWidgetsCatalog.number,
1209
- options: {
1210
- minValue: 200,
1211
- maxValue: 800,
1212
- },
1213
- },
1227
+ name: 'height',
1228
+ title: '@dashboard:widgets.donut-chart.height',
1229
+ group: AXP_STYLING_PROPERTY_GROUP,
1230
+ schema: {
1231
+ defaultValue: 300,
1232
+ dataType: 'number',
1233
+ interface: {
1234
+ name: 'height',
1235
+ path: 'options.height',
1236
+ type: AXPWidgetsCatalog.number,
1237
+ options: {
1238
+ minValue: 200,
1239
+ maxValue: 800,
1240
+ },
1214
1241
  },
1215
- visible: true,
1242
+ },
1243
+ visible: true,
1216
1244
  },
1217
1245
  // ====== Donut Appearance ======
1218
1246
  {
1219
- name: 'showDataLabels',
1220
- title: '@dashboard:widgets.donut-chart.show-data-labels',
1221
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1222
- schema: {
1223
- defaultValue: true,
1224
- dataType: 'boolean',
1225
- interface: {
1226
- name: 'showDataLabels',
1227
- path: 'options.showDataLabels',
1228
- type: AXPWidgetsCatalog.toggle,
1229
- },
1247
+ name: 'showDataLabels',
1248
+ title: '@dashboard:widgets.donut-chart.show-data-labels',
1249
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1250
+ schema: {
1251
+ defaultValue: true,
1252
+ dataType: 'boolean',
1253
+ interface: {
1254
+ name: 'showDataLabels',
1255
+ path: 'options.showDataLabels',
1256
+ type: AXPWidgetsCatalog.toggle,
1230
1257
  },
1231
- visible: true,
1258
+ },
1259
+ visible: true,
1232
1260
  },
1233
1261
  {
1234
- name: 'donutWidth',
1235
- title: '@dashboard:widgets.donut-chart.donut-width',
1236
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1237
- schema: {
1238
- defaultValue: 35,
1239
- dataType: 'number',
1240
- interface: {
1241
- name: 'donutWidth',
1242
- path: 'options.donutWidth',
1243
- type: AXPWidgetsCatalog.number,
1244
- options: {
1245
- placeholder: '10-80',
1246
- minValue: 10,
1247
- maxValue: 80,
1248
- },
1249
- },
1262
+ name: 'donutWidth',
1263
+ title: '@dashboard:widgets.donut-chart.donut-width',
1264
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1265
+ schema: {
1266
+ defaultValue: 35,
1267
+ dataType: 'number',
1268
+ interface: {
1269
+ name: 'donutWidth',
1270
+ path: 'options.donutWidth',
1271
+ type: AXPWidgetsCatalog.number,
1272
+ options: {
1273
+ placeholder: '10-80',
1274
+ minValue: 10,
1275
+ maxValue: 80,
1276
+ },
1250
1277
  },
1251
- visible: true,
1278
+ },
1279
+ visible: true,
1252
1280
  },
1253
1281
  {
1254
- name: 'cornerRadius',
1255
- title: '@dashboard:widgets.donut-chart.corner-radius',
1256
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1257
- schema: {
1258
- defaultValue: 4,
1259
- dataType: 'number',
1260
- interface: {
1261
- name: 'cornerRadius',
1262
- path: 'options.cornerRadius',
1263
- type: AXPWidgetsCatalog.number,
1264
- options: {
1265
- placeholder: '0-20',
1266
- minValue: 0,
1267
- maxValue: 20,
1268
- },
1269
- },
1282
+ name: 'cornerRadius',
1283
+ title: '@dashboard:widgets.donut-chart.corner-radius',
1284
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1285
+ schema: {
1286
+ defaultValue: 4,
1287
+ dataType: 'number',
1288
+ interface: {
1289
+ name: 'cornerRadius',
1290
+ path: 'options.cornerRadius',
1291
+ type: AXPWidgetsCatalog.number,
1292
+ options: {
1293
+ placeholder: '0-20',
1294
+ minValue: 0,
1295
+ maxValue: 20,
1296
+ },
1270
1297
  },
1271
- visible: true,
1298
+ },
1299
+ visible: true,
1272
1300
  },
1273
1301
  // ====== Legend ======
1274
1302
  // {
@@ -1306,71 +1334,72 @@ const AXPDonutChartWidget = {
1306
1334
  // },
1307
1335
  // ====== Tooltip ======
1308
1336
  {
1309
- name: 'showTooltip',
1310
- title: '@dashboard:widgets.donut-chart.show-tooltip',
1311
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1312
- schema: {
1313
- defaultValue: true,
1314
- dataType: 'boolean',
1315
- interface: {
1316
- name: 'showTooltip',
1317
- path: 'options.showTooltip',
1318
- type: AXPWidgetsCatalog.toggle,
1319
- },
1337
+ name: 'showTooltip',
1338
+ title: '@dashboard:widgets.donut-chart.show-tooltip',
1339
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1340
+ schema: {
1341
+ defaultValue: true,
1342
+ dataType: 'boolean',
1343
+ interface: {
1344
+ name: 'showTooltip',
1345
+ path: 'options.showTooltip',
1346
+ type: AXPWidgetsCatalog.toggle,
1320
1347
  },
1321
- visible: true,
1348
+ },
1349
+ visible: true,
1322
1350
  },
1323
1351
  // ====== Animation Settings ======
1324
1352
  {
1325
- name: 'animationEasing',
1326
- title: '@dashboard:widgets.donut-chart.animation-easing',
1327
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1328
- schema: {
1329
- defaultValue: 'cubic-out',
1330
- dataType: 'string',
1331
- interface: {
1332
- name: 'animationEasing',
1333
- path: 'options.animationEasing',
1334
- type: AXPWidgetsCatalog.select,
1335
- options: {
1336
- dataSource: [
1337
- { value: 'linear', text: 'Linear' },
1338
- { value: 'ease', text: 'Ease' },
1339
- { value: 'ease-in', text: 'Ease In' },
1340
- { value: 'ease-out', text: 'Ease Out' },
1341
- { value: 'ease-in-out', text: 'Ease In Out' },
1342
- { value: 'cubic', text: 'Cubic' },
1343
- { value: 'cubic-in', text: 'Cubic In' },
1344
- { value: 'cubic-out', text: 'Cubic Out' },
1345
- { value: 'cubic-in-out', text: 'Cubic In Out' },
1346
- ],
1347
- textField: 'text',
1348
- valueField: 'value',
1349
- },
1350
- },
1353
+ name: 'animationEasing',
1354
+ title: '@dashboard:widgets.donut-chart.animation-easing',
1355
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1356
+ schema: {
1357
+ defaultValue: 'cubic-out',
1358
+ dataType: 'string',
1359
+ interface: {
1360
+ name: 'animationEasing',
1361
+ path: 'options.animationEasing',
1362
+ type: AXPWidgetsCatalog.select,
1363
+ options: {
1364
+ dataSource: [
1365
+ { value: 'linear', text: 'Linear' },
1366
+ { value: 'ease', text: 'Ease' },
1367
+ { value: 'ease-in', text: 'Ease In' },
1368
+ { value: 'ease-out', text: 'Ease Out' },
1369
+ { value: 'ease-in-out', text: 'Ease In Out' },
1370
+ { value: 'cubic', text: 'Cubic' },
1371
+ { value: 'cubic-in', text: 'Cubic In' },
1372
+ { value: 'cubic-out', text: 'Cubic Out' },
1373
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
1374
+ ],
1375
+ textField: 'text',
1376
+ valueField: 'value',
1377
+ },
1351
1378
  },
1352
- visible: true,
1379
+ },
1380
+ visible: true,
1353
1381
  },
1354
1382
  {
1355
- name: 'animationDuration',
1356
- title: '@dashboard:widgets.donut-chart.animation-duration',
1357
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1358
- schema: {
1359
- defaultValue: 800,
1360
- dataType: 'number',
1361
- interface: {
1362
- name: 'animationDuration',
1363
- path: 'options.animationDuration',
1364
- type: AXPWidgetsCatalog.number,
1365
- options: {
1366
- placeholder: '0-2000',
1367
- minValue: 0,
1368
- maxValue: 2000,
1369
- },
1370
- },
1383
+ name: 'animationDuration',
1384
+ title: '@dashboard:widgets.donut-chart.animation-duration',
1385
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1386
+ schema: {
1387
+ defaultValue: 800,
1388
+ dataType: 'number',
1389
+ interface: {
1390
+ name: 'animationDuration',
1391
+ path: 'options.animationDuration',
1392
+ type: AXPWidgetsCatalog.number,
1393
+ options: {
1394
+ placeholder: '0-2000',
1395
+ minValue: 0,
1396
+ maxValue: 2000,
1397
+ },
1371
1398
  },
1372
- visible: true,
1399
+ },
1400
+ visible: true,
1373
1401
  },
1402
+ */
1374
1403
  ],
1375
1404
  components: {
1376
1405
  view: {
@@ -1395,17 +1424,29 @@ const AXPDonutChartWidget = {
1395
1424
  */
1396
1425
  class AXPGaugeChartWidgetViewComponent extends AXPValueWidgetComponent {
1397
1426
  constructor() {
1398
- super(...arguments);
1427
+ super();
1399
1428
  this.gaugeChartValue = computed(() => this.getValue());
1400
1429
  this.gaugeChartOptions = computed(() => this.options());
1430
+ this.setOptions({
1431
+ ...this.options(),
1432
+ width: null,
1433
+ height: 300,
1434
+ minValue: 0,
1435
+ maxValue: 100,
1436
+ showTooltip: true,
1437
+ gaugeWidth: 30,
1438
+ cornerRadius: 4,
1439
+ animationEasing: 'cubic-out',
1440
+ animationDuration: 800,
1441
+ });
1401
1442
  }
1402
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPGaugeChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1443
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPGaugeChartWidgetViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1403
1444
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: AXPGaugeChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-gauge-chart [value]=\"gaugeChartValue()\" [options]=\"gaugeChartOptions()\"></ax-gauge-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXGaugeChartComponent, selector: "ax-gauge-chart", inputs: ["value", "options"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1404
1445
  }
1405
1446
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPGaugeChartWidgetViewComponent, decorators: [{
1406
1447
  type: Component,
1407
1448
  args: [{ imports: [AXGaugeChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-gauge-chart [value]=\"gaugeChartValue()\" [options]=\"gaugeChartOptions()\"></ax-gauge-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
1408
- }] });
1449
+ }], ctorParameters: () => [] });
1409
1450
 
1410
1451
  var gaugeChartWidget_component = /*#__PURE__*/Object.freeze({
1411
1452
  __proto__: null,
@@ -1440,201 +1481,203 @@ const AXPGaugeChartWidget = {
1440
1481
  },
1441
1482
  visible: true,
1442
1483
  },
1443
- // ====== Layout & Dimensions ======
1484
+ // ====== Label Display ======
1444
1485
  {
1445
- name: 'width',
1446
- title: '@dashboard:widgets.gauge-chart.width',
1447
- group: AXP_STYLING_PROPERTY_GROUP,
1486
+ name: 'label',
1487
+ title: '@dashboard:widgets.gauge-chart.label',
1488
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1448
1489
  schema: {
1449
- defaultValue: null,
1450
- dataType: 'number',
1490
+ defaultValue: '',
1491
+ dataType: 'string',
1451
1492
  interface: {
1452
- name: 'width',
1453
- path: 'options.width',
1454
- type: AXPWidgetsCatalog.number,
1455
- options: {
1456
- placeholder: '1-1200',
1457
- minValue: 1,
1458
- maxValue: 1200,
1459
- },
1493
+ name: 'label',
1494
+ path: 'options.label',
1495
+ type: AXPWidgetsCatalog.text,
1460
1496
  },
1461
1497
  },
1462
1498
  visible: true,
1463
1499
  },
1500
+ /* Commented out properties
1501
+ // ====== Layout & Dimensions ======
1464
1502
  {
1465
- name: 'height',
1466
- title: '@dashboard:widgets.gauge-chart.height',
1467
- group: AXP_STYLING_PROPERTY_GROUP,
1468
- schema: {
1469
- defaultValue: 300,
1470
- dataType: 'number',
1471
- interface: {
1472
- name: 'height',
1473
- path: 'options.height',
1474
- type: AXPWidgetsCatalog.number,
1475
- options: {
1476
- placeholder: '1-800',
1477
- minValue: 1,
1478
- maxValue: 800,
1479
- },
1480
- },
1503
+ name: 'width',
1504
+ title: '@dashboard:widgets.gauge-chart.width',
1505
+ group: AXP_STYLING_PROPERTY_GROUP,
1506
+ schema: {
1507
+ defaultValue: null,
1508
+ dataType: 'number',
1509
+ interface: {
1510
+ name: 'width',
1511
+ path: 'options.width',
1512
+ type: AXPWidgetsCatalog.number,
1513
+ options: {
1514
+ placeholder: '1-1200',
1515
+ minValue: 1,
1516
+ maxValue: 1200,
1517
+ },
1481
1518
  },
1482
- visible: true,
1519
+ },
1520
+ visible: true,
1483
1521
  },
1484
- // ====== Gauge Configuration ======
1485
1522
  {
1486
- name: 'minValue',
1487
- title: '@dashboard:widgets.gauge-chart.min-value',
1488
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1489
- schema: {
1490
- defaultValue: 0,
1491
- dataType: 'number',
1492
- interface: {
1493
- name: 'minValue',
1494
- path: 'options.minValue',
1495
- type: AXPWidgetsCatalog.number,
1496
- },
1523
+ name: 'height',
1524
+ title: '@dashboard:widgets.gauge-chart.height',
1525
+ group: AXP_STYLING_PROPERTY_GROUP,
1526
+ schema: {
1527
+ defaultValue: 300,
1528
+ dataType: 'number',
1529
+ interface: {
1530
+ name: 'height',
1531
+ path: 'options.height',
1532
+ type: AXPWidgetsCatalog.number,
1533
+ options: {
1534
+ placeholder: '1-800',
1535
+ minValue: 1,
1536
+ maxValue: 800,
1537
+ },
1497
1538
  },
1498
- visible: true,
1539
+ },
1540
+ visible: true,
1499
1541
  },
1542
+ // ====== Gauge Configuration ======
1500
1543
  {
1501
- name: 'maxValue',
1502
- title: '@dashboard:widgets.gauge-chart.max-value',
1503
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1504
- schema: {
1505
- defaultValue: 100,
1506
- dataType: 'number',
1507
- interface: {
1508
- name: 'maxValue',
1509
- path: 'options.maxValue',
1510
- type: AXPWidgetsCatalog.number,
1511
- },
1544
+ name: 'minValue',
1545
+ title: '@dashboard:widgets.gauge-chart.min-value',
1546
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1547
+ schema: {
1548
+ defaultValue: 0,
1549
+ dataType: 'number',
1550
+ interface: {
1551
+ name: 'minValue',
1552
+ path: 'options.minValue',
1553
+ type: AXPWidgetsCatalog.number,
1512
1554
  },
1513
- visible: true,
1555
+ },
1556
+ visible: true,
1514
1557
  },
1515
- // ====== Gauge Appearance ======
1516
1558
  {
1517
- name: 'showTooltip',
1518
- title: '@dashboard:widgets.gauge-chart.show-tooltip',
1519
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1520
- schema: {
1521
- defaultValue: true,
1522
- dataType: 'boolean',
1523
- interface: {
1524
- name: 'showTooltip',
1525
- path: 'options.showTooltip',
1526
- type: AXPWidgetsCatalog.toggle,
1527
- },
1559
+ name: 'maxValue',
1560
+ title: '@dashboard:widgets.gauge-chart.max-value',
1561
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1562
+ schema: {
1563
+ defaultValue: 100,
1564
+ dataType: 'number',
1565
+ interface: {
1566
+ name: 'maxValue',
1567
+ path: 'options.maxValue',
1568
+ type: AXPWidgetsCatalog.number,
1528
1569
  },
1529
- visible: true,
1570
+ },
1571
+ visible: true,
1530
1572
  },
1573
+ // ====== Gauge Appearance ======
1531
1574
  {
1532
- name: 'gaugeWidth',
1533
- title: '@dashboard:widgets.gauge-chart.gauge-width',
1534
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1535
- schema: {
1536
- defaultValue: 30,
1537
- dataType: 'number',
1538
- interface: {
1539
- name: 'gaugeWidth',
1540
- path: 'options.gaugeWidth',
1541
- type: AXPWidgetsCatalog.number,
1542
- options: {
1543
- placeholder: '1-100',
1544
- minValue: 1,
1545
- maxValue: 100,
1546
- },
1547
- },
1575
+ name: 'showTooltip',
1576
+ title: '@dashboard:widgets.gauge-chart.show-tooltip',
1577
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1578
+ schema: {
1579
+ defaultValue: true,
1580
+ dataType: 'boolean',
1581
+ interface: {
1582
+ name: 'showTooltip',
1583
+ path: 'options.showTooltip',
1584
+ type: AXPWidgetsCatalog.toggle,
1548
1585
  },
1549
- visible: true,
1586
+ },
1587
+ visible: true,
1550
1588
  },
1551
1589
  {
1552
- name: 'cornerRadius',
1553
- title: '@dashboard:widgets.gauge-chart.corner-radius',
1554
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1555
- schema: {
1556
- defaultValue: 4,
1557
- dataType: 'number',
1558
- interface: {
1559
- name: 'cornerRadius',
1560
- path: 'options.cornerRadius',
1561
- type: AXPWidgetsCatalog.number,
1562
- options: {
1563
- placeholder: '1-20',
1564
- minValue: 0,
1565
- maxValue: 20,
1566
- },
1567
- },
1590
+ name: 'gaugeWidth',
1591
+ title: '@dashboard:widgets.gauge-chart.gauge-width',
1592
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1593
+ schema: {
1594
+ defaultValue: 30,
1595
+ dataType: 'number',
1596
+ interface: {
1597
+ name: 'gaugeWidth',
1598
+ path: 'options.gaugeWidth',
1599
+ type: AXPWidgetsCatalog.number,
1600
+ options: {
1601
+ placeholder: '1-100',
1602
+ minValue: 1,
1603
+ maxValue: 100,
1604
+ },
1568
1605
  },
1569
- visible: true,
1606
+ },
1607
+ visible: true,
1570
1608
  },
1571
- // ====== Label Display ======
1572
1609
  {
1573
- name: 'label',
1574
- title: '@dashboard:widgets.gauge-chart.label',
1575
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1576
- schema: {
1577
- defaultValue: '',
1578
- dataType: 'string',
1579
- interface: {
1580
- name: 'label',
1581
- path: 'options.label',
1582
- type: AXPWidgetsCatalog.text,
1583
- },
1610
+ name: 'cornerRadius',
1611
+ title: '@dashboard:widgets.gauge-chart.corner-radius',
1612
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1613
+ schema: {
1614
+ defaultValue: 4,
1615
+ dataType: 'number',
1616
+ interface: {
1617
+ name: 'cornerRadius',
1618
+ path: 'options.cornerRadius',
1619
+ type: AXPWidgetsCatalog.number,
1620
+ options: {
1621
+ placeholder: '1-20',
1622
+ minValue: 0,
1623
+ maxValue: 20,
1624
+ },
1584
1625
  },
1585
- visible: true,
1626
+ },
1627
+ visible: true,
1586
1628
  },
1587
1629
  // ====== Animation Settings ======
1588
1630
  {
1589
- name: 'animationEasing',
1590
- title: '@dashboard:widgets.gauge-chart.animation-easing',
1591
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1592
- schema: {
1593
- defaultValue: 'cubic-out',
1594
- dataType: 'string',
1595
- interface: {
1596
- name: 'animationEasing',
1597
- path: 'options.animationEasing',
1598
- type: AXPWidgetsCatalog.select,
1599
- options: {
1600
- dataSource: [
1601
- { value: 'linear', text: 'Linear' },
1602
- { value: 'ease', text: 'Ease' },
1603
- { value: 'ease-in', text: 'Ease In' },
1604
- { value: 'ease-out', text: 'Ease Out' },
1605
- { value: 'ease-in-out', text: 'Ease In Out' },
1606
- { value: 'cubic', text: 'Cubic' },
1607
- { value: 'cubic-in', text: 'Cubic In' },
1608
- { value: 'cubic-out', text: 'Cubic Out' },
1609
- { value: 'cubic-in-out', text: 'Cubic In Out' },
1610
- ],
1611
- textField: 'text',
1612
- valueField: 'value',
1613
- },
1614
- },
1631
+ name: 'animationEasing',
1632
+ title: '@dashboard:widgets.gauge-chart.animation-easing',
1633
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1634
+ schema: {
1635
+ defaultValue: 'cubic-out',
1636
+ dataType: 'string',
1637
+ interface: {
1638
+ name: 'animationEasing',
1639
+ path: 'options.animationEasing',
1640
+ type: AXPWidgetsCatalog.select,
1641
+ options: {
1642
+ dataSource: [
1643
+ { value: 'linear', text: 'Linear' },
1644
+ { value: 'ease', text: 'Ease' },
1645
+ { value: 'ease-in', text: 'Ease In' },
1646
+ { value: 'ease-out', text: 'Ease Out' },
1647
+ { value: 'ease-in-out', text: 'Ease In Out' },
1648
+ { value: 'cubic', text: 'Cubic' },
1649
+ { value: 'cubic-in', text: 'Cubic In' },
1650
+ { value: 'cubic-out', text: 'Cubic Out' },
1651
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
1652
+ ],
1653
+ textField: 'text',
1654
+ valueField: 'value',
1655
+ },
1615
1656
  },
1616
- visible: true,
1657
+ },
1658
+ visible: true,
1617
1659
  },
1618
1660
  {
1619
- name: 'animationDuration',
1620
- title: '@dashboard:widgets.gauge-chart.animation-duration',
1621
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1622
- schema: {
1623
- defaultValue: 800,
1624
- dataType: 'number',
1625
- interface: {
1626
- name: 'animationDuration',
1627
- path: 'options.animationDuration',
1628
- type: AXPWidgetsCatalog.number,
1629
- options: {
1630
- placeholder: '0-2000',
1631
- minValue: 0,
1632
- maxValue: 2000,
1633
- },
1634
- },
1661
+ name: 'animationDuration',
1662
+ title: '@dashboard:widgets.gauge-chart.animation-duration',
1663
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1664
+ schema: {
1665
+ defaultValue: 800,
1666
+ dataType: 'number',
1667
+ interface: {
1668
+ name: 'animationDuration',
1669
+ path: 'options.animationDuration',
1670
+ type: AXPWidgetsCatalog.number,
1671
+ options: {
1672
+ placeholder: '0-2000',
1673
+ minValue: 0,
1674
+ maxValue: 2000,
1675
+ },
1635
1676
  },
1636
- visible: true,
1677
+ },
1678
+ visible: true,
1637
1679
  },
1680
+ */
1638
1681
  ],
1639
1682
  components: {
1640
1683
  view: {
@@ -1659,20 +1702,37 @@ const AXPGaugeChartWidget = {
1659
1702
  */
1660
1703
  class AXPLineChartWidgetViewComponent extends AXPValueWidgetComponent {
1661
1704
  constructor() {
1662
- super(...arguments);
1705
+ super();
1663
1706
  this.lineChartData = computed(() => this.getValue());
1664
1707
  this.lineChartOptions = computed(() => this.options());
1708
+ this.setOptions({
1709
+ ...this.options(),
1710
+ showXAxis: true,
1711
+ showYAxis: true,
1712
+ yAxisStartsAtZero: true,
1713
+ showGrid: true,
1714
+ showVerticalGrid: true,
1715
+ lineWidth: 2,
1716
+ smoothLine: true,
1717
+ showPoints: true,
1718
+ pointRadius: 4,
1719
+ fillOpacity: 80,
1720
+ showTooltip: true,
1721
+ showCrosshair: true,
1722
+ animationEasing: 'cubic-out',
1723
+ animationDuration: 800,
1724
+ });
1665
1725
  }
1666
1726
  handleLineChartPointClick(event) {
1667
1727
  //console.log(event);
1668
1728
  }
1669
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPLineChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1729
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPLineChartWidgetViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1670
1730
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: AXPLineChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-line-chart\n (pointClick)=\"handleLineChartPointClick($event)\"\n [data]=\"lineChartData()\"\n [options]=\"lineChartOptions()\"\n></ax-line-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXLineChartComponent, selector: "ax-line-chart", inputs: ["data", "options"], outputs: ["pointClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1671
1731
  }
1672
1732
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPLineChartWidgetViewComponent, decorators: [{
1673
1733
  type: Component,
1674
1734
  args: [{ standalone: true, imports: [AXLineChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-line-chart\n (pointClick)=\"handleLineChartPointClick($event)\"\n [data]=\"lineChartData()\"\n [options]=\"lineChartOptions()\"\n></ax-line-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
1675
- }] });
1735
+ }], ctorParameters: () => [] });
1676
1736
 
1677
1737
  var lineChartWidget_component = /*#__PURE__*/Object.freeze({
1678
1738
  __proto__: null,
@@ -1708,218 +1768,33 @@ const AXPLineChartWidget = {
1708
1768
  },
1709
1769
  visible: true,
1710
1770
  },
1711
- // ====== Layout & Dimensions ======
1712
- {
1713
- name: 'width',
1714
- title: '@dashboard:widgets.line-chart.width',
1715
- group: AXP_STYLING_PROPERTY_GROUP,
1716
- schema: {
1717
- defaultValue: null,
1718
- dataType: 'number',
1719
- interface: {
1720
- name: 'width',
1721
- path: 'options.width',
1722
- type: AXPWidgetsCatalog.number,
1723
- options: {
1724
- minValue: 0,
1725
- maxValue: 1200,
1726
- },
1727
- },
1728
- },
1729
- visible: true,
1730
- },
1731
- {
1732
- name: 'height',
1733
- title: '@dashboard:widgets.line-chart.height',
1734
- group: AXP_STYLING_PROPERTY_GROUP,
1735
- schema: {
1736
- defaultValue: 300,
1737
- dataType: 'number',
1738
- interface: {
1739
- name: 'height',
1740
- path: 'options.height',
1741
- type: AXPWidgetsCatalog.number,
1742
- options: {
1743
- minValue: 0,
1744
- maxValue: 800,
1745
- },
1746
- },
1747
- },
1748
- visible: true,
1749
- },
1750
1771
  // ====== Axis Settings ======
1751
- {
1752
- name: 'showXAxis',
1753
- title: '@dashboard:widgets.line-chart.show-x-axis',
1754
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1755
- schema: {
1756
- defaultValue: true,
1757
- dataType: 'boolean',
1758
- interface: {
1759
- name: 'showXAxis',
1760
- path: 'options.showXAxis',
1761
- type: AXPWidgetsCatalog.toggle,
1762
- },
1763
- },
1764
- visible: true,
1765
- },
1766
1772
  {
1767
1773
  name: 'xAxisLabel',
1768
1774
  title: '@dashboard:widgets.line-chart.x-axis-label',
1769
1775
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1770
1776
  schema: {
1771
- defaultValue: '',
1772
- dataType: 'string',
1773
- interface: {
1774
- name: 'xAxisLabel',
1775
- path: 'options.xAxisLabel',
1776
- type: AXPWidgetsCatalog.text,
1777
- },
1778
- },
1779
- visible: true,
1780
- },
1781
- {
1782
- name: 'showYAxis',
1783
- title: '@dashboard:widgets.line-chart.show-y-axis',
1784
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1785
- schema: {
1786
- defaultValue: true,
1787
- dataType: 'boolean',
1788
- interface: {
1789
- name: 'showYAxis',
1790
- path: 'options.showYAxis',
1791
- type: AXPWidgetsCatalog.toggle,
1792
- },
1793
- },
1794
- visible: true,
1795
- },
1796
- {
1797
- name: 'yAxisLabel',
1798
- title: '@dashboard:widgets.line-chart.y-axis-label',
1799
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1800
- schema: {
1801
- defaultValue: '',
1802
- dataType: 'string',
1803
- interface: {
1804
- name: 'yAxisLabel',
1805
- path: 'options.yAxisLabel',
1806
- type: AXPWidgetsCatalog.text,
1807
- },
1808
- },
1809
- visible: true,
1810
- },
1811
- {
1812
- name: 'yAxisStartsAtZero',
1813
- title: '@dashboard:widgets.line-chart.y-axis-starts-at-zero',
1814
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1815
- schema: {
1816
- defaultValue: true,
1817
- dataType: 'boolean',
1818
- interface: {
1819
- name: 'yAxisStartsAtZero',
1820
- path: 'options.yAxisStartsAtZero',
1821
- type: AXPWidgetsCatalog.toggle,
1822
- },
1823
- },
1824
- visible: true,
1825
- },
1826
- {
1827
- name: 'showGrid',
1828
- title: '@dashboard:widgets.line-chart.show-grid',
1829
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1830
- schema: {
1831
- defaultValue: true,
1832
- dataType: 'boolean',
1833
- interface: {
1834
- name: 'showGrid',
1835
- path: 'options.showGrid',
1836
- type: AXPWidgetsCatalog.toggle,
1837
- },
1838
- },
1839
- visible: true,
1840
- },
1841
- {
1842
- name: 'showVerticalGrid',
1843
- title: '@dashboard:widgets.line-chart.show-vertical-grid',
1844
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1845
- schema: {
1846
- defaultValue: true,
1847
- dataType: 'boolean',
1848
- interface: {
1849
- name: 'showVerticalGrid',
1850
- path: 'options.showVerticalGrid',
1851
- type: AXPWidgetsCatalog.toggle,
1852
- },
1853
- },
1854
- visible: true,
1855
- },
1856
- // ====== Line Appearance ======
1857
- {
1858
- name: 'lineWidth',
1859
- title: '@dashboard:widgets.line-chart.line-width',
1860
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1861
- schema: {
1862
- defaultValue: 2,
1863
- dataType: 'number',
1864
- interface: {
1865
- name: 'lineWidth',
1866
- path: 'options.lineWidth',
1867
- type: AXPWidgetsCatalog.number,
1868
- options: {
1869
- placeholder: '1-10',
1870
- minValue: 1,
1871
- maxValue: 10,
1872
- },
1873
- },
1874
- },
1875
- visible: true,
1876
- },
1877
- {
1878
- name: 'smoothLine',
1879
- title: '@dashboard:widgets.line-chart.smooth-line',
1880
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1881
- schema: {
1882
- defaultValue: true,
1883
- dataType: 'boolean',
1884
- interface: {
1885
- name: 'smoothLine',
1886
- path: 'options.smoothLine',
1887
- type: AXPWidgetsCatalog.toggle,
1888
- },
1889
- },
1890
- visible: true,
1891
- },
1892
- {
1893
- name: 'showPoints',
1894
- title: '@dashboard:widgets.line-chart.show-points',
1895
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1896
- schema: {
1897
- defaultValue: true,
1898
- dataType: 'boolean',
1777
+ defaultValue: '',
1778
+ dataType: 'string',
1899
1779
  interface: {
1900
- name: 'showPoints',
1901
- path: 'options.showPoints',
1902
- type: AXPWidgetsCatalog.toggle,
1780
+ name: 'xAxisLabel',
1781
+ path: 'options.xAxisLabel',
1782
+ type: AXPWidgetsCatalog.text,
1903
1783
  },
1904
1784
  },
1905
1785
  visible: true,
1906
1786
  },
1907
1787
  {
1908
- name: 'pointRadius',
1909
- title: '@dashboard:widgets.line-chart.point-radius',
1788
+ name: 'yAxisLabel',
1789
+ title: '@dashboard:widgets.line-chart.y-axis-label',
1910
1790
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1911
1791
  schema: {
1912
- defaultValue: 4,
1913
- dataType: 'number',
1792
+ defaultValue: '',
1793
+ dataType: 'string',
1914
1794
  interface: {
1915
- name: 'pointRadius',
1916
- path: 'options.pointRadius',
1917
- type: AXPWidgetsCatalog.number,
1918
- options: {
1919
- placeholder: '1-10',
1920
- minValue: 1,
1921
- maxValue: 10,
1922
- },
1795
+ name: 'yAxisLabel',
1796
+ path: 'options.yAxisLabel',
1797
+ type: AXPWidgetsCatalog.text,
1923
1798
  },
1924
1799
  },
1925
1800
  visible: true,
@@ -1939,109 +1814,301 @@ const AXPLineChartWidget = {
1939
1814
  },
1940
1815
  visible: true,
1941
1816
  },
1817
+ /* Commented out properties
1818
+ // ====== Layout & Dimensions ======
1942
1819
  {
1943
- name: 'fillOpacity',
1944
- title: '@dashboard:widgets.line-chart.fill-opacity',
1945
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1946
- schema: {
1947
- defaultValue: 0.1,
1948
- dataType: 'number',
1949
- interface: {
1950
- name: 'fillOpacity',
1951
- path: 'options.fillOpacity',
1952
- type: AXPWidgetsCatalog.number,
1953
- options: {
1954
- placeholder: '0-1',
1955
- minValue: 0,
1956
- maxValue: 1,
1957
- step: 0.1,
1958
- },
1959
- },
1820
+ name: 'width',
1821
+ title: '@dashboard:widgets.line-chart.width',
1822
+ group: AXP_STYLING_PROPERTY_GROUP,
1823
+ schema: {
1824
+ defaultValue: null,
1825
+ dataType: 'number',
1826
+ interface: {
1827
+ name: 'width',
1828
+ path: 'options.width',
1829
+ type: AXPWidgetsCatalog.number,
1830
+ options: {
1831
+ minValue: 0,
1832
+ maxValue: 1200,
1833
+ },
1960
1834
  },
1961
- visible: true,
1835
+ },
1836
+ visible: true,
1837
+ },
1838
+ {
1839
+ name: 'height',
1840
+ title: '@dashboard:widgets.line-chart.height',
1841
+ group: AXP_STYLING_PROPERTY_GROUP,
1842
+ schema: {
1843
+ defaultValue: 300,
1844
+ dataType: 'number',
1845
+ interface: {
1846
+ name: 'height',
1847
+ path: 'options.height',
1848
+ type: AXPWidgetsCatalog.number,
1849
+ options: {
1850
+ minValue: 0,
1851
+ maxValue: 800,
1852
+ },
1853
+ },
1854
+ },
1855
+ visible: true,
1856
+ },
1857
+
1858
+ // ====== Axis Settings ======
1859
+ {
1860
+ name: 'showXAxis',
1861
+ title: '@dashboard:widgets.line-chart.show-x-axis',
1862
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1863
+ schema: {
1864
+ defaultValue: true,
1865
+ dataType: 'boolean',
1866
+ interface: {
1867
+ name: 'showXAxis',
1868
+ path: 'options.showXAxis',
1869
+ type: AXPWidgetsCatalog.toggle,
1870
+ },
1871
+ },
1872
+ visible: true,
1873
+ },
1874
+ {
1875
+ name: 'showYAxis',
1876
+ title: '@dashboard:widgets.line-chart.show-y-axis',
1877
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1878
+ schema: {
1879
+ defaultValue: true,
1880
+ dataType: 'boolean',
1881
+ interface: {
1882
+ name: 'showYAxis',
1883
+ path: 'options.showYAxis',
1884
+ type: AXPWidgetsCatalog.toggle,
1885
+ },
1886
+ },
1887
+ visible: true,
1888
+ },
1889
+ {
1890
+ name: 'yAxisStartsAtZero',
1891
+ title: '@dashboard:widgets.line-chart.y-axis-starts-at-zero',
1892
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1893
+ schema: {
1894
+ defaultValue: true,
1895
+ dataType: 'boolean',
1896
+ interface: {
1897
+ name: 'yAxisStartsAtZero',
1898
+ path: 'options.yAxisStartsAtZero',
1899
+ type: AXPWidgetsCatalog.toggle,
1900
+ },
1901
+ },
1902
+ visible: true,
1903
+ },
1904
+
1905
+ {
1906
+ name: 'showGrid',
1907
+ title: '@dashboard:widgets.line-chart.show-grid',
1908
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1909
+ schema: {
1910
+ defaultValue: true,
1911
+ dataType: 'boolean',
1912
+ interface: {
1913
+ name: 'showGrid',
1914
+ path: 'options.showGrid',
1915
+ type: AXPWidgetsCatalog.toggle,
1916
+ },
1917
+ },
1918
+ visible: true,
1919
+ },
1920
+ {
1921
+ name: 'showVerticalGrid',
1922
+ title: '@dashboard:widgets.line-chart.show-vertical-grid',
1923
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1924
+ schema: {
1925
+ defaultValue: true,
1926
+ dataType: 'boolean',
1927
+ interface: {
1928
+ name: 'showVerticalGrid',
1929
+ path: 'options.showVerticalGrid',
1930
+ type: AXPWidgetsCatalog.toggle,
1931
+ },
1932
+ },
1933
+ visible: true,
1934
+ },
1935
+
1936
+ // ====== Line Appearance ======
1937
+ {
1938
+ name: 'lineWidth',
1939
+ title: '@dashboard:widgets.line-chart.line-width',
1940
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1941
+ schema: {
1942
+ defaultValue: 2,
1943
+ dataType: 'number',
1944
+ interface: {
1945
+ name: 'lineWidth',
1946
+ path: 'options.lineWidth',
1947
+ type: AXPWidgetsCatalog.number,
1948
+ options: {
1949
+ placeholder: '1-10',
1950
+ minValue: 1,
1951
+ maxValue: 10,
1952
+ },
1953
+ },
1954
+ },
1955
+ visible: true,
1956
+ },
1957
+ {
1958
+ name: 'smoothLine',
1959
+ title: '@dashboard:widgets.line-chart.smooth-line',
1960
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1961
+ schema: {
1962
+ defaultValue: true,
1963
+ dataType: 'boolean',
1964
+ interface: {
1965
+ name: 'smoothLine',
1966
+ path: 'options.smoothLine',
1967
+ type: AXPWidgetsCatalog.toggle,
1968
+ },
1969
+ },
1970
+ visible: true,
1971
+ },
1972
+ {
1973
+ name: 'showPoints',
1974
+ title: '@dashboard:widgets.line-chart.show-points',
1975
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1976
+ schema: {
1977
+ defaultValue: true,
1978
+ dataType: 'boolean',
1979
+ interface: {
1980
+ name: 'showPoints',
1981
+ path: 'options.showPoints',
1982
+ type: AXPWidgetsCatalog.toggle,
1983
+ },
1984
+ },
1985
+ visible: true,
1986
+ },
1987
+ {
1988
+ name: 'pointRadius',
1989
+ title: '@dashboard:widgets.line-chart.point-radius',
1990
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1991
+ schema: {
1992
+ defaultValue: 4,
1993
+ dataType: 'number',
1994
+ interface: {
1995
+ name: 'pointRadius',
1996
+ path: 'options.pointRadius',
1997
+ type: AXPWidgetsCatalog.number,
1998
+ options: {
1999
+ placeholder: '1-10',
2000
+ minValue: 1,
2001
+ maxValue: 10,
2002
+ },
2003
+ },
2004
+ },
2005
+ visible: true,
2006
+ },
2007
+ {
2008
+ name: 'fillOpacity',
2009
+ title: '@dashboard:widgets.line-chart.fill-opacity',
2010
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2011
+ schema: {
2012
+ defaultValue: 80,
2013
+ dataType: 'number',
2014
+ interface: {
2015
+ name: 'fillOpacity',
2016
+ path: 'options.fillOpacity',
2017
+ type: AXPWidgetsCatalog.number,
2018
+ options: {
2019
+ placeholder: '1-100',
2020
+ minValue: 1,
2021
+ maxValue: 100,
2022
+ },
2023
+ },
2024
+ },
2025
+ visible: true,
1962
2026
  },
2027
+
1963
2028
  // ====== Tooltip Settings ======
1964
2029
  {
1965
- name: 'showTooltip',
1966
- title: '@dashboard:widgets.line-chart.show-tooltip',
1967
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1968
- schema: {
1969
- defaultValue: true,
1970
- dataType: 'boolean',
1971
- interface: {
1972
- name: 'showTooltip',
1973
- path: 'options.showTooltip',
1974
- type: AXPWidgetsCatalog.toggle,
1975
- },
2030
+ name: 'showTooltip',
2031
+ title: '@dashboard:widgets.line-chart.show-tooltip',
2032
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2033
+ schema: {
2034
+ defaultValue: true,
2035
+ dataType: 'boolean',
2036
+ interface: {
2037
+ name: 'showTooltip',
2038
+ path: 'options.showTooltip',
2039
+ type: AXPWidgetsCatalog.toggle,
1976
2040
  },
1977
- visible: true,
2041
+ },
2042
+ visible: true,
1978
2043
  },
1979
2044
  {
1980
- name: 'showCrosshair',
1981
- title: '@dashboard:widgets.line-chart.show-crosshair',
1982
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1983
- schema: {
1984
- defaultValue: true,
1985
- dataType: 'boolean',
1986
- interface: {
1987
- name: 'showCrosshair',
1988
- path: 'options.showCrosshair',
1989
- type: AXPWidgetsCatalog.toggle,
1990
- },
2045
+ name: 'showCrosshair',
2046
+ title: '@dashboard:widgets.line-chart.show-crosshair',
2047
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2048
+ schema: {
2049
+ defaultValue: true,
2050
+ dataType: 'boolean',
2051
+ interface: {
2052
+ name: 'showCrosshair',
2053
+ path: 'options.showCrosshair',
2054
+ type: AXPWidgetsCatalog.toggle,
1991
2055
  },
1992
- visible: true,
2056
+ },
2057
+ visible: true,
1993
2058
  },
2059
+
1994
2060
  // ====== Animation Settings ======
1995
2061
  {
1996
- name: 'animationEasing',
1997
- title: '@dashboard:widgets.line-chart.animation-easing',
1998
- group: AXP_APPEARANCE_PROPERTY_GROUP,
1999
- schema: {
2000
- defaultValue: 'cubic-out',
2001
- dataType: 'string',
2002
- interface: {
2003
- name: 'animationEasing',
2004
- path: 'options.animationEasing',
2005
- type: AXPWidgetsCatalog.select,
2006
- options: {
2007
- dataSource: [
2008
- { value: 'linear', text: 'Linear' },
2009
- { value: 'ease', text: 'Ease' },
2010
- { value: 'ease-in', text: 'Ease In' },
2011
- { value: 'ease-out', text: 'Ease Out' },
2012
- { value: 'ease-in-out', text: 'Ease In Out' },
2013
- { value: 'cubic', text: 'Cubic' },
2014
- { value: 'cubic-in', text: 'Cubic In' },
2015
- { value: 'cubic-out', text: 'Cubic Out' },
2016
- { value: 'cubic-in-out', text: 'Cubic In Out' },
2017
- ],
2018
- textField: 'text',
2019
- valueField: 'value',
2020
- },
2021
- },
2062
+ name: 'animationEasing',
2063
+ title: '@dashboard:widgets.line-chart.animation-easing',
2064
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2065
+ schema: {
2066
+ defaultValue: 'cubic-out',
2067
+ dataType: 'string',
2068
+ interface: {
2069
+ name: 'animationEasing',
2070
+ path: 'options.animationEasing',
2071
+ type: AXPWidgetsCatalog.select,
2072
+ options: {
2073
+ dataSource: [
2074
+ { value: 'linear', text: 'Linear' },
2075
+ { value: 'ease', text: 'Ease' },
2076
+ { value: 'ease-in', text: 'Ease In' },
2077
+ { value: 'ease-out', text: 'Ease Out' },
2078
+ { value: 'ease-in-out', text: 'Ease In Out' },
2079
+ { value: 'cubic', text: 'Cubic' },
2080
+ { value: 'cubic-in', text: 'Cubic In' },
2081
+ { value: 'cubic-out', text: 'Cubic Out' },
2082
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
2083
+ ],
2084
+ textField: 'text',
2085
+ valueField: 'value',
2086
+ },
2022
2087
  },
2023
- visible: true,
2088
+ },
2089
+ visible: true,
2024
2090
  },
2025
2091
  {
2026
- name: 'animationDuration',
2027
- title: '@dashboard:widgets.line-chart.animation-duration',
2028
- group: AXP_APPEARANCE_PROPERTY_GROUP,
2029
- schema: {
2030
- defaultValue: 800,
2031
- dataType: 'number',
2032
- interface: {
2033
- name: 'animationDuration',
2034
- path: 'options.animationDuration',
2035
- type: AXPWidgetsCatalog.number,
2036
- options: {
2037
- placeholder: '0-2000',
2038
- minValue: 0,
2039
- maxValue: 2000,
2040
- },
2041
- },
2092
+ name: 'animationDuration',
2093
+ title: '@dashboard:widgets.line-chart.animation-duration',
2094
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2095
+ schema: {
2096
+ defaultValue: 800,
2097
+ dataType: 'number',
2098
+ interface: {
2099
+ name: 'animationDuration',
2100
+ path: 'options.animationDuration',
2101
+ type: AXPWidgetsCatalog.number,
2102
+ options: {
2103
+ placeholder: '0-2000',
2104
+ minValue: 0,
2105
+ maxValue: 2000,
2106
+ },
2042
2107
  },
2043
- visible: true,
2108
+ },
2109
+ visible: true,
2044
2110
  },
2111
+ */
2045
2112
  ],
2046
2113
  components: {
2047
2114
  view: {
@@ -2054,8 +2121,8 @@ const AXPLineChartWidget = {
2054
2121
  height: 4,
2055
2122
  minWidth: 2,
2056
2123
  minHeight: 2,
2057
- maxWidth: 4,
2058
- maxHeight: 5,
2124
+ maxWidth: 6,
2125
+ maxHeight: 6,
2059
2126
  },
2060
2127
  },
2061
2128
  };
@@ -3285,7 +3352,7 @@ class AXPWeatherWidgetViewComponent extends AXPValueWidgetComponent {
3285
3352
  provide: AXPWeatherApiAbstract,
3286
3353
  useClass: AXPWeatherApiService,
3287
3354
  },
3288
- ], viewQueries: [{ propertyName: "containerEl", first: true, predicate: ["containerElement"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() | translate: { scope: 'dashboard' } | async }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.retry' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">\n {{ getCurrentCondition() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{\n getTemperatureUnit() | translate: { scope: 'dashboard' } | async\n }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.humidity' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.wind' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">\n {{ getWindSpeed() }} {{ getWindSpeedUnit() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span class=\"ax-px-1\">{{ 'weather.forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </h3>\n </div>\n <!-- Loading indicator for forecast -->\n <!-- @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading-forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n } -->\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">\n {{ getDayName(parseDate(day.date)) | translate: { scope: 'dashboard' } | async }}\n </div>\n <div\n class=\"axp-weather-forecast-icon\"\n [title]=\"getConditionName(day.condition) | translate: { scope: 'dashboard' } | async\"\n >\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>{{ 'weather.last-updated' | translate: { scope: 'dashboard' } | async }}: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n [title]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.refresh' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>{{ 'weather.no-data' | translate: { scope: 'dashboard' } | async }}</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.load-data' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column;justify-content:space-between}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;padding-inline:.25rem;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-bottom:.5rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:90px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.775rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem;padding-inline:.25rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: HttpClientModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2$3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3355
+ ], viewQueries: [{ propertyName: "containerEl", first: true, predicate: ["containerElement"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() | translate: { scope: 'dashboard' } | async }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.retry' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">\n {{ getCurrentCondition() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{\n getTemperatureUnit() | translate: { scope: 'dashboard' } | async\n }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.humidity' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.wind' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">\n {{ getWindSpeed() }} {{ getWindSpeedUnit() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span class=\"ax-px-1\">{{ 'weather.forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </h3>\n </div>\n <!-- Loading indicator for forecast -->\n <!-- @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading-forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n } -->\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">\n {{ getDayName(parseDate(day.date)) | translate: { scope: 'dashboard' } | async }}\n </div>\n <div\n class=\"axp-weather-forecast-icon\"\n [title]=\"getConditionName(day.condition) | translate: { scope: 'dashboard' } | async\"\n >\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>{{ 'weather.last-updated' | translate: { scope: 'dashboard' } | async }}: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n [title]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.refresh' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>{{ 'weather.no-data' | translate: { scope: 'dashboard' } | async }}</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.load-data' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column;justify-content:space-between}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;padding-inline:.25rem;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-bottom:.5rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:90px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.775rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem;padding-inline:.25rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: HttpClientModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2$3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3289
3356
  }
3290
3357
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPWeatherWidgetViewComponent, decorators: [{
3291
3358
  type: Component,
@@ -3294,7 +3361,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
3294
3361
  provide: AXPWeatherApiAbstract,
3295
3362
  useClass: AXPWeatherApiService,
3296
3363
  },
3297
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() | translate: { scope: 'dashboard' } | async }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.retry' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">\n {{ getCurrentCondition() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{\n getTemperatureUnit() | translate: { scope: 'dashboard' } | async\n }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.humidity' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.wind' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">\n {{ getWindSpeed() }} {{ getWindSpeedUnit() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span class=\"ax-px-1\">{{ 'weather.forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </h3>\n </div>\n <!-- Loading indicator for forecast -->\n <!-- @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading-forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n } -->\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">\n {{ getDayName(parseDate(day.date)) | translate: { scope: 'dashboard' } | async }}\n </div>\n <div\n class=\"axp-weather-forecast-icon\"\n [title]=\"getConditionName(day.condition) | translate: { scope: 'dashboard' } | async\"\n >\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>{{ 'weather.last-updated' | translate: { scope: 'dashboard' } | async }}: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n [title]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.refresh' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>{{ 'weather.no-data' | translate: { scope: 'dashboard' } | async }}</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.load-data' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column;justify-content:space-between}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;padding-inline:.25rem;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-bottom:.5rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:90px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.775rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem;padding-inline:.25rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"] }]
3364
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() | translate: { scope: 'dashboard' } | async }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.retry' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">\n {{ getCurrentCondition() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{\n getTemperatureUnit() | translate: { scope: 'dashboard' } | async\n }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.humidity' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.wind' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">\n {{ getWindSpeed() }} {{ getWindSpeedUnit() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span class=\"ax-px-1\">{{ 'weather.forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </h3>\n </div>\n <!-- Loading indicator for forecast -->\n <!-- @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading-forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n } -->\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">\n {{ getDayName(parseDate(day.date)) | translate: { scope: 'dashboard' } | async }}\n </div>\n <div\n class=\"axp-weather-forecast-icon\"\n [title]=\"getConditionName(day.condition) | translate: { scope: 'dashboard' } | async\"\n >\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>{{ 'weather.last-updated' | translate: { scope: 'dashboard' } | async }}: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n [title]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.refresh' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>{{ 'weather.no-data' | translate: { scope: 'dashboard' } | async }}</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.load-data' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column;justify-content:space-between}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;padding-inline:.25rem;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-bottom:.5rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:90px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.775rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem;padding-inline:.25rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"] }]
3298
3365
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
3299
3366
 
3300
3367
  var weatherWidget_component = /*#__PURE__*/Object.freeze({
@@ -3949,7 +4016,6 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
3949
4016
  constructor() {
3950
4017
  super(...arguments);
3951
4018
  this.scope = RootConfig.config.i18n;
3952
- this.isAdmin = false;
3953
4019
  this.roleService = inject(AXMOrganizationManagementRoleEntityService);
3954
4020
  this.sessionService = inject(AXPSessionService);
3955
4021
  this.title = model('');
@@ -3957,6 +4023,7 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
3957
4023
  this.selectedRoleIds = model([]);
3958
4024
  this.isDisabled = model(false);
3959
4025
  this.isLocked = model(false);
4026
+ this.isAdmin = model(false);
3960
4027
  this.roles = [];
3961
4028
  }
3962
4029
  get isValid() {
@@ -3966,14 +4033,20 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
3966
4033
  // Set initial values from input data
3967
4034
  this.title.set(this.data?.title || '');
3968
4035
  this.description.set(this.data?.description || '');
3969
- this.selectedRoleIds.set(this.data?.roleIds || []);
3970
4036
  this.isDisabled.set(this.data?.isDeleted || false);
3971
4037
  this.isLocked.set(this.data?.locked || false);
4038
+ this.isAdmin.set(this.data?.isAdmin || false);
3972
4039
  // Load roles if admin
3973
- if (this.isAdmin) {
4040
+ if (this.isAdmin()) {
3974
4041
  try {
3975
4042
  const result = await this.roleService.query({ skip: 0, take: 100 });
3976
- this.roles = result.items || [];
4043
+ if (result.items && result.items.length > 0) {
4044
+ this.roles = result.items.map((i) => ({
4045
+ id: i.id,
4046
+ title: i.title,
4047
+ }));
4048
+ }
4049
+ this.selectedRoleIds.set(this.roles.filter((i) => this.data?.roleIds?.includes(i.id)).map((i) => i.id));
3977
4050
  }
3978
4051
  catch (error) {
3979
4052
  console.error('Error loading roles:', error);
@@ -3985,10 +4058,10 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
3985
4058
  this.close({
3986
4059
  title: this.title()?.trim(),
3987
4060
  description: this.description()?.trim(),
3988
- roleIds: this.isAdmin ? this.selectedRoleIds() : undefined,
3989
- isDeleted: this.isAdmin ? this.isDisabled() : undefined,
3990
- locked: this.isAdmin ? this.isLocked() : undefined,
3991
- scope: this.isAdmin ? 'T' : 'U',
4061
+ roleIds: this.isAdmin() ? this.selectedRoleIds() : undefined,
4062
+ isDeleted: this.isAdmin() ? this.isDisabled() : undefined,
4063
+ locked: this.isAdmin() ? this.isLocked() : undefined,
4064
+ scope: this.isAdmin() ? 'T' : 'U',
3992
4065
  createdBy: this.sessionService.user?.id,
3993
4066
  createdAt: new Date(),
3994
4067
  updatedBy: this.sessionService.user?.id,
@@ -3997,7 +4070,7 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
3997
4070
  });
3998
4071
  }
3999
4072
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMAddDashboardPopup, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4000
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXMAddDashboardPopup, isStandalone: true, selector: "ng-component", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, selectedRoleIds: { classPropertyName: "selectedRoleIds", publicName: "selectedRoleIds", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null }, isLocked: { classPropertyName: "isLocked", publicName: "isLocked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { title: "titleChange", description: "descriptionChange", selectedRoleIds: "selectedRoleIdsChange", isDisabled: "isDisabledChange", isLocked: "isLockedChange" }, usesInheritance: true, ngImport: i0, template: `
4073
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXMAddDashboardPopup, isStandalone: true, selector: "ng-component", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, selectedRoleIds: { classPropertyName: "selectedRoleIds", publicName: "selectedRoleIds", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null }, isLocked: { classPropertyName: "isLocked", publicName: "isLocked", isSignal: true, isRequired: false, transformFunction: null }, isAdmin: { classPropertyName: "isAdmin", publicName: "isAdmin", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { title: "titleChange", description: "descriptionChange", selectedRoleIds: "selectedRoleIdsChange", isDisabled: "isDisabledChange", isLocked: "isLockedChange", isAdmin: "isAdminChange" }, usesInheritance: true, ngImport: i0, template: `
4001
4074
  <div class="ax-card-body ax-p-4">
4002
4075
  <div class="ax-flex ax-flex-col ax-gap-2 ax-pb-4">
4003
4076
  <p class="ax-font-semibold">{{ 'title' | translate | async }}</p>
@@ -4009,7 +4082,7 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
4009
4082
  </ax-text-box>
4010
4083
  </div>
4011
4084
 
4012
- @if (isAdmin) {
4085
+ @if (isAdmin()) {
4013
4086
  <div class="ax-flex ax-flex-col ax-gap-2 ax-mt-4">
4014
4087
  <p class="ax-font-semibold">{{ 'roles' | translate: { scope } | async }}</p>
4015
4088
  <ax-select-box
@@ -4070,7 +4143,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
4070
4143
  </ax-text-box>
4071
4144
  </div>
4072
4145
 
4073
- @if (isAdmin) {
4146
+ @if (isAdmin()) {
4074
4147
  <div class="ax-flex ax-flex-col ax-gap-2 ax-mt-4">
4075
4148
  <p class="ax-font-semibold">{{ 'roles' | translate: { scope } | async }}</p>
4076
4149
  <ax-select-box
@@ -4204,7 +4277,7 @@ class AXMDashboardPopupService {
4204
4277
  draggable: true,
4205
4278
  hasBackdrop: true,
4206
4279
  title: await this.translateService.translateAsync('dashboard-info', { scope: 'dashboard' }),
4207
- data: dashboardData,
4280
+ data: { data: dashboardData },
4208
4281
  });
4209
4282
  if (!result.data) {
4210
4283
  return;
@@ -4221,7 +4294,7 @@ class AXMDashboardPopupService {
4221
4294
  size: 'sm',
4222
4295
  draggable: true,
4223
4296
  hasBackdrop: true,
4224
- title: 'Widget Configuration',
4297
+ title: await this.translateService.translateAsync('widget-configuration', { scope: 'dashboard' }),
4225
4298
  data: { widget },
4226
4299
  });
4227
4300
  if (!result.data) {
@@ -4241,139 +4314,115 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
4241
4314
  args: [{ providedIn: 'root' }]
4242
4315
  }] });
4243
4316
 
4317
+ // Helper functions
4318
+ const createInitialState = () => ({
4319
+ dashboards: [],
4320
+ allDashboards: [],
4321
+ currentDashboardId: null,
4322
+ isAdmin: false,
4323
+ dashboardsOption: {
4324
+ float: false,
4325
+ cellHeight: 75,
4326
+ gap: 5,
4327
+ minRow: 9,
4328
+ column: 12,
4329
+ responsiveLayout: [
4330
+ { column: 12, width: 2048 },
4331
+ { column: 6, width: 768 },
4332
+ { column: 1, width: 480 },
4333
+ ],
4334
+ },
4335
+ isLoading: false,
4336
+ });
4337
+ const modelToDashboardLayout = (model) => ({
4338
+ id: model.id || '',
4339
+ title: model.title,
4340
+ description: model.description,
4341
+ widgets: model.widgets || [],
4342
+ roleIds: model.roleIds,
4343
+ isDeleted: model.isDeleted,
4344
+ locked: model.locked,
4345
+ createdAt: model.createdAt,
4346
+ updatedAt: model.updatedAt,
4347
+ createdBy: model.createdBy,
4348
+ updatedBy: model.updatedBy,
4349
+ scope: model.scope,
4350
+ });
4351
+ const dashboardLayoutToModel = (layout) => ({
4352
+ id: layout.id,
4353
+ name: layout.title,
4354
+ title: layout.title,
4355
+ description: layout.description || '',
4356
+ widgets: layout.widgets,
4357
+ roleIds: layout.roleIds,
4358
+ isDeleted: layout.isDeleted,
4359
+ locked: layout.locked,
4360
+ createdAt: layout.createdAt,
4361
+ updatedAt: layout.updatedAt,
4362
+ createdBy: layout.createdBy,
4363
+ updatedBy: layout.updatedBy,
4364
+ scope: layout.scope,
4365
+ });
4244
4366
  // Create the SignalStore
4245
4367
  const AXMDashboardStore = signalStore({ providedIn: 'root' },
4246
4368
  // Initial State Definition
4247
- withState(() => {
4248
- // Define initial empty state
4249
- const state = {
4250
- dashboards: [],
4251
- allDashboards: [],
4252
- currentDashboardId: null,
4253
- isAdmin: false,
4254
- dashboardsOption: {
4255
- float: false,
4256
- cellHeight: 75,
4257
- gap: 5,
4258
- minRow: 9,
4259
- column: 12,
4260
- responsiveLayout: [
4261
- { column: 12, width: 2048 },
4262
- { column: 6, width: 768 },
4263
- { column: 1, width: 480 },
4264
- ],
4265
- },
4266
- isLoading: false,
4267
- };
4268
- return state;
4269
- }),
4369
+ withState(() => createInitialState()),
4270
4370
  // Computed Properties
4271
4371
  withComputed((state, sessionService = inject(AXPSessionService), layoutThemeService = inject(AXPLayoutThemeService)) => ({
4272
- currentDashboard: computed(() => {
4273
- return state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId()) || null;
4274
- }),
4275
- isAdmin: computed(() => {
4276
- return state.isAdmin();
4277
- }),
4278
- allDashboards: computed(() => {
4279
- return state.allDashboards();
4280
- }),
4281
- dashboardsOption: computed(() => {
4372
+ selectedDashboard: computed(() => state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId()) || null),
4373
+ isUserAdmin: computed(() => state.isAdmin()),
4374
+ availableDashboards: computed(() => state.allDashboards()),
4375
+ currentLayoutOptions: computed(() => {
4282
4376
  const currentDashboard = state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId());
4283
4377
  const baseOptions = state.dashboardsOption();
4284
- // If no current dashboard, return base options
4285
- if (!currentDashboard) {
4378
+ if (!currentDashboard)
4286
4379
  return baseOptions;
4287
- }
4288
- // Always disable drag and resize on mobile devices
4289
4380
  if (!layoutThemeService.isDesktopDevice()) {
4290
- return {
4291
- ...baseOptions,
4292
- disableDrag: true,
4293
- disableResize: true,
4294
- };
4381
+ return { ...baseOptions, disableDrag: true, disableResize: true };
4295
4382
  }
4296
- // If the base options already have explicit disableDrag and disableResize values,
4297
- // preserve those values (these were likely set by toggleLockDashboard)
4298
4383
  if (baseOptions.disableDrag !== undefined && baseOptions.disableResize !== undefined) {
4299
4384
  return baseOptions;
4300
4385
  }
4301
- // Check if dashboard is locked - locked dashboards always have drag and resize disabled
4302
4386
  if (currentDashboard.locked === true) {
4303
- return {
4304
- ...baseOptions,
4305
- disableDrag: true,
4306
- disableResize: true,
4307
- };
4387
+ return { ...baseOptions, disableDrag: true, disableResize: true };
4308
4388
  }
4309
- // If admin, no restrictions unless it's locked (which is checked above)
4310
- if (state.isAdmin()) {
4389
+ if (state.isAdmin())
4311
4390
  return baseOptions;
4312
- }
4313
- // Get user role
4314
4391
  const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4315
- // Check if user has role in dashboard
4316
4392
  const hasRoleIds = currentDashboard.roleIds && Array.isArray(currentDashboard.roleIds) && currentDashboard.roleIds.length > 0;
4317
4393
  const hasUserRole = userRole && hasRoleIds && currentDashboard.roleIds?.includes(userRole);
4318
- // If user is not admin, has role in dashboard, and dashboard has scope 'T', disable drag and resize
4319
4394
  if (!state.isAdmin() && hasUserRole && currentDashboard.scope === 'T') {
4320
- return {
4321
- ...baseOptions,
4322
- disableDrag: true,
4323
- disableResize: true,
4324
- };
4395
+ return { ...baseOptions, disableDrag: true, disableResize: true };
4325
4396
  }
4326
- // Otherwise, return base options
4327
4397
  return baseOptions;
4328
4398
  }),
4329
- canConfigureWidget: computed(() => {
4330
- return (widget) => {
4331
- const currentDashboard = state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId());
4332
- if (!currentDashboard)
4333
- return true;
4334
- // If admin, always allow configuration
4335
- if (state.isAdmin())
4336
- return widget.node?.options?.['hasConfiguration'] ?? true;
4337
- // If dashboard is locked, no configuration allowed
4338
- if (currentDashboard.locked === true) {
4339
- return false;
4340
- }
4341
- // Get user role
4342
- const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4343
- // Check if user has role in dashboard
4344
- const hasRoleIds = currentDashboard.roleIds && Array.isArray(currentDashboard.roleIds) && currentDashboard.roleIds.length > 0;
4345
- const hasUserRole = userRole && hasRoleIds && currentDashboard.roleIds?.includes(userRole);
4346
- // If user is not admin, has role in dashboard, and dashboard has scope 'T', disable configuration
4347
- if (hasUserRole && currentDashboard.scope === 'T') {
4348
- return false;
4349
- }
4350
- // Otherwise, use the widget's configuration value or default to true
4399
+ canConfigureWidget: computed(() => (widget) => {
4400
+ const currentDashboard = state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId());
4401
+ if (!currentDashboard)
4402
+ return true;
4403
+ if (state.isAdmin())
4351
4404
  return widget.node?.options?.['hasConfiguration'] ?? true;
4352
- };
4405
+ if (currentDashboard.locked === true)
4406
+ return false;
4407
+ const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4408
+ const hasRoleIds = currentDashboard.roleIds && Array.isArray(currentDashboard.roleIds) && currentDashboard.roleIds.length > 0;
4409
+ const hasUserRole = userRole && hasRoleIds && currentDashboard.roleIds?.includes(userRole);
4410
+ if (hasUserRole && currentDashboard.scope === 'T')
4411
+ return false;
4412
+ return widget.node?.options?.['hasConfiguration'] ?? true;
4353
4413
  }),
4354
- isWidgetLocked: computed(() => {
4355
- return (widget) => {
4356
- const currentDashboard = state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId());
4357
- if (!currentDashboard)
4358
- return false;
4359
- // If dashboard is locked, widget is locked
4360
- if (currentDashboard.locked === true) {
4361
- return true;
4362
- }
4363
- // If admin, widget is not locked
4364
- if (state.isAdmin())
4365
- return false;
4366
- // Get user role
4367
- const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4368
- // Check if user has role in dashboard
4369
- const hasRoleIds = currentDashboard.roleIds && Array.isArray(currentDashboard.roleIds) && currentDashboard.roleIds.length > 0;
4370
- const hasUserRole = userRole && hasRoleIds && currentDashboard.roleIds?.includes(userRole);
4371
- // If user is not admin, has role in dashboard, and dashboard has scope 'T', widget is locked
4372
- if (hasUserRole && currentDashboard.scope === 'T') {
4373
- return true;
4374
- }
4414
+ isWidgetLocked: computed(() => (widget) => {
4415
+ const currentDashboard = state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId());
4416
+ if (!currentDashboard)
4375
4417
  return false;
4376
- };
4418
+ if (currentDashboard.locked === true)
4419
+ return true;
4420
+ if (state.isAdmin())
4421
+ return false;
4422
+ const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4423
+ const hasRoleIds = currentDashboard.roleIds && Array.isArray(currentDashboard.roleIds) && currentDashboard.roleIds.length > 0;
4424
+ const hasUserRole = userRole && hasRoleIds && currentDashboard.roleIds?.includes(userRole);
4425
+ return hasUserRole && currentDashboard.scope === 'T';
4377
4426
  }),
4378
4427
  })),
4379
4428
  // Methods for State Management
@@ -4386,126 +4435,112 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4386
4435
  async function loadDashboards() {
4387
4436
  try {
4388
4437
  patchState(store, { isLoading: true });
4389
- // Get dashboards from service using query method
4390
4438
  const result = await dashboardService.query({ skip: 0, take: 100 });
4391
4439
  const dashboardModels = result.items || [];
4392
- // Convert dashboard models to AXPDashboardLayout
4393
4440
  const dashboards = dashboardModels.map(modelToDashboardLayout);
4394
- // Get current dashboard from settings
4395
4441
  const currentDashboardId = await settingService
4396
4442
  .scope(AXPPlatformScope.User)
4397
4443
  .get(AXPHomeDashboardSetting.CurrentDashboard);
4398
4444
  let newCurrentDashboardId = null;
4399
4445
  if (dashboards.length > 0) {
4400
- // Check if currentDashboardId exists and is valid
4401
4446
  const dashboardExists = currentDashboardId && dashboards.some((d) => d.id === currentDashboardId);
4402
- if (dashboardExists) {
4403
- newCurrentDashboardId = currentDashboardId;
4404
- }
4405
- else {
4406
- // If current dashboard is not valid or not set, use the first one
4407
- newCurrentDashboardId = dashboards[0].id;
4408
- // Save to user settings
4447
+ newCurrentDashboardId = dashboardExists ? currentDashboardId : dashboards[0].id;
4448
+ if (!dashboardExists) {
4409
4449
  settingService
4410
4450
  .scope(AXPPlatformScope.User)
4411
4451
  .set(AXPHomeDashboardSetting.CurrentDashboard, newCurrentDashboardId);
4412
4452
  }
4413
4453
  }
4414
- // First, update the state with all dashboards
4415
4454
  patchState(store, {
4416
4455
  allDashboards: dashboards,
4417
- dashboards: dashboards, // Initially set all dashboards
4456
+ dashboards: dashboards,
4418
4457
  isLoading: false,
4419
4458
  currentDashboardId: newCurrentDashboardId,
4420
4459
  });
4421
- // After state is updated, apply filtering if needed
4422
- if (store.isAdmin() !== undefined) {
4423
- // We need to use the method from the return object, so we'll call it later
4424
- }
4425
4460
  }
4426
4461
  catch (error) {
4427
4462
  console.error('Error loading dashboards:', error);
4428
4463
  patchState(store, { isLoading: false });
4429
4464
  }
4430
4465
  }
4431
- // Convert entity model to dashboard layout
4432
- function modelToDashboardLayout(model) {
4433
- return {
4434
- id: model.id || '',
4435
- title: model.title,
4436
- description: model.description,
4437
- widgets: model.widgets || [],
4438
- roleIds: model.roleIds,
4439
- isDeleted: model.isDeleted,
4440
- locked: model.locked,
4441
- createdAt: model.createdAt,
4442
- updatedAt: model.updatedAt,
4443
- createdBy: model.createdBy,
4444
- updatedBy: model.updatedBy,
4445
- scope: model.scope,
4446
- };
4447
- }
4448
- // Convert dashboard layout to entity model
4449
- function dashboardLayoutToModel(layout) {
4450
- return {
4451
- id: layout.id,
4452
- name: layout.title,
4453
- title: layout.title,
4454
- description: layout.description || '',
4455
- widgets: layout.widgets,
4456
- roleIds: layout.roleIds,
4457
- isDeleted: layout.isDeleted,
4458
- locked: layout.locked,
4459
- createdAt: layout.createdAt,
4460
- updatedAt: layout.updatedAt,
4461
- createdBy: layout.createdBy,
4462
- updatedBy: layout.updatedBy,
4463
- scope: layout.scope,
4464
- };
4465
- }
4466
4466
  return {
4467
- // Set current dashboard
4468
4467
  setCurrentDashboard(dashboardId) {
4469
4468
  patchState(store, { currentDashboardId: dashboardId });
4470
4469
  settingService.scope(AXPPlatformScope.User).set(AXPHomeDashboardSetting.CurrentDashboard, dashboardId);
4471
4470
  },
4472
- // Add a new dashboard
4473
4471
  async addDashboard() {
4474
4472
  try {
4475
- const newDashboard = await dashboardPopup.generateDashboardLayout({}, store.isAdmin());
4473
+ const newDashboard = await dashboardPopup.generateDashboardLayout({}, store.isUserAdmin());
4476
4474
  if (!newDashboard)
4477
4475
  return;
4478
- // Add creation and update metadata
4479
4476
  const userId = sessionService.user?.id;
4480
4477
  const now = new Date();
4481
- newDashboard.createdBy = userId;
4482
- newDashboard.createdAt = now;
4483
- newDashboard.updatedBy = userId;
4484
- newDashboard.updatedAt = now;
4485
- newDashboard.scope = store.isAdmin() ? 'T' : 'U';
4486
- // Create dashboard model and save to service
4487
- const dashboardModel = dashboardLayoutToModel(newDashboard);
4478
+ const dashboardWithMetadata = {
4479
+ ...newDashboard,
4480
+ createdBy: userId,
4481
+ createdAt: now,
4482
+ updatedBy: userId,
4483
+ updatedAt: now,
4484
+ scope: store.isUserAdmin() ? 'T' : 'U',
4485
+ widgets: [],
4486
+ };
4487
+ const dashboardModel = dashboardLayoutToModel(dashboardWithMetadata);
4488
4488
  const createdDashboardId = await dashboardService.insertOne(dashboardModel);
4489
- newDashboard.id = createdDashboardId;
4490
- newDashboard.widgets = [];
4491
- // Update both allDashboards and dashboards states
4492
- const updatedAllDashboards = [...store.allDashboards(), newDashboard];
4493
- const updatedDashboards = [...store.dashboards(), newDashboard];
4489
+ dashboardWithMetadata.id = createdDashboardId;
4490
+ const updatedAllDashboards = [...store.availableDashboards(), dashboardWithMetadata];
4491
+ const updatedDashboards = [...store.dashboards(), dashboardWithMetadata];
4494
4492
  patchState(store, {
4495
4493
  allDashboards: updatedAllDashboards,
4496
4494
  dashboards: updatedDashboards,
4497
- currentDashboardId: newDashboard.id,
4495
+ currentDashboardId: dashboardWithMetadata.id,
4498
4496
  });
4499
- // Save current dashboard to settings
4500
- settingService.scope(AXPPlatformScope.User).set(AXPHomeDashboardSetting.CurrentDashboard, newDashboard.id);
4497
+ settingService
4498
+ .scope(AXPPlatformScope.User)
4499
+ .set(AXPHomeDashboardSetting.CurrentDashboard, dashboardWithMetadata.id);
4501
4500
  }
4502
4501
  catch (error) {
4503
4502
  console.error('Error adding dashboard:', error);
4504
4503
  }
4505
4504
  },
4506
- // Add a widget to the current dashboard
4505
+ async editDashboard() {
4506
+ const currentDashboard = store.selectedDashboard();
4507
+ if (!currentDashboard)
4508
+ return;
4509
+ try {
4510
+ const editedDashboard = await dashboardPopup.generateDashboardLayout({
4511
+ title: currentDashboard.title,
4512
+ description: currentDashboard.description,
4513
+ roleIds: currentDashboard.roleIds,
4514
+ scope: currentDashboard.scope,
4515
+ }, store.isUserAdmin());
4516
+ if (!editedDashboard)
4517
+ return;
4518
+ const userId = sessionService.user?.id;
4519
+ const now = new Date();
4520
+ const updatedDashboard = {
4521
+ ...currentDashboard,
4522
+ ...editedDashboard,
4523
+ updatedBy: userId,
4524
+ updatedAt: now,
4525
+ };
4526
+ await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
4527
+ const updatedAllDashboards = store
4528
+ .availableDashboards()
4529
+ .map((d) => (d.id === updatedDashboard.id ? updatedDashboard : d));
4530
+ const updatedDashboards = store
4531
+ .dashboards()
4532
+ .map((d) => (d.id === updatedDashboard.id ? updatedDashboard : d));
4533
+ patchState(store, {
4534
+ allDashboards: updatedAllDashboards,
4535
+ dashboards: updatedDashboards,
4536
+ });
4537
+ }
4538
+ catch (error) {
4539
+ console.error('Error editing dashboard:', error);
4540
+ }
4541
+ },
4507
4542
  async addWidget() {
4508
- if (!store.currentDashboardId()) {
4543
+ if (!store.selectedDashboard()) {
4509
4544
  console.warn('No current dashboard selected');
4510
4545
  return;
4511
4546
  }
@@ -4513,57 +4548,43 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4513
4548
  const widgets = await widgetPickerService.showPicker({
4514
4549
  groups: [AXPWidgetGroupEnum.DashboardWidget],
4515
4550
  });
4516
- //remove meta from widgets //TODO TEMPORARY FIX
4517
- const filteredWidgets = widgets.map(({ __meta__, ...rest }) => rest);
4518
- if (filteredWidgets[0]?.type === 'sticky-note') {
4519
- if (!filteredWidgets[0].options) {
4520
- filteredWidgets[0].options = {};
4551
+ const filteredWidgets = widgets.map(({ __meta__, ...rest }) => {
4552
+ const widget = rest;
4553
+ if (widget.type === 'sticky-note' && !widget.options) {
4554
+ widget.options = { hasConfiguration: false };
4521
4555
  }
4522
- filteredWidgets[0].options.hasConfiguration = false;
4523
- }
4524
- filteredWidgets.forEach((widget) => {
4525
4556
  const randomId = AXPDataGenerator.uuid();
4526
- widget.name = widget?.type + '-' + randomId;
4527
- widget.path = widget?.type + '-' + randomId;
4528
- });
4529
- // Step 2: Convert the selected widgets into AXPDashboardWidgetData format
4530
- const convertedWidgets = filteredWidgets.map((widget) => {
4531
- const id = AXPDataGenerator.uuid();
4532
- return {
4533
- config: {
4534
- height: widget?.meta?.dimensions?.height ?? 2,
4535
- width: widget?.meta?.dimensions?.width ?? 2,
4536
- minHeight: widget?.meta?.dimensions?.minHeight,
4537
- minWidth: widget?.meta?.dimensions?.minWidth,
4538
- maxHeight: widget?.meta?.dimensions?.maxHeight,
4539
- maxWidth: widget?.meta?.dimensions?.maxWidth,
4540
- id,
4541
- },
4542
- node: { ...widget, name: id },
4543
- };
4544
- });
4545
- // Step 3: Update the dashboards
4546
- const updatedDashboards = store.dashboards().map((dashboard) => {
4547
- if (dashboard.id === store.currentDashboardId()) {
4548
- return {
4549
- ...dashboard,
4550
- widgets: [...dashboard.widgets, ...convertedWidgets],
4551
- };
4552
- }
4553
- return dashboard;
4557
+ widget.name = `${widget.type}-${randomId}`;
4558
+ widget.path = `${widget.type}-${randomId}`;
4559
+ return widget;
4554
4560
  });
4555
- // Step 4: Save the updated dashboard to the service
4556
- const currentDashboard = updatedDashboards.find((d) => d.id === store.currentDashboardId());
4557
- if (currentDashboard) {
4558
- await dashboardService.updateOne(currentDashboard.id, dashboardLayoutToModel(currentDashboard));
4559
- }
4561
+ const convertedWidgets = filteredWidgets.map((widget) => ({
4562
+ config: {
4563
+ height: widget?.meta?.dimensions?.height ?? 2,
4564
+ width: widget?.meta?.dimensions?.width ?? 2,
4565
+ minHeight: widget?.meta?.dimensions?.minHeight,
4566
+ minWidth: widget?.meta?.dimensions?.minWidth,
4567
+ maxHeight: widget?.meta?.dimensions?.maxHeight,
4568
+ maxWidth: widget?.meta?.dimensions?.maxWidth,
4569
+ id: AXPDataGenerator.uuid(),
4570
+ },
4571
+ node: { ...widget, name: widget.name },
4572
+ }));
4573
+ const currentDashboard = store.selectedDashboard();
4574
+ const updatedDashboard = {
4575
+ ...currentDashboard,
4576
+ widgets: [...currentDashboard.widgets, ...convertedWidgets],
4577
+ };
4578
+ await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
4579
+ const updatedDashboards = store
4580
+ .dashboards()
4581
+ .map((d) => (d.id === updatedDashboard.id ? updatedDashboard : d));
4560
4582
  patchState(store, { dashboards: updatedDashboards });
4561
4583
  }
4562
4584
  catch (error) {
4563
4585
  console.error('Error adding widget:', error);
4564
4586
  }
4565
4587
  },
4566
- // Remove a dashboard
4567
4588
  async removeDashboard(id) {
4568
4589
  if (!id) {
4569
4590
  console.warn('No dashboard ID provided for removal');
@@ -4572,17 +4593,13 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4572
4593
  try {
4573
4594
  const dialogResult = await dialogService.confirm(await translationService.translateAsync('workflow.warning'), await translationService.translateAsync('workflow.confirm-delete'), 'danger', 'horizontal');
4574
4595
  if (dialogResult.result) {
4575
- // Delete from service
4576
4596
  await dashboardService.deleteOne(id);
4577
- // Remove the dashboard from both state arrays
4578
- const updatedAllDashboards = store.allDashboards().filter((dashboard) => dashboard.id !== id);
4597
+ const updatedAllDashboards = store.availableDashboards().filter((dashboard) => dashboard.id !== id);
4579
4598
  const updatedDashboards = store.dashboards().filter((dashboard) => dashboard.id !== id);
4580
- // Update state and select a new current dashboard if needed
4581
4599
  let newCurrentDashboardId = store.currentDashboardId();
4582
4600
  if (id === store.currentDashboardId()) {
4583
4601
  newCurrentDashboardId =
4584
4602
  updatedDashboards.length > 0 ? updatedDashboards[updatedDashboards.length - 1].id : null;
4585
- // Save to settings if we changed the current dashboard
4586
4603
  if (newCurrentDashboardId) {
4587
4604
  settingService
4588
4605
  .scope(AXPPlatformScope.User)
@@ -4600,7 +4617,6 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4600
4617
  console.error('Error removing dashboard:', error);
4601
4618
  }
4602
4619
  },
4603
- // Remove a widget from a dashboard
4604
4620
  async removeWidget(dashboardId, widgetId) {
4605
4621
  const currentDashboard = store.dashboards().find((d) => d.id === dashboardId);
4606
4622
  if (!currentDashboard)
@@ -4609,92 +4625,56 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4609
4625
  ...currentDashboard,
4610
4626
  widgets: currentDashboard.widgets.filter((widget) => widget.config.id !== widgetId),
4611
4627
  };
4612
- // Save to service
4613
4628
  await dashboardService.updateOne(dashboardId, dashboardLayoutToModel(updatedDashboard));
4614
- // Update local state
4615
4629
  const updatedDashboards = store
4616
4630
  .dashboards()
4617
4631
  .map((dashboard) => (dashboard.id === dashboardId ? updatedDashboard : dashboard));
4618
4632
  patchState(store, { dashboards: updatedDashboards });
4619
4633
  },
4620
- // Handle configuration changes
4621
4634
  async handleConfigChange(dashboard) {
4622
- // Save to service
4623
4635
  await dashboardService.updateOne(dashboard.id, dashboardLayoutToModel(dashboard));
4624
- // Update local state
4625
4636
  const updatedDashboards = store.dashboards().map((d) => (d.id === dashboard.id ? dashboard : d));
4626
4637
  patchState(store, {
4627
4638
  dashboards: updatedDashboards,
4628
4639
  currentDashboardId: dashboard.id,
4629
4640
  });
4630
- // Save current dashboard to settings
4631
4641
  settingService.scope(AXPPlatformScope.User).set(AXPHomeDashboardSetting.CurrentDashboard, dashboard.id);
4632
4642
  },
4633
- // Handle grid layout changes
4634
4643
  async onGridChange(event) {
4635
- // Skip any changes on mobile devices
4636
- if (!layoutThemeService.isDesktopDevice()) {
4637
- return;
4638
- }
4639
- if (!store.currentDashboard()) {
4640
- console.warn('No current dashboard for grid change');
4644
+ if (!layoutThemeService.isDesktopDevice() || !store.selectedDashboard())
4641
4645
  return;
4642
- }
4643
- // Extract nodes from the event and remove the `element` property
4644
4646
  const nodes = event.nodes.map(({ element, ...rest }) => rest);
4645
- // Update the current dashboard
4646
- const currentDashboard = store.currentDashboard();
4647
+ const currentDashboard = store.selectedDashboard();
4647
4648
  const updatedWidgets = currentDashboard.widgets.map((widget) => {
4648
4649
  const updatedNode = nodes.find((node) => node.id === widget.config.id);
4649
- if (updatedNode) {
4650
- return {
4651
- ...widget,
4652
- config: updatedNode,
4653
- };
4654
- }
4655
- return widget;
4650
+ return updatedNode ? { ...widget, config: updatedNode } : widget;
4656
4651
  });
4657
4652
  const updatedDashboard = {
4658
4653
  ...currentDashboard,
4659
4654
  widgets: updatedWidgets,
4660
4655
  };
4661
- // Save to service
4662
4656
  await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
4663
- // Update the dashboards
4664
4657
  const updatedDashboards = store
4665
4658
  .dashboards()
4666
4659
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
4667
4660
  patchState(store, { dashboards: updatedDashboards });
4668
4661
  },
4669
- // Handle widget configuration
4670
4662
  async handlePopupConfiguration(widgetNode) {
4671
- if (!store.currentDashboard()) {
4672
- console.warn('No current dashboard selected');
4663
+ if (!store.selectedDashboard())
4673
4664
  return;
4674
- }
4675
4665
  try {
4676
4666
  const updatedNode = await dashboardPopup.handlePopupConfiguration(widgetNode);
4677
- if (!updatedNode) {
4667
+ if (!updatedNode)
4678
4668
  return;
4679
- }
4680
- // Update the current dashboard's widget with the new configuration
4681
- const currentDashboard = store.currentDashboard();
4682
- const updatedWidgets = currentDashboard.widgets.map((widget) => {
4683
- if (widget.node?.name === widgetNode.name && widget.node?.path === widgetNode.path) {
4684
- return {
4685
- ...widget,
4686
- node: updatedNode,
4687
- };
4688
- }
4689
- return widget;
4690
- });
4669
+ const currentDashboard = store.selectedDashboard();
4670
+ const updatedWidgets = currentDashboard.widgets.map((widget) => widget.node?.name === widgetNode.name && widget.node?.path === widgetNode.path
4671
+ ? { ...widget, node: updatedNode }
4672
+ : widget);
4691
4673
  const updatedDashboard = {
4692
4674
  ...currentDashboard,
4693
4675
  widgets: updatedWidgets,
4694
4676
  };
4695
- // Save to service
4696
4677
  await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
4697
- // Update the dashboards state
4698
4678
  const updatedDashboards = store
4699
4679
  .dashboards()
4700
4680
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
@@ -4704,74 +4684,47 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4704
4684
  console.error('Error handling widget configuration:', error);
4705
4685
  }
4706
4686
  },
4707
- // Handle widget value changes
4708
4687
  async handleValueChanged(widgetNode, data) {
4709
- if (!store.currentDashboard()) {
4710
- console.warn('No current dashboard selected');
4688
+ if (!store.selectedDashboard())
4711
4689
  return;
4712
- }
4713
4690
  try {
4714
- // Update the current dashboard's widget with the new value
4715
- const currentDashboard = store.currentDashboard();
4716
- const updatedWidgets = currentDashboard.widgets.map((widget) => {
4717
- if (widget.node && widget.node.name === widgetNode.name && widget.node.path === widgetNode.path) {
4718
- return {
4719
- ...widget,
4720
- node: {
4721
- ...widget.node,
4722
- defaultValue: data,
4723
- },
4724
- };
4725
- }
4726
- return widget;
4727
- });
4691
+ const currentDashboard = store.selectedDashboard();
4692
+ const updatedWidgets = currentDashboard.widgets.map((widget) => widget.node && widget.node.name === widgetNode.name && widget.node.path === widgetNode.path
4693
+ ? { ...widget, node: { ...widget.node, defaultValue: data } }
4694
+ : widget);
4728
4695
  const updatedDashboard = {
4729
4696
  ...currentDashboard,
4730
4697
  widgets: updatedWidgets,
4731
4698
  };
4732
- // Save to service
4733
4699
  await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
4734
- // Update the dashboards state
4735
4700
  const updatedDashboards = store
4736
4701
  .dashboards()
4737
4702
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
4738
- // patchState(store, { dashboards: updatedDashboards });
4703
+ patchState(store, { dashboards: updatedDashboards });
4739
4704
  }
4740
4705
  catch (error) {
4741
4706
  console.error('Error handling widget value change:', error);
4742
4707
  }
4743
4708
  },
4744
- // Handle widget options changes
4745
4709
  async handleOptionsChanged(widgetNode, data) {
4746
- if (!store.currentDashboard()) {
4747
- console.warn('No current dashboard selected');
4710
+ if (!store.selectedDashboard())
4748
4711
  return;
4749
- }
4750
4712
  try {
4751
- // Update the current dashboard's widget with the new options
4752
- const currentDashboard = store.currentDashboard();
4753
- const updatedWidgets = currentDashboard.widgets.map((widget) => {
4754
- if (widget.node && widget.node.name === widgetNode.name && widget.node.path === widgetNode.path) {
4755
- return {
4756
- ...widget,
4757
- node: {
4758
- ...widget.node,
4759
- options: {
4760
- ...(widget.node.options || {}),
4761
- ...data,
4762
- },
4763
- },
4764
- };
4713
+ const currentDashboard = store.selectedDashboard();
4714
+ const updatedWidgets = currentDashboard.widgets.map((widget) => widget.node && widget.node.name === widgetNode.name && widget.node.path === widgetNode.path
4715
+ ? {
4716
+ ...widget,
4717
+ node: {
4718
+ ...widget.node,
4719
+ options: { ...(widget.node.options || {}), ...data },
4720
+ },
4765
4721
  }
4766
- return widget;
4767
- });
4722
+ : widget);
4768
4723
  const updatedDashboard = {
4769
4724
  ...currentDashboard,
4770
4725
  widgets: updatedWidgets,
4771
4726
  };
4772
- // Save to service
4773
4727
  await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
4774
- // Update the dashboards state
4775
4728
  const updatedDashboards = store
4776
4729
  .dashboards()
4777
4730
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
@@ -4781,110 +4734,70 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4781
4734
  console.error('Error handling widget options change:', error);
4782
4735
  }
4783
4736
  },
4784
- // Handle setting admin state
4785
4737
  setIsAdmin(isAdmin) {
4786
4738
  patchState(store, { isAdmin });
4787
4739
  },
4788
- // Filter dashboards by scope
4789
4740
  filterDashboardsByScope(isAdmin) {
4790
- // Get all dashboards from the stored allDashboards array
4791
- const allDashboards = store.allDashboards();
4792
- // Get user ID and role from session service
4741
+ const allDashboards = store.availableDashboards();
4793
4742
  const userId = sessionService.user?.id;
4794
4743
  const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4795
4744
  if (!userId) {
4796
- // If no user ID, don't filter
4797
4745
  patchState(store, { dashboards: allDashboards });
4798
4746
  return;
4799
4747
  }
4800
- // Apply filtering based on user permissions
4801
- let filteredDashboards = allDashboards;
4802
- if (isAdmin) {
4803
- // Admin sees only tenant-level dashboards
4804
- filteredDashboards = allDashboards.filter((dashboard) => dashboard.scope === 'T');
4805
- }
4806
- else {
4807
- // Regular users see:
4808
- // 1. User-level dashboards they created
4809
- // 2. Tenant-level dashboards where their role is included AND isDeleted is false/undefined
4810
- filteredDashboards = allDashboards.filter((dashboard) => {
4811
- // Check if this is a user-level dashboard created by this user
4748
+ const filteredDashboards = isAdmin
4749
+ ? allDashboards.filter((dashboard) => dashboard.scope === 'T')
4750
+ : allDashboards.filter((dashboard) => {
4812
4751
  const isUserDashboard = dashboard.scope === 'U' && dashboard.createdBy === userId;
4813
- // Check if this is a tenant-level dashboard with user's role and is not deleted
4814
4752
  const hasRoleIds = dashboard.roleIds && Array.isArray(dashboard.roleIds) && dashboard.roleIds.length > 0;
4815
4753
  const isTenantDashboard = dashboard.scope === 'T';
4816
4754
  const hasUserRole = userRole && hasRoleIds && dashboard.roleIds?.includes(userRole);
4817
- const isNotDeleted = dashboard.isDeleted !== true; // Show if isDeleted is false or undefined
4755
+ const isNotDeleted = dashboard.isDeleted !== true;
4818
4756
  const isTenantDashboardWithRole = isTenantDashboard && hasUserRole && isNotDeleted;
4819
4757
  return isUserDashboard || isTenantDashboardWithRole;
4820
4758
  });
4821
- }
4822
- // Update dashboards state
4823
4759
  patchState(store, { dashboards: filteredDashboards });
4824
- // If current dashboard is not in filtered list, select the first one
4825
4760
  if (filteredDashboards.length > 0 && !filteredDashboards.some((d) => d.id === store.currentDashboardId())) {
4826
4761
  this.setCurrentDashboard(filteredDashboards[0].id);
4827
4762
  }
4828
4763
  },
4829
- // Toggle lock state for the current dashboard
4830
4764
  async toggleLockDashboard() {
4831
- const currentDashboard = store.currentDashboard();
4832
- if (!currentDashboard) {
4833
- console.warn('No current dashboard selected');
4765
+ const currentDashboard = store.selectedDashboard();
4766
+ if (!currentDashboard)
4834
4767
  return;
4835
- }
4836
4768
  try {
4837
- // Check permission to toggle lock
4838
- const isAdmin = store.isAdmin();
4769
+ const isAdmin = store.isUserAdmin();
4839
4770
  const userId = sessionService.user?.id;
4840
- // Determine if user can toggle lock based on the rules:
4841
- // 1. If isAdmin is false, user can only toggle their own user-level dashboards
4842
- // 2. If isAdmin is true, user can only toggle tenant-level dashboards
4843
4771
  const canToggle = (!isAdmin && currentDashboard.scope === 'U' && currentDashboard.createdBy === userId) ||
4844
4772
  (isAdmin && currentDashboard.scope === 'T');
4845
4773
  if (!canToggle) {
4846
4774
  console.warn('User does not have permission to toggle lock for this dashboard');
4847
4775
  return;
4848
4776
  }
4849
- // Toggle the locked state
4850
4777
  const newLockedState = !currentDashboard.locked;
4851
- // Create an updated dashboard with toggled lock state
4852
4778
  const updatedDashboard = {
4853
4779
  ...currentDashboard,
4854
4780
  locked: newLockedState,
4855
4781
  };
4856
- // Save to service
4857
4782
  await dashboardService.updateOne(updatedDashboard.id, dashboardLayoutToModel(updatedDashboard));
4858
- // Update the dashboards in store
4859
4783
  const updatedDashboards = store
4860
4784
  .dashboards()
4861
4785
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
4862
- // IMPORTANT: Get the base options BEFORE updating the dashboards state
4863
- // This ensures we're getting the current options without the lock state applied yet
4864
4786
  const baseOptions = { ...store.dashboardsOption() };
4865
- // First update the dashboards state
4866
- patchState(store, {
4867
- dashboards: updatedDashboards,
4868
- });
4869
- // Get a fresh reference to the updated options with drag/resize explicitly set
4870
- // This ensures the grid layout container gets a new object reference and responds immediately
4787
+ patchState(store, { dashboards: updatedDashboards });
4871
4788
  const updatedOptions = {
4872
4789
  ...baseOptions,
4873
4790
  disableDrag: newLockedState,
4874
4791
  disableResize: newLockedState,
4875
4792
  };
4876
- // Now update the options state separately to force a refresh of the grid layout
4877
- patchState(store, {
4878
- dashboardsOption: updatedOptions,
4879
- });
4793
+ patchState(store, { dashboardsOption: updatedOptions });
4880
4794
  }
4881
4795
  catch (error) {
4882
4796
  console.error('Error toggling dashboard lock state:', error);
4883
4797
  }
4884
4798
  },
4885
- // Check if dashboard is locked
4886
4799
  isDashboardLocked() {
4887
- const currentDashboard = store.currentDashboard();
4800
+ const currentDashboard = store.selectedDashboard();
4888
4801
  return currentDashboard?.locked === true;
4889
4802
  },
4890
4803
  };
@@ -4893,6 +4806,7 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4893
4806
  class AXMDashboardHomeComponent extends AXPBasePageComponent {
4894
4807
  constructor() {
4895
4808
  super(...arguments);
4809
+ // Dependencies
4896
4810
  this.rootConfig = RootConfig;
4897
4811
  this.activatedRoute = inject(ActivatedRoute);
4898
4812
  this.dialogService = inject(AXDialogService);
@@ -4900,25 +4814,20 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4900
4814
  this.router = inject(Router);
4901
4815
  this.store = inject(AXMDashboardStore);
4902
4816
  this.themeService = inject(AXPLayoutThemeService);
4903
- this.isEdited = signal(false);
4817
+ // Component State
4904
4818
  this.context = signal({});
4905
4819
  this.dashboardsLoaded = signal(false);
4906
- this.#dashboardsEffect = effect(() => {
4907
- const allDashboards = this.store.allDashboards();
4820
+ // Effects
4821
+ this.#initEffect = effect(() => {
4822
+ const allDashboards = this.store.availableDashboards();
4908
4823
  if (allDashboards.length > 0 && !this.dashboardsLoaded()) {
4909
4824
  this.dashboardsLoaded.set(true);
4910
4825
  this.applyDashboardFiltering();
4911
4826
  this.recompute();
4912
4827
  }
4913
4828
  });
4914
- this.#loadingEffect = effect(() => {
4915
- const isLoading = this.store.isLoading();
4916
- if (isLoading === false && this.dashboardsLoaded()) {
4917
- this.recompute;
4918
- setTimeout(() => this.recompute(), 0);
4919
- }
4920
- });
4921
4829
  }
4830
+ // Lifecycle Hooks
4922
4831
  async ngOnInit() {
4923
4832
  const childRoute = this.activatedRoute.firstChild || this.activatedRoute;
4924
4833
  childRoute.data.subscribe((data) => {
@@ -4926,13 +4835,11 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4926
4835
  this.store.setIsAdmin(isAdmin);
4927
4836
  });
4928
4837
  }
4838
+ // Effects
4839
+ #initEffect;
4840
+ // Private Methods
4929
4841
  applyDashboardFiltering() {
4930
- this.store.filterDashboardsByScope(this.store.isAdmin());
4931
- }
4932
- #dashboardsEffect;
4933
- #loadingEffect;
4934
- toggleEdit() {
4935
- this.isEdited.update((value) => !value);
4842
+ this.store.filterDashboardsByScope(this.store.isUserAdmin());
4936
4843
  }
4937
4844
  async confirmWidgetDelete(dashboardId, widgetId) {
4938
4845
  try {
@@ -4945,23 +4852,21 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4945
4852
  console.error('Error confirming widget deletion:', error);
4946
4853
  }
4947
4854
  }
4855
+ // Page Interface Implementation
4948
4856
  getPageTitle() {
4949
- return this.store.currentDashboard()?.title || 'Dashboard';
4857
+ return this.store.selectedDashboard()?.title || 'Dashboard';
4950
4858
  }
4951
4859
  async getPageDescription() {
4952
- return this.store.currentDashboard()?.description || '';
4860
+ return this.store.selectedDashboard()?.description || '';
4953
4861
  }
4954
4862
  getTitleActions() {
4955
- return [
4956
- ...this.store.dashboards().map((i) => ({
4957
- title: i.title,
4958
- command: { name: i.id, metadata: { isDashboard: true, dashboard: i } },
4959
- icon: i.id === this.store.currentDashboardId() ? 'fa-solid fa-check' : '',
4960
- })),
4961
- ];
4863
+ return this.store.dashboards().map((dashboard) => ({
4864
+ title: dashboard.title,
4865
+ command: { name: dashboard.id, metadata: { isDashboard: true, dashboard } },
4866
+ icon: dashboard.id === this.store.currentDashboardId() ? 'fa-solid fa-check' : '',
4867
+ }));
4962
4868
  }
4963
4869
  async getPrimaryMenuItems() {
4964
- const scope = this.rootConfig.config.i18n;
4965
4870
  return [
4966
4871
  {
4967
4872
  title: 't("add-item")',
@@ -4972,16 +4877,12 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4972
4877
  title: await this.translateService.translateAsync('dashboard', { scope: 'dashboard' }),
4973
4878
  icon: 'fa-light fa-gauge-high',
4974
4879
  break: true,
4975
- command: {
4976
- name: 'new-dashboard',
4977
- },
4880
+ command: { name: 'new-dashboard' },
4978
4881
  },
4979
4882
  {
4980
4883
  title: await this.translateService.translateAsync('widget', { scope: 'dashboard' }),
4981
4884
  icon: 'fa-light fa-window-restore',
4982
- command: {
4983
- name: 'new-widget',
4984
- },
4885
+ command: { name: 'new-widget' },
4985
4886
  disabled: this.store.dashboards().length < 1,
4986
4887
  },
4987
4888
  ],
@@ -4989,19 +4890,16 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4989
4890
  ];
4990
4891
  }
4991
4892
  async getSecondaryMenuItems() {
4992
- const scope = this.rootConfig.config.i18n;
4993
4893
  const items = [
4994
4894
  {
4995
- title: await this.translateService.translateAsync('delete'),
4996
- icon: 'fa-light fa-trash-can',
4997
- color: 'danger',
4895
+ title: await this.translateService.translateAsync('edit'),
4896
+ icon: 'fa-light fa-pen',
4897
+ color: 'primary',
4998
4898
  disabled: this.store.dashboards().length < 1,
4999
- command: {
5000
- name: 'delete',
5001
- },
4899
+ command: { name: 'edit' },
5002
4900
  },
5003
4901
  ];
5004
- if (!this.store.isAdmin() && this.themeService.isDesktopDevice()) {
4902
+ if (!this.store.isUserAdmin() && this.themeService.isDesktopDevice()) {
5005
4903
  items.push({
5006
4904
  title: await this.translateService.translateAsync(this.store.isDashboardLocked() ? 'unlock' : 'lock', {
5007
4905
  scope: 'dashboard',
@@ -5009,43 +4907,48 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
5009
4907
  icon: this.store.isDashboardLocked() ? 'fa-light fa-lock-open' : 'fa-light fa-lock',
5010
4908
  color: 'accent3',
5011
4909
  disabled: this.store.dashboards().length < 1,
5012
- command: {
5013
- name: 'toggle-lock',
5014
- },
4910
+ command: { name: 'toggle-lock' },
5015
4911
  });
5016
4912
  }
4913
+ items.push({
4914
+ title: await this.translateService.translateAsync('delete'),
4915
+ icon: 'fa-light fa-trash-can',
4916
+ color: 'danger',
4917
+ disabled: this.store.dashboards().length < 1,
4918
+ command: { name: 'delete' },
4919
+ });
5017
4920
  return items;
5018
4921
  }
5019
4922
  async execute(command) {
5020
4923
  if (command.metadata?.['isDashboard']) {
5021
4924
  this.store.handleConfigChange(command.metadata?.['dashboard']);
5022
4925
  this.recompute();
4926
+ return;
5023
4927
  }
5024
- else {
5025
- switch (command.name) {
5026
- case 'new-dashboard':
5027
- await this.store.addDashboard();
5028
- this.applyDashboardFiltering();
5029
- this.recompute();
5030
- break;
5031
- case 'new-widget':
5032
- await this.store.addWidget();
5033
- this.recompute();
5034
- break;
5035
- case 'delete':
5036
- await this.store.removeDashboard(this.store.currentDashboard()?.id);
5037
- this.applyDashboardFiltering();
5038
- this.recompute();
5039
- break;
5040
- case 'toggle-lock':
5041
- await this.store.toggleLockDashboard();
5042
- this.recompute();
5043
- // Add a short delay to ensure the grid layout updates properly
5044
- setTimeout(() => {
5045
- this.recompute();
5046
- }, 50);
5047
- break;
5048
- }
4928
+ switch (command.name) {
4929
+ case 'new-dashboard':
4930
+ await this.store.addDashboard();
4931
+ this.applyDashboardFiltering();
4932
+ this.recompute();
4933
+ break;
4934
+ case 'new-widget':
4935
+ await this.store.addWidget();
4936
+ this.recompute();
4937
+ break;
4938
+ case 'edit':
4939
+ await this.store.editDashboard();
4940
+ this.recompute();
4941
+ break;
4942
+ case 'delete':
4943
+ await this.store.removeDashboard(this.store.selectedDashboard()?.id);
4944
+ this.applyDashboardFiltering();
4945
+ this.recompute();
4946
+ break;
4947
+ case 'toggle-lock':
4948
+ await this.store.toggleLockDashboard();
4949
+ this.recompute();
4950
+ setTimeout(() => this.recompute(), 50);
4951
+ break;
5049
4952
  }
5050
4953
  }
5051
4954
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMDashboardHomeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
@@ -5056,7 +4959,7 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
5056
4959
  provide: AXPBasePage,
5057
4960
  useExisting: AXMDashboardHomeComponent,
5058
4961
  },
5059
- ], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.dashboardsOption()\" (onChange)=\"store.onGridChange($event)\">\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-dashboards', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ t('no-current-dashboard', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('select-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()?.widgets || store.currentDashboard()?.widgets.length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-widgets', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-widget', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else { @for(widget of store.currentDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.currentDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPLayoutBuilderModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXGridLayoutBuilderModule }, { kind: "component", type: i4$1.AXGridLayoutContainerComponent, selector: "ax-grid-layout-container", inputs: ["options", "isEmpty"], outputs: ["onAdded", "onRemoved", "onWidgetChange", "onChange", "onRender", "isEmptyChange"] }, { kind: "component", type: i4$1.AXGridLayoutWidgetComponent, selector: "ax-grid-layout-widget", inputs: ["options"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer, axp-page-header, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-container, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i2$3.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "component", type: AXMDashboardWidgetWrapperComponent, selector: "axm-dashboard-widget-wrapper", inputs: ["title", "hasConfiguration", "isLocked"], outputs: ["onDelete", "onConfiguration", "onValueChanged", "onOptionsChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4962
+ ], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n <!-- Loading State -->\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.currentLayoutOptions()\" (onChange)=\"store.onGridChange($event)\">\n <!-- No Dashboards State -->\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-dashboards', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n }\n <!-- No Selected Dashboard State -->\n @else if (!store.selectedDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ t('no-current-dashboard', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('select-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n }\n <!-- No Widgets State -->\n @else if (!store.selectedDashboard()?.widgets || store.selectedDashboard()?.widgets?.length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-widgets', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-widget', { scope: 'dashboard' }) | async }}</p>\n </div>\n }\n <!-- Widgets Grid -->\n @else { @for(widget of store.selectedDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.selectedDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPLayoutBuilderModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXGridLayoutBuilderModule }, { kind: "component", type: i4$1.AXGridLayoutContainerComponent, selector: "ax-grid-layout-container", inputs: ["options", "isEmpty"], outputs: ["onAdded", "onRemoved", "onWidgetChange", "onChange", "onRender", "isEmptyChange"] }, { kind: "component", type: i4$1.AXGridLayoutWidgetComponent, selector: "ax-grid-layout-widget", inputs: ["options"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer, axp-page-header, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-container, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i2$3.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "component", type: AXMDashboardWidgetWrapperComponent, selector: "axm-dashboard-widget-wrapper", inputs: ["title", "hasConfiguration", "isLocked"], outputs: ["onDelete", "onConfiguration", "onValueChanged", "onOptionsChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
5060
4963
  }
5061
4964
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMDashboardHomeComponent, decorators: [{
5062
4965
  type: Component,
@@ -5082,7 +4985,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
5082
4985
  provide: AXPBasePage,
5083
4986
  useExisting: AXMDashboardHomeComponent,
5084
4987
  },
5085
- ], template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.dashboardsOption()\" (onChange)=\"store.onGridChange($event)\">\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-dashboards', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ t('no-current-dashboard', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('select-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()?.widgets || store.currentDashboard()?.widgets.length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-widgets', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-widget', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else { @for(widget of store.currentDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.currentDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"] }]
4988
+ ], template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n <!-- Loading State -->\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.currentLayoutOptions()\" (onChange)=\"store.onGridChange($event)\">\n <!-- No Dashboards State -->\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-dashboards', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n }\n <!-- No Selected Dashboard State -->\n @else if (!store.selectedDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ t('no-current-dashboard', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('select-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n }\n <!-- No Widgets State -->\n @else if (!store.selectedDashboard()?.widgets || store.selectedDashboard()?.widgets?.length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-widgets', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-widget', { scope: 'dashboard' }) | async }}</p>\n </div>\n }\n <!-- Widgets Grid -->\n @else { @for(widget of store.selectedDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.selectedDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"] }]
5086
4989
  }] });
5087
4990
 
5088
4991
  var homeDashboard = /*#__PURE__*/Object.freeze({