@esfaenza/es-charts 15.2.1 → 15.2.3

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.
Files changed (29) hide show
  1. package/esm2020/lib/components/base/base-chart.component.mjs +4 -3
  2. package/esm2020/lib/components/specializations/es-area-chart.component.mjs +10 -12
  3. package/esm2020/lib/components/specializations/es-chart.component.mjs +10 -12
  4. package/esm2020/lib/components/specializations/es-line-chart.component.mjs +10 -12
  5. package/esm2020/lib/components/specializations/es-pie-chart.component.mjs +10 -12
  6. package/esm2020/lib/components/specializations/es-vertical-2d-chart.component.mjs +10 -12
  7. package/esm2020/lib/components/specializations/es-vertical-chart.component.mjs +10 -12
  8. package/esm2020/lib/components/specializations/es-vertical-stacked-chart.component.mjs +10 -12
  9. package/esm2020/lib/es-charts.module.mjs +6 -12
  10. package/esm2020/lib/models/EsChaartsModuleConfig.mjs +1 -1
  11. package/esm2020/lib/models/core/ChartDispatcher.mjs +4 -3
  12. package/esm2020/lib/models/core/ChartLoader.mjs +14 -1
  13. package/esm2020/lib/tokens.mjs +1 -5
  14. package/fesm2015/esfaenza-es-charts.mjs +1602 -1617
  15. package/fesm2015/esfaenza-es-charts.mjs.map +1 -1
  16. package/fesm2020/esfaenza-es-charts.mjs +1585 -1602
  17. package/fesm2020/esfaenza-es-charts.mjs.map +1 -1
  18. package/lib/components/base/base-chart.component.d.ts +2 -2
  19. package/lib/components/specializations/es-area-chart.component.d.ts +2 -1
  20. package/lib/components/specializations/es-chart.component.d.ts +2 -1
  21. package/lib/components/specializations/es-line-chart.component.d.ts +2 -1
  22. package/lib/components/specializations/es-pie-chart.component.d.ts +2 -1
  23. package/lib/components/specializations/es-vertical-2d-chart.component.d.ts +2 -1
  24. package/lib/components/specializations/es-vertical-chart.component.d.ts +2 -1
  25. package/lib/components/specializations/es-vertical-stacked-chart.component.d.ts +2 -1
  26. package/lib/models/EsChaartsModuleConfig.d.ts +3 -7
  27. package/lib/models/core/ChartLoader.d.ts +3 -0
  28. package/lib/tokens.d.ts +0 -4
  29. package/package.json +3 -2
@@ -1,10 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, EventEmitter, Component, ChangeDetectionStrategy, Input, Output, ContentChild, InjectionToken, Inject, Directive, PLATFORM_ID, NgModule } from '@angular/core';
3
- import * as i4 from '@angular/common';
4
- import { isPlatformBrowser, CommonModule } from '@angular/common';
2
+ import { Injectable, EventEmitter, Component, ChangeDetectionStrategy, Input, Output, ContentChild, InjectionToken, Inject, PLATFORM_ID, NgModule, Directive } from '@angular/core';
3
+ import * as i5 from '@angular/common';
4
+ import { CommonModule, isPlatformBrowser } from '@angular/common';
5
5
  import * as am4core from '@amcharts/amcharts4/core';
6
6
  import * as am4charts from '@amcharts/amcharts4/charts';
7
- import * as i3 from '@esfaenza/extensions';
7
+ import * as i4 from '@esfaenza/extensions';
8
+ import * as i4$1 from '@esfaenza/localizations';
8
9
 
9
10
  /**
10
11
  * Adapter Base da reimplementare per trasformare i dati da una libreria di grafici a questa per evitare di riscrivere tutto il codice di
@@ -364,7 +365,7 @@ class PageChartSelector {
364
365
  }
365
366
  }
366
367
  PageChartSelector.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: PageChartSelector, deps: [], target: i0.ɵɵFactoryTarget.Component });
367
- PageChartSelector.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: PageChartSelector, selector: "chart-pager", inputs: { Items: "Items", Dtos: "Dtos", BrowseDelayMs: "BrowseDelayMs", StartIndex: "StartIndex" }, outputs: { onPageChange: "onPageChange" }, queries: [{ propertyName: "headerInner_tr", first: true, predicate: ["header_inner"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"(Items || Dtos) && (Items || Dtos).length > 0\" class=\"pcs-no-selection\">\r\n <div class=\"pcs-button pcs-backward\">\r\n <svg class=\"pcs-svg-header\">\r\n <g class=\"pcs-svg-button-container\" role=\"button\" (click)=\"currentpage != 1 && Previous(); $event.stopPropagation(); $event.preventDefault();\">\r\n <!--Pulsante e freccettina all'interno-->\r\n <g class=\"pcs-svg-button\" [style.cursor]=\"currentpage == 1 ? 'not-allowed' : 'pointer'\"><path d=\"M3,0 L53.027,0 a3,3 0 0 1 3,3 L56.027,36.817 a3,3 0 0 1 -3,3 L3,39.817 a3,3 0 0 1 -3,-3 L0,3 a3,3 0 0 1 3,-3 Z\"></path></g>\r\n <g class=\"pcs-svg-arrow pcs-svg-arrow-left\"><path d=\"M26,14H10l5.17-6.79A2,2,0,0,0,12,4.79l-7.62,10a2,2,0,0,0,0,2.42l7.62,10a2,2,0,0,0,3.18-2.42L10,18H26a2,2,0,0,0,0-4Z\"></path></g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div class=\"pcs-infos\">\r\n <ng-container *ngIf=\"headerInner_tr\">\r\n <ng-container *ngTemplateOutlet=\"headerInner_tr; context : {$implicit: (Items || Dtos)[currentpage - 1]}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <div class=\"pcs-button pcs-forward\">\r\n <svg class=\"pcs-svg-header\">\r\n <g class=\"pcs-svg-button-container\" role=\"button\" (click)=\"(Items || Dtos).length != currentpage && Next(); $event.stopPropagation(); $event.preventDefault();\">\r\n <!--Pulsante e freccettina all'interno-->\r\n <g class=\"pcs-svg-button\" [style.cursor]=\"(Items || Dtos).length == currentpage ? 'not-allowed' : 'pointer'\"><path d=\"M3,0 L53.027,0 a3,3 0 0 1 3,3 L56.027,36.817 a3,3 0 0 1 -3,3 L3,39.817 a3,3 0 0 1 -3,-3 L0,3 a3,3 0 0 1 3,-3 Z\"></path></g>\r\n <g class=\"pcs-svg-arrow pcs-svg-arrow-right\"><path d=\"M26,14H10l5.17-6.79A2,2,0,0,0,12,4.79l-7.62,10a2,2,0,0,0,0,2.42l7.62,10a2,2,0,0,0,3.18-2.42L10,18H26a2,2,0,0,0,0-4Z\"></path></g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n</div>", styles: [".pcs-button{width:60px}.pcs-forward{float:right;text-align:end}.pcs-backward{float:left}.pcs-svg-header{width:57px;height:40px}.pcs-svg-button-container{outline:currentcolor none medium}.pcs-svg-arrow{pointer-events:none;fill:#555}.pcs-svg-arrow-right{transform:translate(44px,36px) rotate(180deg)}.pcs-svg-arrow-left{transform:translate(13px,4px)}.pcs-svg-button{fill:#d9d9d9;stroke:#fff;fill-opacity:1;stroke-opacity:1}.pcs-svg-button:hover{fill:#a3a3a3;cursor:pointer}.pcs-infos{width:calc(100% - 120px);height:44px;float:left}.pcs-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
368
+ PageChartSelector.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: PageChartSelector, selector: "chart-pager", inputs: { Items: "Items", Dtos: "Dtos", BrowseDelayMs: "BrowseDelayMs", StartIndex: "StartIndex" }, outputs: { onPageChange: "onPageChange" }, queries: [{ propertyName: "headerInner_tr", first: true, predicate: ["header_inner"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"(Items || Dtos) && (Items || Dtos).length > 0\" class=\"pcs-no-selection\">\r\n <div class=\"pcs-button pcs-backward\">\r\n <svg class=\"pcs-svg-header\">\r\n <g class=\"pcs-svg-button-container\" role=\"button\" (click)=\"currentpage != 1 && Previous(); $event.stopPropagation(); $event.preventDefault();\">\r\n <!--Pulsante e freccettina all'interno-->\r\n <g class=\"pcs-svg-button\" [style.cursor]=\"currentpage == 1 ? 'not-allowed' : 'pointer'\"><path d=\"M3,0 L53.027,0 a3,3 0 0 1 3,3 L56.027,36.817 a3,3 0 0 1 -3,3 L3,39.817 a3,3 0 0 1 -3,-3 L0,3 a3,3 0 0 1 3,-3 Z\"></path></g>\r\n <g class=\"pcs-svg-arrow pcs-svg-arrow-left\"><path d=\"M26,14H10l5.17-6.79A2,2,0,0,0,12,4.79l-7.62,10a2,2,0,0,0,0,2.42l7.62,10a2,2,0,0,0,3.18-2.42L10,18H26a2,2,0,0,0,0-4Z\"></path></g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div class=\"pcs-infos\">\r\n <ng-container *ngIf=\"headerInner_tr\">\r\n <ng-container *ngTemplateOutlet=\"headerInner_tr; context : {$implicit: (Items || Dtos)[currentpage - 1]}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <div class=\"pcs-button pcs-forward\">\r\n <svg class=\"pcs-svg-header\">\r\n <g class=\"pcs-svg-button-container\" role=\"button\" (click)=\"(Items || Dtos).length != currentpage && Next(); $event.stopPropagation(); $event.preventDefault();\">\r\n <!--Pulsante e freccettina all'interno-->\r\n <g class=\"pcs-svg-button\" [style.cursor]=\"(Items || Dtos).length == currentpage ? 'not-allowed' : 'pointer'\"><path d=\"M3,0 L53.027,0 a3,3 0 0 1 3,3 L56.027,36.817 a3,3 0 0 1 -3,3 L3,39.817 a3,3 0 0 1 -3,-3 L0,3 a3,3 0 0 1 3,-3 Z\"></path></g>\r\n <g class=\"pcs-svg-arrow pcs-svg-arrow-right\"><path d=\"M26,14H10l5.17-6.79A2,2,0,0,0,12,4.79l-7.62,10a2,2,0,0,0,0,2.42l7.62,10a2,2,0,0,0,3.18-2.42L10,18H26a2,2,0,0,0,0-4Z\"></path></g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n</div>", styles: [".pcs-button{width:60px}.pcs-forward{float:right;text-align:end}.pcs-backward{float:left}.pcs-svg-header{width:57px;height:40px}.pcs-svg-button-container{outline:currentcolor none medium}.pcs-svg-arrow{pointer-events:none;fill:#555}.pcs-svg-arrow-right{transform:translate(44px,36px) rotate(180deg)}.pcs-svg-arrow-left{transform:translate(13px,4px)}.pcs-svg-button{fill:#d9d9d9;stroke:#fff;fill-opacity:1;stroke-opacity:1}.pcs-svg-button:hover{fill:#a3a3a3;cursor:pointer}.pcs-infos{width:calc(100% - 120px);height:44px;float:left}.pcs-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
368
369
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: PageChartSelector, decorators: [{
369
370
  type: Component,
370
371
  args: [{ selector: "chart-pager", changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"(Items || Dtos) && (Items || Dtos).length > 0\" class=\"pcs-no-selection\">\r\n <div class=\"pcs-button pcs-backward\">\r\n <svg class=\"pcs-svg-header\">\r\n <g class=\"pcs-svg-button-container\" role=\"button\" (click)=\"currentpage != 1 && Previous(); $event.stopPropagation(); $event.preventDefault();\">\r\n <!--Pulsante e freccettina all'interno-->\r\n <g class=\"pcs-svg-button\" [style.cursor]=\"currentpage == 1 ? 'not-allowed' : 'pointer'\"><path d=\"M3,0 L53.027,0 a3,3 0 0 1 3,3 L56.027,36.817 a3,3 0 0 1 -3,3 L3,39.817 a3,3 0 0 1 -3,-3 L0,3 a3,3 0 0 1 3,-3 Z\"></path></g>\r\n <g class=\"pcs-svg-arrow pcs-svg-arrow-left\"><path d=\"M26,14H10l5.17-6.79A2,2,0,0,0,12,4.79l-7.62,10a2,2,0,0,0,0,2.42l7.62,10a2,2,0,0,0,3.18-2.42L10,18H26a2,2,0,0,0,0-4Z\"></path></g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div class=\"pcs-infos\">\r\n <ng-container *ngIf=\"headerInner_tr\">\r\n <ng-container *ngTemplateOutlet=\"headerInner_tr; context : {$implicit: (Items || Dtos)[currentpage - 1]}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <div class=\"pcs-button pcs-forward\">\r\n <svg class=\"pcs-svg-header\">\r\n <g class=\"pcs-svg-button-container\" role=\"button\" (click)=\"(Items || Dtos).length != currentpage && Next(); $event.stopPropagation(); $event.preventDefault();\">\r\n <!--Pulsante e freccettina all'interno-->\r\n <g class=\"pcs-svg-button\" [style.cursor]=\"(Items || Dtos).length == currentpage ? 'not-allowed' : 'pointer'\"><path d=\"M3,0 L53.027,0 a3,3 0 0 1 3,3 L56.027,36.817 a3,3 0 0 1 -3,3 L3,39.817 a3,3 0 0 1 -3,-3 L0,3 a3,3 0 0 1 3,-3 Z\"></path></g>\r\n <g class=\"pcs-svg-arrow pcs-svg-arrow-right\"><path d=\"M26,14H10l5.17-6.79A2,2,0,0,0,12,4.79l-7.62,10a2,2,0,0,0,0,2.42l7.62,10a2,2,0,0,0,3.18-2.42L10,18H26a2,2,0,0,0,0-4Z\"></path></g>\r\n </g>\r\n </svg>\r\n </div>\r\n <div style=\"clear: both;\"></div>\r\n</div>", styles: [".pcs-button{width:60px}.pcs-forward{float:right;text-align:end}.pcs-backward{float:left}.pcs-svg-header{width:57px;height:40px}.pcs-svg-button-container{outline:currentcolor none medium}.pcs-svg-arrow{pointer-events:none;fill:#555}.pcs-svg-arrow-right{transform:translate(44px,36px) rotate(180deg)}.pcs-svg-arrow-left{transform:translate(13px,4px)}.pcs-svg-button{fill:#d9d9d9;stroke:#fff;fill-opacity:1;stroke-opacity:1}.pcs-svg-button:hover{fill:#a3a3a3;cursor:pointer}.pcs-infos{width:calc(100% - 120px);height:44px;float:left}.pcs-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}\n"] }]
@@ -444,210 +445,6 @@ class ChartThemes {
444
445
  ;
445
446
  }
446
447
 
447
- /**
448
- * Classe di supporto al caricamento dinamico dei vari pezzi di amcharts che mi servono per il grafico (temi, locali, ecc...)
449
- *
450
- * Essenzialmente ogni volta che viene creato un grafico, questo acquisisce il tema e il locale applicato IN QUEL MOMENTO,
451
- * questo significa che per creare due grafici con temi diversi bisogna fare:
452
- *
453
- * 1) Caricamento tema 1
454
- *
455
- * 2) Creazione grafico 1
456
- *
457
- * 3) Scaricamento tema 1
458
- *
459
- * 3) Caricamento tema 2
460
- *
461
- * 4) Creazione grafico 2
462
- *
463
- */
464
- class ChartLoader {
465
- /**
466
- * @ignore
467
- */
468
- constructor(logs) {
469
- this.logs = logs;
470
- /**
471
- * Indica se attualmente ho le animazioni caricate in modo da non ricaricarle inutilmente
472
- */
473
- this.AnimationsAreLoaded = false;
474
- /**
475
- * Indica l'ultimo tema caricato in modo da non ricaricarlo inutilmente qualora il prossimo grafico da creare richieda lo stesso tema
476
- */
477
- this.LastLoadedTheme = "";
478
- /**
479
- * Cache dei temi (moduli caricati dinamicamente)
480
- */
481
- this.themeCache = {};
482
- /**
483
- * Cache delle localizzazioni (moduli caricati dinamicamente)
484
- */
485
- this.localizationCache = {};
486
- }
487
- /**
488
- * Applica il tema con le animazioni all'istanza globale di amCharts
489
- *
490
- * @param {Object} chartsCore Istanza globale di amCharts
491
- * @returns {Promise} Promise che identifica la fine del caricamento
492
- */
493
- applyAnimations(chartsCore) {
494
- if (!this.AnimationsAreLoaded) {
495
- return this.importIfNeeded('themes', ChartThemes.animated).then(() => {
496
- this.log("CORE: Applying theme " + ChartThemes.animated);
497
- chartsCore.useTheme(this.themeCache[ChartThemes.animated]);
498
- this.AnimationsAreLoaded = true;
499
- });
500
- }
501
- else {
502
- this.log("CORE: theme already applyed " + ChartThemes.animated);
503
- return new Promise((resolve) => { resolve(true); });
504
- }
505
- }
506
- /**
507
- * De-applica il tema con le animazioni dall'istanza globale di amCharts
508
- *
509
- * @param {Object} chartsCore Istanza globale di amCharts
510
- * @returns {Promise} Promise che identifica la fine dello scarico
511
- */
512
- unapplyAnimations(chartsCore) {
513
- if (this.AnimationsAreLoaded) {
514
- this.log("CORE: Animations in use, unapplying theme " + ChartThemes.animated);
515
- chartsCore.unuseTheme(this.themeCache[ChartThemes.animated]);
516
- this.AnimationsAreLoaded = false;
517
- }
518
- else
519
- this.log("CORE: Animations already unused, no need to unapply them");
520
- return new Promise((resolve) => { resolve(true); });
521
- }
522
- /**
523
- * Applica il tema specificato all'istanza globale di amCharts
524
- *
525
- * @param {Object} chartsCore Istanza globale di amCharts
526
- * @param {'spiritedaway' | 'moonrisekingdom' | 'frozen' | 'dark' | 'kelly' | 'material' | 'dataviz' | 'none'} theme Tema da applicare
527
- * @returns {Promise} Promise che identifica la fine del caricamento
528
- */
529
- applyTheme(chartsCore, theme) {
530
- // Ultimo tema applicato è lo stesso che mi è stato richiesto di applicare --> NO-OP
531
- if (this.LastLoadedTheme == theme) {
532
- this.log("CORE: theme already applied " + theme);
533
- return new Promise((resolve) => { resolve(true); });
534
- }
535
- // Scarico il tema precedente a prescindere, ormai non mi serve più
536
- this.unapplyPreviousTheme(chartsCore);
537
- // Il tema è il none --> registro la cosa e basta, il tema precedente è stato rimosso subito qui sopra ^
538
- if (theme == ChartThemes.none) {
539
- this.LastLoadedTheme = ChartThemes.none;
540
- return new Promise((resolve) => { resolve(true); });
541
- }
542
- // Il tema è diverso dal precedente e non è il tema vuoto --> Importo il tema specificato se non presente in memoria e lo applico al grafico attuale
543
- return this.importIfNeeded('themes', theme).then(() => {
544
- this.log("CORE: Applying theme " + theme);
545
- chartsCore.useTheme(this.themeCache[theme]);
546
- this.LastLoadedTheme = theme;
547
- });
548
- }
549
- /**
550
- * De-applica il tema precedente dall'istanza globale di amCharts
551
- *
552
- * @param {Object} chartsCore Istanza globale di amCharts
553
- */
554
- unapplyPreviousTheme(chartsCore) {
555
- if (!this.LastLoadedTheme || this.LastLoadedTheme == ChartThemes.none)
556
- return;
557
- this.log("CORE: Unapplying previously used theme " + this.LastLoadedTheme);
558
- chartsCore.unuseTheme(this.themeCache[this.LastLoadedTheme]);
559
- }
560
- /**
561
- * Applica il locale specificato all'istanza specifica del grafico
562
- *
563
- * @param {amCharts.Chart} chart Istanza specifica del grafico a cui applicare il locale
564
- * @param {string} locale Locale da applicare
565
- * @returns {Promise} Promise che identifica la fine del caricamento
566
- */
567
- applyLocale(chart, locale) {
568
- return this.importIfNeeded('lang', locale).then(() => {
569
- this.log("Chart " + chart.htmlContainer.id + ": applying locale " + locale);
570
- chart.language.locale = this.localizationCache[locale];
571
- });
572
- }
573
- /**
574
- * Permette di importare, se serve un dato tema o localizzazione
575
- *
576
- * @param {'lang' | 'themes'} what Oggetto da importare, se localizzazione o tema
577
- * @param {string} item Chiave dell'oggetto da importare
578
- *
579
- * @returns {Promise} Promise che identifica la fine del caricamento
580
- */
581
- importIfNeeded(what, item) {
582
- // Se sto cercando di caricare qualcosa di già caricato non faccio nulla
583
- if (!(what == 'themes' && !this.themeCache[item]) && !(what == 'lang' && !this.localizationCache[item])) {
584
- this.log("CORE: " + (what == 'lang' ? "Language " : "Theme ") + item + " already loaded");
585
- return new Promise((resolve) => { resolve(true); });
586
- }
587
- this.log("CORE: Loading " + (what == 'lang' ? "language " : "theme ") + item);
588
- /*
589
- * ****************************
590
- * ******** ATTENZIONE ********
591
- * ****************************
592
- *
593
- * Se stai vedendo questo codice di import e stai valutando di riscriverlo come:
594
- *
595
- * V V
596
- * import(`@amcharts/amcharts4/${what}/${item}`).then(module => {
597
- * if (what == 'themes') this.themeCache[item] = module.default;
598
- * else if (what == 'lang') this.localizationCache[item] = module.default;
599
- * });
600
- *
601
- * Sappi che è una pessima idea. Gli import sono valutati da webpack in compiletime per generare i chunk,
602
- * mettere la navigazione agli import con la concatenazione viene preso malissimo ed essenzialmente dice a webpack
603
- * di tirare su e bundlare l'intera node_modules. Divertente, no?
604
- *
605
- */
606
- switch (what) {
607
- case 'themes':
608
- switch (item) {
609
- case ChartThemes.spiritedaway:
610
- return import('@amcharts/amcharts4/themes/spiritedaway').then(theme => this.themeCache[item] = theme.default);
611
- case ChartThemes.moonrisekingdom:
612
- return import('@amcharts/amcharts4/themes/moonrisekingdom').then(theme => this.themeCache[item] = theme.default);
613
- case ChartThemes.frozen:
614
- return import('@amcharts/amcharts4/themes/frozen').then(theme => this.themeCache[item] = theme.default);
615
- case ChartThemes.dark:
616
- return import('@amcharts/amcharts4/themes/dark').then(theme => this.themeCache[item] = theme.default);
617
- case ChartThemes.kelly:
618
- return import('@amcharts/amcharts4/themes/kelly').then(theme => this.themeCache[item] = theme.default);
619
- case ChartThemes.material:
620
- return import('@amcharts/amcharts4/themes/material').then(theme => this.themeCache[item] = theme.default);
621
- case ChartThemes.dataviz:
622
- return import('@amcharts/amcharts4/themes/dataviz').then(theme => this.themeCache[item] = theme.default);
623
- case ChartThemes.animated:
624
- return import('@amcharts/amcharts4/themes/animated').then(theme => this.themeCache[item] = theme.default);
625
- }
626
- break;
627
- case 'lang':
628
- switch (item) {
629
- case 'it-IT':
630
- return import('@amcharts/amcharts4/lang/it_IT').then(lang => this.localizationCache[item] = lang.default);
631
- case 'en-US':
632
- return import('@amcharts/amcharts4/lang/en_US').then(lang => this.localizationCache[item] = lang.default);
633
- }
634
- }
635
- this.log("CORE: Loading Failed. " + (what == 'lang' ? "Language " : "Theme") + " not recognized: " + item);
636
- return new Promise((resolve) => { resolve(true); });
637
- }
638
- /**
639
- * @ignore
640
- */
641
- log(text) {
642
- if (this.logs)
643
- console.log("@esfaenza/es-charts: " + text);
644
- }
645
- }
646
-
647
- /**
648
- * Token che identifica il Locale di default per tutti i grafici, può essere sovrascritto dalle impostazioni locali (Settings e Input)
649
- */
650
- const ESC_LOCALE = new InjectionToken('ESC_LOCALE');
651
448
  /**
652
449
  * Token che identifica il default per l'utilizzo o meno delle Animazioni per tutti i grafici, può essere sovrascritto dalle impostazioni locali (Settings e Input)
653
450
  */
@@ -662,676 +459,594 @@ const ESC_THEME = new InjectionToken('ESC_THEME');
662
459
  const ESC_LOGS = new InjectionToken('ESC_LOGS');
663
460
 
664
461
  /**
665
- * Classe che si occupa del dispatch delle operazioni di rendering dei grafici utilizzando una coda per permettere ad ogni grafico di avere temi e localizzazione custom
462
+ * Classe il cui unico scopo è gestire il setup e rendering di un LineChart
666
463
  */
667
- class ChartDispatcher {
668
- /**
669
- * @ignore
670
- */
671
- constructor(logs) {
672
- this.logs = logs;
673
- /**
674
- * Coda di inizializzazioni ancora da eseguire. Quando questa è vuota significa che nessuno sta creando grafici
675
- */
676
- this.Initializations = [];
677
- /**
678
- * Lista dei grafici inizializzati e attivi in un dato momento (viene registrata la proprietà **name**). Non è possibile registrare due grafici con lo stesso identificativo
679
- */
680
- this.InitializedGraphs = [];
681
- }
682
- /**
683
- * Registra un grafico da visualizzare insieme alla propria funzione di creazione. Quest'ultima sarà differita fino a che tutti i grafici
684
- * precedentemente registati non hanno finito la fase di inizializzazione
685
- *
686
- * @param {string} name Identificativo del grafico da registrare
687
- * @param {Function} chartCreationFunction Funzione che fisicamente dovrà occuparsi della creazione del grafico
688
- */
689
- register(name, chartCreationFunction) {
690
- if (this.InitializedGraphs.indexOf(name) != -1)
691
- throw "Attempting to register a duplicate chart '" + name + "'. Make sure the 'name' properties of your charts are univoque";
692
- this.log("DISPATCHER: Registering chart creation function execution for " + name);
693
- this.Initializations.push({ name: name, function: chartCreationFunction });
694
- if (this.Initializations.length == 1) {
695
- this.log("DISPATCHER: Initial drain started");
696
- this.drainInitQueues();
697
- }
464
+ class LineChartService {
465
+ /** @ignore */
466
+ constructor(Adapter, dateExts) {
467
+ this.Adapter = Adapter;
468
+ this.dateExts = dateExts;
469
+ /** @ignore */
470
+ this.DataGroupBucketSize = 1500;
471
+ /** @ignore */
472
+ this.OpacityOnSelected = 0.3;
473
+ /** @ignore */
474
+ this.OpacityOnFill = 0.75;
475
+ /** @ignore */
476
+ this.singleDataSet = false;
477
+ //******************** Funzione di throttling per non spammare richieste in caso di animazioni attivate
478
+ //TODO: spostarla in un metodo di utilità (esfaenza/extensions)
479
+ /** @ignore */
480
+ this.executionTimers = {};
698
481
  }
699
482
  /**
700
- * Deregistra un grafico presente. Chiamata generalmente al dispose del grafico in questione quando non dev'essere più mostrato nella pagina corrente
701
- *
702
- * @param {string} name Identificativo del grafico da deregistrare
483
+ * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un LineChart
703
484
  */
704
- deregisterGraph(name) {
705
- let index = this.InitializedGraphs.indexOf(name);
706
- if (index == -1) {
707
- //Questo succede quando si cerca di distruggere il grafico mentre sta venendo graficato
708
- this.log("DISPATCHER: Registration missing for chart " + name + " it was probably destroyed during load");
709
- return;
485
+ graphicate(data, settings) {
486
+ let dataConverted = this.Adapter ? this.Adapter.adaptDataForLineChart(data) : data;
487
+ let threshold = settings.DataGroupingThreshold ?? 3000;
488
+ this.singleDataSet = settings.MergeDatasets ?? false;
489
+ let showTicks = settings.ShowTicks == null ? true : settings?.ShowTicks;
490
+ let dataShouldBeGrouped = Math.max(...dataConverted.series.map(t => t.values.length)) > threshold;
491
+ let showTimeline = settings.Timeline || dataShouldBeGrouped;
492
+ let seriesWithInterval = dataConverted.series.some(t => t.interval);
493
+ let interval = seriesWithInterval ? dataConverted.series.find(t => t.interval).interval : null;
494
+ let gapsAllowed = settings?.AllowGaps == null ? seriesWithInterval : settings?.AllowGaps;
495
+ let finalInstant = settings?.FinalInstants ?? true;
496
+ //Per evitare di dimenticarmeli e gestire comunque bene gli ngif ecc...
497
+ am4core.options.autoDispose = true;
498
+ this.ChartInstance = am4core.create(settings.Name, am4charts.XYChart);
499
+ let ChartInstanceCasted = this.ChartInstance;
500
+ let yAxis = ChartInstanceCasted.yAxes.push(new am4charts.ValueAxis());
501
+ if (settings.YAxisTitle) {
502
+ yAxis.title.text = settings.YAxisTitle;
503
+ yAxis.title.fontWeight = "bold";
710
504
  }
711
- this.log("DISPATCHER: Chart deregistered " + name);
712
- this.InitializedGraphs.splice(index, 1);
713
- }
714
- /**
715
- * Metodo che esegue in maniera sequenziale le funzioni di inizializzazione dei grafici finché presenti
716
- * in modo che nessun grafico possa essere inizializzato contemporaneamente ad un altro.
717
- *
718
- * Questo è il punto chiave che permette di avere per ogni grafico temi e locale differenti
719
- */
720
- drainInitQueues() {
721
- let toExecute = this.Initializations[0];
722
- this.log("DISPATCHER: Executing initialization function for chart " + toExecute.name);
723
- toExecute.function().then(() => {
724
- this.log("DISPATCHER: initialization for chart " + toExecute.name + " is done");
725
- this.InitializedGraphs.push(toExecute.name);
726
- this.Initializations.splice(0, 1);
727
- if (this.Initializations.length >= 1) {
728
- this.log("DISPATCHER: Found queued initializations. Continuing");
729
- this.drainInitQueues();
505
+ if (settings.Min)
506
+ yAxis.min = settings.Min;
507
+ if (settings.Max)
508
+ yAxis.max = settings.Max;
509
+ let limitNullOrUndef = dataConverted.limit == null || dataConverted.limit == undefined;
510
+ let limits = limitNullOrUndef ? [] : !dataConverted.limit.length ? [dataConverted.limit] : dataConverted.limit;
511
+ if (limits.length > 0) {
512
+ for (let i = 0; i < limits.length; i++) {
513
+ let limit = limits[i];
514
+ if (limit.upper != null && limit.upper != undefined && limit.lower != null && limit.lower != undefined) {
515
+ let range = yAxis.axisRanges.create();
516
+ range.value = limit.lower;
517
+ range.endValue = limit.upper;
518
+ if (limit.fillColor) {
519
+ range.contents.stroke = am4core.color(limit.fillColor);
520
+ range.contents.fill = range.contents.stroke;
521
+ }
522
+ range.label.inside = true;
523
+ range.label.text = limit.upperlabel;
524
+ range.label.fill = range.grid.stroke;
525
+ range.label.verticalCenter = "bottom";
526
+ range.label.stroke = am4core.color(limit.uppercolor || "#F92200");
527
+ range.grid.stroke = am4core.color(limit.uppercolor || "#F92200");
528
+ range.grid.strokeWidth = 2;
529
+ range.grid.strokeOpacity = 1;
530
+ }
531
+ else if ((limit.lower == null || limit.lower == undefined) && limit.upper != null && limit.upper != undefined) {
532
+ let range = yAxis.axisRanges.create();
533
+ range.value = limit.upper;
534
+ range.label.inside = true;
535
+ range.label.text = limit.upperlabel;
536
+ range.label.fill = range.grid.stroke;
537
+ range.label.verticalCenter = "bottom";
538
+ range.label.stroke = am4core.color(limit.uppercolor || "#F92200");
539
+ range.grid.stroke = am4core.color(limit.uppercolor || "#F92200");
540
+ range.grid.strokeWidth = 2;
541
+ range.grid.strokeOpacity = 1;
542
+ }
543
+ else if ((limit.upper == null || limit.upper == undefined) && limit.lower != null && limit.lower != undefined) {
544
+ let range = yAxis.axisRanges.create();
545
+ range.value = limit.lower;
546
+ range.label.inside = true;
547
+ range.label.text = limit.lowerlabel;
548
+ range.label.fill = range.grid.stroke;
549
+ range.label.verticalCenter = "bottom";
550
+ range.label.stroke = am4core.color(limit.lowercolor || "#F92200");
551
+ range.grid.stroke = am4core.color(limit.lowercolor || "#F92200");
552
+ range.grid.strokeWidth = 2;
553
+ range.grid.strokeOpacity = 1;
554
+ }
555
+ }
556
+ }
557
+ this.dateAxis = ChartInstanceCasted.xAxes.push(new am4charts.DateAxis());
558
+ // Per comatibilità col codice scritto quando non era a livello globale, mi scoccia sostituire
559
+ let dateAxis = this.dateAxis;
560
+ if (settings.XAxisTitle) {
561
+ dateAxis.title.text = settings.XAxisTitle;
562
+ dateAxis.title.fontWeight = "bold";
563
+ }
564
+ if (showTicks) {
565
+ dateAxis.renderer.ticks.template.disabled = false;
566
+ dateAxis.renderer.ticks.template.strokeOpacity = 1;
567
+ dateAxis.renderer.ticks.template.stroke = am4core.color("#495C43");
568
+ dateAxis.renderer.ticks.template.strokeWidth = 2;
569
+ dateAxis.renderer.ticks.template.length = 10;
570
+ dateAxis.renderer.ticks.template.location = 0;
571
+ }
572
+ dateAxis.renderer.minGridDistance = settings?.MinGridDistance ?? 50;
573
+ dateAxis.renderer.grid.template.location = 0;
574
+ dateAxis.minZoomCount = 5;
575
+ dateAxis.groupData = dataShouldBeGrouped;
576
+ dateAxis.groupCount = settings.DataGroupBucketSize ?? this.DataGroupBucketSize;
577
+ //Se ho almeno una serie ad intervallo e i settings non mi impediscono esplicitamente di usare i gaps, visualizzo i dati col gap
578
+ if (gapsAllowed) {
579
+ if (!seriesWithInterval) {
580
+ console.error("Per utilizzare la funzionalità dei gap è obbligatorio definire un intervallo nelle serie del grafico");
581
+ return null;
582
+ }
583
+ dateAxis.baseInterval = { count: interval.count, timeUnit: interval.timeunit };
584
+ }
585
+ if (showTimeline)
586
+ ChartInstanceCasted.scrollbarX = new am4charts.XYChartScrollbar();
587
+ let seriesToPush = [];
588
+ let seriesColors = [];
589
+ let defaultIndex = 0;
590
+ // Ordinamento dei dati se serve
591
+ dataConverted.series.forEach((s) => {
592
+ if (s.values[0] && !(s.values[0].d instanceof Date)) {
593
+ for (let v = 0; v < s.values.length; v++)
594
+ s.values[v].d = new Date(s.values[v].d);
595
+ }
596
+ var correctOrder = true;
597
+ var prevDate = null;
598
+ for (let v = 0; v < s.values.length; v++) {
599
+ if (!prevDate)
600
+ prevDate = s.values[v].d;
601
+ else if (s.values[v].d < prevDate) {
602
+ correctOrder = false;
603
+ break;
604
+ }
605
+ }
606
+ if (!correctOrder)
607
+ s.values.sort((d1, d2) => d1.d.getTime() - d2.d.getTime());
608
+ });
609
+ // Generazione di un unico dataset invece che N, per poter gestire un unico tooltip
610
+ if (this.singleDataSet) {
611
+ this.ChartInstance.data = this.generateSingleDataset(dataConverted);
612
+ ;
613
+ dateAxis.cursorTooltipEnabled = false;
614
+ }
615
+ dataConverted.series.forEach((s, index) => {
616
+ let stacked = s.stacked != null && s.stacked != undefined ? s.stacked : (settings?.Stacked ?? false);
617
+ let fill = stacked || (s.fill != null && s.fill != undefined ? s.fill : (settings?.Fill ?? false));
618
+ let series = settings?.Step ? new am4charts.StepLineSeries() : new am4charts.LineSeries();
619
+ series.dataFields.valueY = "v" + (this.singleDataSet ? index : "");
620
+ series.dataFields.dateX = "d";
621
+ series.measureUnit = s.uom;
622
+ series.name = s.name;
623
+ series.strokeWidth = settings?.StrokeSize ?? 1;
624
+ series.connect = !gapsAllowed;
625
+ series.minBulletDistance = 10;
626
+ series.tooltipText = this.singleDataSet ? "" : s.name ? "{name}: [bold]{valueY}[/]" : "[bold]{valueY}[/]";
627
+ series.tooltip.pointerOrientation = "vertical";
628
+ series.tooltip.background.fillOpacity = 0.5;
629
+ series.tooltip.label.padding(12, 12, 12, 12);
630
+ series.fillOpacity = fill ? this.OpacityOnFill : 0.0001;
631
+ series.stacked = stacked;
632
+ series.hidden = s.hidden;
633
+ //Dataset singolo, i dati sono registrati a livello di chart, creo il tooltip che permette di vederli tutti insieme
634
+ //altrimenti assegno i dati della serie direttamente alla serie
635
+ if (this.singleDataSet) {
636
+ series.tooltip.getFillFromObject = false;
637
+ series.tooltip.background.fill = am4core.color("#eee");
638
+ series.tooltip.label.fill = am4core.color("#00");
639
+ series.tooltip.defaultState.transitionDuration = 0;
640
+ series.tooltip.hiddenState.transitionDuration = 0;
641
+ //Utilizzo il mio dateService per la formattazione della data in modo che non debba mai gestire n formati fra n librerie... bellissimo
642
+ series.dateFormatter.format = (source) => {
643
+ if (interval && finalInstant && ["hour", "minute", "second"].includes(interval.timeunit)) {
644
+ let timepart = null;
645
+ switch (interval.timeunit) {
646
+ case "hour":
647
+ timepart = 'day';
648
+ break;
649
+ case "minute":
650
+ timepart = 'hour';
651
+ break;
652
+ case "second":
653
+ timepart = 'minute';
654
+ break;
655
+ }
656
+ if (timepart)
657
+ return this.dateExts.adjustDateToFinalInstant(source, timepart, interval ? interval.timeunit == "second" : false);
658
+ }
659
+ else
660
+ return this.dateExts.getFormatted(source, interval ? ["day", "week", "month", "year"].includes(interval.timeunit) : false, interval ? interval.timeunit == "second" : false);
661
+ };
662
+ series.adapter.add("tooltipText", () => {
663
+ var text = "[bold]{dateX.formatDate()}[/]\n";
664
+ this.ChartInstance.series.each((item) => {
665
+ let uom = " [font-style: italic]" + series.measureUnit || "" + "[/]";
666
+ text += "[" + item.stroke.hex + "]●[/] " + (item.name ? (item.name + ": ") : "") + "[bold]{" + item.dataFields.valueY + "}[/]" + uom + "\n";
667
+ });
668
+ return text;
669
+ });
730
670
  }
731
671
  else
732
- this.log("DISPATCHER: queue is over, nothing more to do");
672
+ series.data = s.values;
673
+ let segment = series.segments.template;
674
+ let hoverState = segment.states.create("hover");
675
+ hoverState.properties.strokeWidth = (settings?.StrokeSize ?? 1) + 1;
676
+ let dimmed = segment.states.create("dimmed");
677
+ dimmed.properties.stroke = am4core.color("#dadada");
678
+ //Se la serie ha un colore, uso quello, altrimenti pesco dai colori di default andando in ordine
679
+ if (s.color)
680
+ seriesColors.push(am4core.color(s.color));
681
+ else {
682
+ seriesColors.push(ChartInstanceCasted.colors.list[defaultIndex % ChartInstanceCasted.colors.list.length]);
683
+ defaultIndex++;
684
+ }
685
+ seriesToPush.push(series);
733
686
  });
687
+ ChartInstanceCasted.colors.list = seriesColors;
688
+ //Scrivo le serie nel grafico
689
+ seriesToPush.forEach(s => {
690
+ ChartInstanceCasted.series.push(s);
691
+ if (showTimeline)
692
+ ChartInstanceCasted.scrollbarX.series.push(s);
693
+ });
694
+ if (settings.Legend) {
695
+ this.ChartInstance.legend = new am4charts.Legend();
696
+ this.ChartInstance.legend.position = settings?.LegendPosition ?? 'right';
697
+ this.ChartInstance.legend.scrollable = true;
698
+ this.ChartInstance.legend.itemContainers.template.tooltipText = "{name}";
699
+ this.ChartInstance.legend.itemContainers.template.events.on("over", (event) => { this.processOver(event.target.dataItem.dataContext); });
700
+ this.ChartInstance.legend.itemContainers.template.events.on("out", () => { this.processOut(); });
701
+ if (settings.LegendPadding) {
702
+ let template = this.ChartInstance.legend.itemContainers.template;
703
+ template.paddingTop = settings.LegendPadding.top ?? 0;
704
+ template.paddingBottom = settings.LegendPadding.bottom ?? 0;
705
+ template.paddingLeft = settings.LegendPadding.left ?? 0;
706
+ template.paddingRight = settings.LegendPadding.right ?? 0;
707
+ }
708
+ }
709
+ this.ChartInstance.cursor = new am4charts.XYCursor();
710
+ //Prove******************************************************************************************************************************
711
+ // this.ChartInstance.cursor.events.on("cursorpositionchanged", (ev) => {
712
+ // //var value = dateAxis.positionToDate(dateAxis.toAxisPosition(ev.target.xPosition));
713
+ // var dt = dateAxis.series.values.find(t => t.dataItem.values.dateX);
714
+ // if (dt && dt.dataItem) {
715
+ // console.log(dt.dataItem.values);
716
+ // // this.ChartInstance.tooltipText = dt;
717
+ // }
718
+ // else {
719
+ // this.ChartInstance.tooltipText = "";
720
+ // }
721
+ // });
722
+ //******************************************************************************************************************************
723
+ this.ChartInstance.cursor.xAxis = dateAxis;
724
+ this.ChartInstance.cursor.yAxis = yAxis;
725
+ if (this.singleDataSet)
726
+ this.ChartInstance.cursor.maxTooltipDistance = -1;
727
+ //TODO: Cercare di capire perché è figlio di puttana......
728
+ dateAxis.events.on("startchanged", t => this.emitSelectionChanged(t, settings));
729
+ dateAxis.events.on("endchanged", t => this.emitSelectionChanged(t, settings));
730
+ return this;
734
731
  }
735
- /**
736
- * @ignore
737
- */
738
- log(text) {
739
- if (this.logs)
740
- console.log("@esfaenza/es-charts: " + text);
741
- }
742
- }
743
- ChartDispatcher.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartDispatcher, deps: [{ token: ESC_LOGS }], target: i0.ɵɵFactoryTarget.Injectable });
744
- ChartDispatcher.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartDispatcher });
745
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartDispatcher, decorators: [{
746
- type: Injectable
747
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
748
- type: Inject,
749
- args: [ESC_LOGS]
750
- }] }]; } });
751
-
752
- /**
753
- * Componente Grafico Base che gestisce tutte le cose comuni dei vari grafici istanziabili, come la presenza o menu di una legenda,
754
- * il tema utilizzato, il locale del singolo grafico, ecc ecc...
755
- */
756
- class BaseChartComponent {
757
- /**
758
- * Costruttore
759
- *
760
- * @param {ElementRef} el Contenitore all'interno del cui viene creato il grafico. Utilizzato per estrapolarne la **ContainerHeight**
761
- * @param {Object} platformId piattaforma Angular (browser, ecc...) per essere sicuri che amcharts venga attivato solo lato browser. Non utilizzando SSR nelle applicazioni che consumano questa libreria non è particolarmente significativo, ma non si sa mai
762
- * @param {NgZone} zone NgZone di default per permettere di inizializzare il grafico all'infuori di Angular per avere qualche prestazione in più
763
- * @param {ChartLoader} Charter Istanza del Loader che si occuperà di caricare in memoria tutto ciò che serve per il grafico attuale (temi, locale, animazioni, ecc...)
764
- * @param {ChartDispatcher} Dispatcher Istanza del Dispatcher che si occupa di differire il caricamento dei grafici 1 dopo l'altro in modo che caricamenti pseudo paralleli incasinino tutto
765
- * @param {boolean} logs Indica se effettuare log a console o meno, iniettato dalle classi specializzate dal token ESC_LOGS
766
- * @param {boolean} animations Indica se per questo grafico devono essere attive o meno le animazioni. Impostazione generica presa dal token ESC_ANIMATIONS
767
- * @param {string} locale Indica il locale specifico per questo grafico. Impostazione generica presa dal token ESC_LOCALE
768
- * @param {string} theme Indica il tema specifico per questo grafico. Impostazione generica presa dal token ESC_THEME
769
- */
770
- constructor(el, platformId, zone, Charter, Dispatcher, logs, animations, locale, theme) {
771
- this.el = el;
772
- this.platformId = platformId;
773
- this.zone = zone;
774
- this.Charter = Charter;
775
- this.Dispatcher = Dispatcher;
776
- this.logs = logs;
777
- this.animations = animations;
778
- this.locale = locale;
779
- this.theme = theme;
780
- /**
781
- * Nome del grafico, fondamentale assegnarlo per permettere alla libreria di schedularne la creazione
782
- */
783
- this.name = "";
784
- /**
785
- * Dopo aver navigato a un nuovo grafico verranno attesi questi millisecondi prima di richiedere i dati attraverso la **DataRetrieve**.
786
- *
787
- * Questo per evitare che l'utente cliccando velocemente "avanti" generi tonnellate di richieste inutili
788
- */
789
- this.BrowseDelayMs = 500;
790
- /**
791
- * Evento lanciato sulla selezione di un range di dati o dalla timeline o dal grafico. Valido per tutti i grafici che supportano serie basate sulle date
792
- */
793
- this.onSelectionChanged = new EventEmitter();
794
- /**
795
- * Evento lanciato dal click di una serie dalla Legenda, a patto che l'Input **HideSeriesOnLabelClick** sia impostato a false
796
- */
797
- this.onSeriesClicked = new EventEmitter();
798
- /**
799
- * Evento lanciato all'inizio del caricamento di una nuova pagina del grafico
800
- */
801
- this.onLoadStart = new EventEmitter();
802
- /**
803
- * Evento lanciato al termine del caricamento di una nuova pagina del grafico
804
- */
805
- this.onLoadEnd = new EventEmitter();
806
- /**
807
- * Evento lanciato al termine della creazione del grafico referenziando l'istanza nativa del grafico creato in modo da poter effettuare modifiche
808
- * post inizializzazione lato applicativo
809
- */
810
- this.chartLoaded = new EventEmitter();
811
- /**
812
- * Serve a decidere se sarà presente l'interfaccia di paginazione
813
- */
814
- this.isPaged = false;
815
- /**
816
- * @ignore
817
- */
818
- this.initDone = false;
819
- }
820
- /**
821
- * Metodo di inizializzazione post valorizzazione degli input, utilizzato per valorizzare correttamente le proprietà essenziali del grafico (Animazioni, Tema e Locale)
822
- *
823
- * Viene data priorità ai Settings (HTML), priorità secondaria agli Input diretti (Lato HTML), priorità ultima alle impostazioni globali,
824
- * impostate in fase di import del modulo assegnando valori ai token ESC_LOCALE, ESC_ANIMATIONS, ESC_THEME
825
- */
826
- ngOnInit() {
827
- // Qui servono solo le variabili da conoscere PRE-graficazione per il caricamento dei moduli lazy del grafico
828
- this.Animations = this.Settings?.Animations != null ? this.Settings?.Animations : (this.Animations != null ? this.Animations : this.animations);
829
- this.Theme = this.Settings?.Theme != null ? this.Settings?.Theme : (this.Theme != null ? this.Theme : this.theme);
830
- this.Locale = this.Settings?.Locale != null ? this.Settings?.Locale : (this.Locale != null ? this.Locale : this.locale);
831
- this.isPaged = (this.DataArray && this.DataArray.length > 0 && !this.Data) || (this.DataDtos && this.DataDtos.length > 0 && !!this.DataRetrieve);
832
- this.log("Chart " + this.name + ": ngOnInit");
732
+ /** @ignore */
733
+ setSelection(from, to) {
734
+ this.dateAxis.zoomToDates(from, to, true, true);
833
735
  }
834
- /**
835
- * Implementazione utilizzata per controllare eventuali proprietà chiave del grafico e rigraficare tutto qualora si rivelasse necessario
836
- *
837
- * @param {SimpleChanges} changes Indicazione dei cambiamenti sulle proprietà del grafico. Vedere documentazione Angular in merito
838
- */
839
- ngOnChanges(changes) {
840
- if (!this.initDone)
736
+ /** @ignore */
737
+ refreshData(data) {
738
+ let dataConverted = this.Adapter ? this.Adapter.adaptDataForLineChart(data) : data;
739
+ if (this.singleDataSet) {
740
+ var data = this.generateSingleDataset(dataConverted);
741
+ this.ChartInstance.addData(data);
841
742
  return;
842
- this.log("Chart " + this.name + ": ngOnChanges");
843
- let propsToCheck = ["Timeline", "Legend", "Settings", "Animations", "Theme", "Locale", ...this.getSpecificPropertiesToCheck()];
844
- this.checkPropertiesAndRegraphicateAsNeeded(changes, propsToCheck);
743
+ }
744
+ throw "Impossibile aggiornare i dati senza unire il dataset. Si prega di impostare [MergeDatasets] a true";
845
745
  }
846
- /**
847
- * Nel post inizializzazione, a patto che mi trovi in ambiente "browser", proseguo al caricamento del grafico sull'HTML
848
- */
849
- ngAfterViewInit() {
850
- if (!this.name)
851
- throw "a Unique name is mandatory to create a chart";
852
- this.log("Chart " + this.name + ": ngAfterViewInit, graphicating chart outside Angular");
853
- if (!this.isPaged)
854
- this.dispatchLoadChart();
746
+ /** Partendo da dati divisi per seriue genera un dataset unito con la data come chiave e i vari valori dopo */
747
+ generateSingleDataset(data) {
748
+ let dto = {};
749
+ data.series.forEach((vs, index) => {
750
+ for (let i = 0; i < vs.values.length; i++) {
751
+ var dataitem = vs.values[i];
752
+ var indexer = new Date(dataitem.d).valueOf();
753
+ if (!dto[indexer])
754
+ dto[indexer] = {};
755
+ dto[indexer]['v' + index] = dataitem.v;
756
+ }
757
+ });
758
+ var dates = Object.keys(dto);
759
+ var ret = [];
760
+ for (let i = 0; i < dates.length; i++) {
761
+ let values = dto[dates[i]];
762
+ let item = { d: new Date(parseInt(dates[i])) };
763
+ var vals = Object.keys(values);
764
+ for (let ii = 0; ii < vals.length; ii++) {
765
+ let series = vals[ii];
766
+ let singleVal = values[series];
767
+ item[series] = singleVal;
768
+ }
769
+ ret.push(item);
770
+ }
771
+ return ret;
855
772
  }
856
- /**
857
- * All'onDestroy scarico il grafico per liberare memoria
858
- */
859
- ngOnDestroy() {
860
- if (this.Chart) {
861
- this.log("Chart " + this.name + ": Unloading destroyed chart");
862
- this.browserOnly(() => { this.Chart.dispose(); this.Dispatcher.deregisterGraph(this.name); });
773
+ /** @ignore */
774
+ emitSelectionChanged(ev, settings) {
775
+ if (settings.OnSelectionChangedCallback) {
776
+ this.throttla("selchange", () => {
777
+ var axis = ev.target;
778
+ var start = new Date(axis.minZoomed);
779
+ var end = new Date(axis.maxZoomed);
780
+ var initial = axis.min == axis.minZoomed && axis.max == axis.maxZoomed;
781
+ settings.OnSelectionChangedCallback({ from: start, to: end, initial: initial });
782
+ }, 150);
863
783
  }
864
- else
865
- this.log("Chart " + this.name + ": Unloading uncreated chart component. It probably was a duplicated");
866
784
  }
867
- /**
868
- * Registra il grafico attuale nel Dispatcher in modo che venga caricato appena possibile
869
- */
870
- dispatchLoadChart() {
871
- this.browserOnly(() => {
872
- this.Dispatcher.register(this.name, () => { return this.loadChart(); });
785
+ /** @ignore */
786
+ processOver(hoveredSeries) {
787
+ hoveredSeries.zIndex = 999;
788
+ let fill = hoveredSeries.fillOpacity == this.OpacityOnFill;
789
+ hoveredSeries.segments.each((segment) => {
790
+ segment.setState("hover");
791
+ if (!fill)
792
+ segment.fillSprite.fillOpacity = this.OpacityOnSelected;
793
+ });
794
+ if (!fill)
795
+ hoveredSeries.legendDataItem.marker.children.getIndex(1).fillOpacity = this.OpacityOnSelected;
796
+ this.ChartInstance.series.each((series) => {
797
+ if (series != hoveredSeries) {
798
+ let fill = series.fillOpacity == this.OpacityOnFill;
799
+ series.segments.each((segment) => {
800
+ segment.setState("dimmed");
801
+ if (!fill)
802
+ segment.fillSprite.fillOpacity = 0;
803
+ });
804
+ }
873
805
  });
874
806
  }
875
- /**
876
- * Il caricamento del grafico funziona nel seguente modo:
877
- *
878
- * 1) Caricamento del tema e delle animazioni, qualora necessari
879
- *
880
- * 2) Caricamento delle impostazioni specifiche e integrazione con le impostazioni generiche
881
- *
882
- * 3) Graficazione
883
- *
884
- * 4) Caricamento del locale
885
- */
886
- loadChart() {
887
- this.log("Chart " + this.name + ": Start loading Modules if needed");
888
- return Promise.all([
889
- this.setupAmChartsThemes().then(() => {
890
- this.log("Chart " + this.name + ": Graphicating after modules load");
891
- var castedSettings = this.getCastedSettings();
892
- this.fillSettings(castedSettings);
893
- this.fillSpecificSettings(castedSettings);
894
- this.ChartService = this.graphicate(castedSettings);
895
- this.Chart = this.ChartService.ChartInstance;
896
- if (!this.Chart)
897
- this.log("Chart " + this.name + ": Could not create graph");
898
- return this.Charter.applyLocale(this.Chart, this.Locale).then(() => { this.initDone = true; this.chartLoaded.emit(this); });
899
- })
900
- ]);
807
+ /** @ignore */
808
+ processOut() {
809
+ this.ChartInstance.series.each((series, i) => {
810
+ series.zIndex = i;
811
+ let fill = series.fillOpacity == this.OpacityOnFill;
812
+ series.segments.each((segment) => {
813
+ segment.setState("default");
814
+ if (!fill)
815
+ segment.fillSprite.fillOpacity = 0;
816
+ });
817
+ if (!fill)
818
+ series.legendDataItem.marker.children.getIndex(1).fillOpacity = 0;
819
+ });
820
+ }
821
+ /** @ignore */
822
+ throttla(id, func, throttleTime) {
823
+ //Se ho la funzione che vuole eseguire ripulisco quel timeout
824
+ if (this.executionTimers[id])
825
+ clearTimeout(this.executionTimers[id]);
826
+ //Ricreo il timeout per eseguire quella funzione dopo throttleTime millisecondi
827
+ this.executionTimers[id] = setTimeout(() => { func(); this.executionTimers[id] = null; }, throttleTime);
901
828
  }
829
+ }
830
+
831
+ /**
832
+ * Classe che si occupa del dispatch delle operazioni di rendering dei grafici utilizzando una coda per permettere ad ogni grafico di avere temi e localizzazione custom
833
+ */
834
+ class ChartDispatcher {
902
835
  /**
903
- * Riempimento delle impostazioni nella classe Settings. Si danno priorità ai valori già impostati nei Settings,
904
- * integrando eventualmente con le proprietà del grafico
905
- *
906
- * @param {BaseSettings} settings Impostazioni base ricevute dalla specializzazione del grafico
836
+ * @ignore
907
837
  */
908
- fillSettings(settings) {
909
- // Merge degli Input con i Settings, dando priorità ai Settings
910
- settings.Theme = settings.Theme ? settings.Theme : this.Theme;
911
- settings.Locale = settings.Locale ? settings.Locale : this.Locale;
912
- settings.Animations = settings.Animations != null ? settings.Animations : this.Animations;
913
- settings.Legend = settings.Legend != null ? settings.Legend : this.Legend;
914
- settings.Name = settings.Name ? settings.Name : this.name;
915
- settings.Timeline = settings.Timeline != null ? settings.Timeline : this.Timeline;
916
- settings.AdaptLabelSizeAndOrientation = settings.AdaptLabelSizeAndOrientation != null ? settings.AdaptLabelSizeAndOrientation : this.AdaptLabelSizeAndOrientation;
917
- settings.XAxisTitle = settings.XAxisTitle ? settings.XAxisTitle : this.XTitle;
918
- settings.YAxisTitle = settings.YAxisTitle ? settings.YAxisTitle : this.YTitle;
919
- settings.LegendPosition = settings.LegendPosition ? settings.LegendPosition : this.LegendPosition;
920
- settings.HideSeriesOnLabelClick = settings.HideSeriesOnLabelClick != null ? settings.HideSeriesOnLabelClick : this.HideSeriesOnLabelClick;
921
- settings.MinGridDistance = settings.MinGridDistance != null ? settings.MinGridDistance : this.MinGridDistance;
922
- settings.LegendPadding = settings.LegendPadding ? settings.LegendPadding : this.LegendPadding ?? null;
923
- settings.ContainerHeight = this.el.nativeElement.parentElement.offsetHeight;
924
- settings.OnSeriesClickCallback = (series) => { this.onSeriesClicked.emit(series); };
925
- settings.OnSelectionChangedCallback = (event) => { this.onSelectionChanged.emit({ from: event.from, to: event.to, initial: event.initial }); };
838
+ constructor(logs) {
839
+ this.logs = logs;
840
+ /**
841
+ * Coda di inizializzazioni ancora da eseguire. Quando questa è vuota significa che nessuno sta creando grafici
842
+ */
843
+ this.Initializations = [];
844
+ /**
845
+ * Lista dei grafici inizializzati e attivi in un dato momento (viene registrata la proprietà **name**). Non è possibile registrare due grafici con lo stesso identificativo
846
+ */
847
+ this.InitializedGraphs = [];
926
848
  }
927
849
  /**
928
- * Controlla i cambiamenti avvenuti alle proprietà chiave e rieffettua la graficazione qualora necessario
850
+ * Registra un grafico da visualizzare insieme alla propria funzione di creazione. Quest'ultima sarà differita fino a che tutti i grafici
851
+ * precedentemente registati non hanno finito la fase di inizializzazione
929
852
  *
930
- * @param {SimpleChanges} changes Indicazione della modifiche avvenute nei vari Input
931
- * @param {string[]} propsToCheck Lista degli Input da controllare per cui una modifica causa una rigraficazione
853
+ * @param {string} name Identificativo del grafico da registrare
854
+ * @param {Function} chartCreationFunction Funzione che fisicamente dovrà occuparsi della creazione del grafico
932
855
  */
933
- checkPropertiesAndRegraphicateAsNeeded(changes, propsToCheck) {
934
- let toReGraphicate = false;
935
- for (let i = 0; i < propsToCheck.length; i++)
936
- toReGraphicate = toReGraphicate || (changes[propsToCheck[i]] && changes[propsToCheck[i]].currentValue);
937
- if (toReGraphicate)
938
- this.reloadChart();
856
+ register(name, chartCreationFunction) {
857
+ if (this.InitializedGraphs.indexOf(name) != -1)
858
+ throw "Attempting to register a duplicate chart '" + name + "'. Make sure the 'name' properties of your charts are univoque";
859
+ this.log("DISPATCHER: Registering chart creation function execution for " + name);
860
+ this.Initializations.push({ name: name, function: chartCreationFunction });
861
+ if (this.Initializations.length == 1) {
862
+ this.log("DISPATCHER: Initial drain started");
863
+ this.drainInitQueues();
864
+ }
939
865
  }
940
866
  /**
941
- * Funzione che effettua un cambio di pagina per i grafici paginati. Qualora **data** fosse nullo significa che è iniziato un caricamento
942
- * e anche lato applicativo il DataRetrieve dovrà considerare che l'assenza di valori non è altro che un'indicazione di inizio caricamento
943
- *
944
- * Il caricamento di qualsiasi pagina genererà comunque una primo evento con **data** nullo in modo da indicare l'inizio caricamento e
945
- * in seconda istanza un altro evento in cui **data** sarà sempre valorizzato, o con il Dto da usare per recuperare i dati, o con i dati
946
- * veri e propri già presenti nel **DataArray**
947
- *
948
- * I callback **onLoadStart** e **onLoadEnd** vengono sempre chiamati
867
+ * Deregistra un grafico presente. Chiamata generalmente al dispose del grafico in questione quando non dev'essere più mostrato nella pagina corrente
949
868
  *
950
- * @param {{ data: LineChartData | PieChartData | Vertical2DChartData | VerticalChartData | any, index: number }} nd Indice del caricamento dati, con eventualmente già i dati se disponibili
869
+ * @param {string} name Identificativo del grafico da deregistrare
951
870
  */
952
- changePage(nd) {
953
- if (!nd.data) {
954
- this.loadingChart = true;
955
- // Serve per informare l'applicativo in listening sull'indice attualmente in visualizzazione.
956
- // La mancanza di dati indica che non devono essere effettuate ricerche per ora
957
- if (this.DataRetrieve)
958
- this.DataRetrieve(null, nd.index);
959
- this.onLoadStart.emit();
871
+ deregisterGraph(name) {
872
+ let index = this.InitializedGraphs.indexOf(name);
873
+ if (index == -1) {
874
+ //Questo succede quando si cerca di distruggere il grafico mentre sta venendo graficato
875
+ this.log("DISPATCHER: Registration missing for chart " + name + " it was probably destroyed during load");
960
876
  return;
961
877
  }
962
- if (this.DataRetrieve)
963
- this.DataRetrieve(nd.data, nd.index).then(t => { this.changePageDataReceived(t); });
964
- else
965
- this.changePageDataReceived(nd.data);
878
+ this.log("DISPATCHER: Chart deregistered " + name);
879
+ this.InitializedGraphs.splice(index, 1);
966
880
  }
967
881
  /**
968
- * Al termine del caricamento dei dati di una pagina questo metodo viene chiamato per rigraficare la situazione con i nuovi dati
882
+ * Metodo che esegue in maniera sequenziale le funzioni di inizializzazione dei grafici finché presenti
883
+ * in modo che nessun grafico possa essere inizializzato contemporaneamente ad un altro.
969
884
  *
970
- * @param {LineChartData | PieChartData | Vertical2DChartData | VerticalChartData | any} data Dati del grafico
885
+ * Questo è il punto chiave che permette di avere per ogni grafico temi e locale differenti
971
886
  */
972
- changePageDataReceived(data) {
973
- this.loadingChart = false;
974
- this.onLoadEnd.emit();
975
- let firstBind = !this.Data;
976
- this.Data = data;
977
- if (!firstBind)
978
- this.reloadChart();
979
- else
980
- this.dispatchLoadChart();
887
+ drainInitQueues() {
888
+ let toExecute = this.Initializations[0];
889
+ this.log("DISPATCHER: Executing initialization function for chart " + toExecute.name);
890
+ toExecute.function().then(() => {
891
+ this.log("DISPATCHER: initialization for chart " + toExecute.name + " is done");
892
+ this.InitializedGraphs.push(toExecute.name);
893
+ this.Initializations.splice(0, 1);
894
+ if (this.Initializations.length >= 1) {
895
+ this.log("DISPATCHER: Found queued initializations. Continuing");
896
+ this.drainInitQueues();
897
+ }
898
+ else
899
+ this.log("DISPATCHER: queue is over, nothing more to do");
900
+ });
981
901
  }
982
902
  /**
983
- * Ricarica il grafico distruggendo il vecchio e ricreando il nuovo
984
- *
985
- * Le chiamate a questo metodo possono essere trasformate in chiamate al metodo **graphicate** della Service, se solo quel metodo fosse abbastanza intelligente per capire
986
- * le differenze fra il grafico com'era prima e come deve diventare, in modo da non ricrearlo ma semplicemente modificare quello che già è disegnato
903
+ * @ignore
987
904
  */
988
- reloadChart() {
989
- this.browserOnly(() => { if (!this.Chart.isDisposed())
990
- this.Chart.dispose(); this.Dispatcher.deregisterGraph(this.name); });
991
- this.Dispatcher.register(this.name, () => { return this.loadChart(); });
905
+ log(text) {
906
+ if (this.logs)
907
+ console.log("@esfaenza/es-charts: " + text);
992
908
  }
909
+ }
910
+ ChartDispatcher.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartDispatcher, deps: [{ token: ESC_LOGS }], target: i0.ɵɵFactoryTarget.Injectable });
911
+ ChartDispatcher.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartDispatcher, providedIn: 'root' });
912
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartDispatcher, decorators: [{
913
+ type: Injectable,
914
+ args: [{ providedIn: 'root' }]
915
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
916
+ type: Inject,
917
+ args: [ESC_LOGS]
918
+ }] }]; } });
919
+
920
+ /**
921
+ * Componente specifico per la graficazione di un grafico a Linea su un asse temporale
922
+ */
923
+ class EsLineChartComponent extends BaseChartComponent {
993
924
  /**
994
- * Permette di aggiungere un blocco di dati in maniera "live" ad un grafico
925
+ * @ignore
995
926
  */
996
- addData(chartData) {
997
- this.ChartService.refreshData(chartData);
927
+ constructor(el, ChartLoader, ChartDispatcher, adapter, dateService, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_THEME, lc) {
928
+ super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, lc.Locale, ESC_THEME);
929
+ this.adapter = adapter;
930
+ this.dateService = dateService;
998
931
  }
999
- ;
1000
932
  /**
1001
- * Funzione che si occupa di caricare i temi necessari per il grafico in oggetto. Prima applica il tema, poi, se serve, applica le animazioni
933
+ * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
1002
934
  */
1003
- setupAmChartsThemes() {
1004
- return Promise.all([
1005
- this.Charter.applyTheme(am4core, this.Theme).then(() => {
1006
- return this.Animations ? this.Charter.applyAnimations(am4core) : this.Charter.unapplyAnimations(am4core);
1007
- })
1008
- ]);
935
+ getSpecificPropertiesToCheck() {
936
+ return ["Data", "DataArray", "Step", "DataGroupBucketSize", "DataGroupingThreshold", "StrokeSize", "Stacked", "AllowGaps", "MergeDatasets", "FinalInstants", "Fill", "Min", "Max"];
1009
937
  }
1010
938
  /**
1011
- * @ignore
939
+ * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
940
+ *
941
+ * @returns {LineChartSettings} Settings castati al tipo giusto
1012
942
  */
1013
- log(log) {
1014
- if (this.logs)
1015
- console.log("@esfaenza/es-charts: " + log);
943
+ getCastedSettings() {
944
+ return (this.Settings ?? new LineChartSettings());
1016
945
  }
1017
946
  /**
1018
- * Imposta lo zoom dal **from** al **to**
947
+ * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
1019
948
  *
1020
- * @param {Date} from Inizio dello zoom
1021
- * @param {Date} to Fine dello zoom
949
+ * @param {LineChartSettings} settingsCasted Settings castati al tipo giusto
1022
950
  */
1023
- setSelection(from, to) {
1024
- this.ChartService.setSelection(from, to);
951
+ fillSpecificSettings(settingsCasted) {
952
+ settingsCasted.Step = settingsCasted.Step != null ? settingsCasted.Step : this.Step;
953
+ settingsCasted.DataGroupBucketSize = settingsCasted.DataGroupBucketSize != null ? settingsCasted.DataGroupBucketSize : this.DataGroupBucketSize;
954
+ settingsCasted.StrokeSize = settingsCasted.StrokeSize != null ? settingsCasted.StrokeSize : this.StrokeSize;
955
+ settingsCasted.DataGroupingThreshold = settingsCasted.DataGroupingThreshold != null ? settingsCasted.DataGroupingThreshold : this.DataGroupingThreshold;
956
+ settingsCasted.AllowGaps = settingsCasted.AllowGaps != null ? settingsCasted.AllowGaps : this.AllowGaps;
957
+ settingsCasted.MergeDatasets = settingsCasted.MergeDatasets != null ? settingsCasted.MergeDatasets : this.MergeDatasets;
958
+ settingsCasted.FinalInstants = settingsCasted.FinalInstants != null ? settingsCasted.FinalInstants : this.FinalInstants;
959
+ settingsCasted.Min = settingsCasted.Min != null ? settingsCasted.Min : this.Min;
960
+ settingsCasted.Max = settingsCasted.Max != null ? settingsCasted.Max : this.Max;
961
+ settingsCasted.Fill = settingsCasted.Fill != null ? settingsCasted.Fill : this.Fill;
962
+ settingsCasted.Stacked = settingsCasted.Stacked != null ? settingsCasted.Stacked : this.Stacked;
1025
963
  }
1026
964
  /**
1027
- * @ignore
965
+ * Effettua il rendering di questo grafico in base ai Settings
966
+ *
967
+ * @param {LineChartSettings} settingsCasted Impostazioni di graficazione
968
+ * @returns {LineChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
1028
969
  */
1029
- browserOnly(f) {
1030
- if (isPlatformBrowser(this.platformId)) {
1031
- this.zone.runOutsideAngular(() => {
1032
- f();
1033
- });
1034
- }
970
+ graphicate(settingsCasted) {
971
+ return new LineChartService(this.adapter, this.dateService).graphicate(this.Data, settingsCasted);
1035
972
  }
1036
973
  }
1037
- BaseChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseChartComponent, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
1038
- BaseChartComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: BaseChartComponent, inputs: { XTitle: "XTitle", YTitle: "YTitle", Settings: "Settings", Legend: "Legend", LegendPosition: "LegendPosition", Timeline: "Timeline", name: "name", Animations: "Animations", Theme: "Theme", Locale: "Locale", HideSeriesOnLabelClick: "HideSeriesOnLabelClick", MinGridDistance: "MinGridDistance", AdaptLabelSizeAndOrientation: "AdaptLabelSizeAndOrientation", LegendPadding: "LegendPadding", DataDtos: "DataDtos", DataDtoStartIndex: "DataDtoStartIndex", DataRetrieve: "DataRetrieve", BrowseDelayMs: "BrowseDelayMs" }, outputs: { onSelectionChanged: "onSelectionChanged", onSeriesClicked: "onSeriesClicked", onLoadStart: "onLoadStart", onLoadEnd: "onLoadEnd", chartLoaded: "chartLoaded" }, queries: [{ propertyName: "header_tr", first: true, predicate: ["header"], descendants: true }, { propertyName: "loading_template", first: true, predicate: ["loading"], descendants: true }], usesOnChanges: true, ngImport: i0 });
1039
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseChartComponent, decorators: [{
1040
- type: Directive
1041
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: Object }, { type: i0.NgZone }, { type: ChartLoader }, { type: ChartDispatcher }, { type: undefined }, { type: undefined }, { type: undefined }, { type: undefined }]; }, propDecorators: { XTitle: [{
1042
- type: Input
1043
- }], YTitle: [{
1044
- type: Input
1045
- }], Settings: [{
1046
- type: Input
1047
- }], Legend: [{
1048
- type: Input
1049
- }], LegendPosition: [{
1050
- type: Input
1051
- }], Timeline: [{
974
+ EsLineChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsLineChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i4.DateService }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_THEME }, { token: i4$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
975
+ EsLineChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsLineChartComponent, selector: "es-line-chart", inputs: { Data: "Data", DataArray: "DataArray", Step: "Step", DataGroupBucketSize: "DataGroupBucketSize", DataGroupingThreshold: "DataGroupingThreshold", StrokeSize: "StrokeSize", AllowGaps: "AllowGaps", MergeDatasets: "MergeDatasets", FinalInstants: "FinalInstants", Min: "Min", Max: "Max", Fill: "Fill", Stacked: "Stacked" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
976
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsLineChartComponent, decorators: [{
977
+ type: Component,
978
+ args: [{ selector: 'es-line-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
979
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i4.DateService }, { type: i0.NgZone }, { type: Object, decorators: [{
980
+ type: Inject,
981
+ args: [PLATFORM_ID]
982
+ }] }, { type: undefined, decorators: [{
983
+ type: Inject,
984
+ args: [ESC_LOGS]
985
+ }] }, { type: undefined, decorators: [{
986
+ type: Inject,
987
+ args: [ESC_ANIMATIONS]
988
+ }] }, { type: undefined, decorators: [{
989
+ type: Inject,
990
+ args: [ESC_THEME]
991
+ }] }, { type: i4$1.LocalizationService }]; }, propDecorators: { Data: [{
1052
992
  type: Input
1053
- }], name: [{
993
+ }], DataArray: [{
1054
994
  type: Input
1055
- }], Animations: [{
995
+ }], Step: [{
1056
996
  type: Input
1057
- }], Theme: [{
997
+ }], DataGroupBucketSize: [{
1058
998
  type: Input
1059
- }], Locale: [{
999
+ }], DataGroupingThreshold: [{
1060
1000
  type: Input
1061
- }], HideSeriesOnLabelClick: [{
1001
+ }], StrokeSize: [{
1062
1002
  type: Input
1063
- }], MinGridDistance: [{
1003
+ }], AllowGaps: [{
1064
1004
  type: Input
1065
- }], AdaptLabelSizeAndOrientation: [{
1005
+ }], MergeDatasets: [{
1066
1006
  type: Input
1067
- }], LegendPadding: [{
1007
+ }], FinalInstants: [{
1068
1008
  type: Input
1069
- }], DataDtos: [{
1009
+ }], Min: [{
1070
1010
  type: Input
1071
- }], DataDtoStartIndex: [{
1011
+ }], Max: [{
1072
1012
  type: Input
1073
- }], DataRetrieve: [{
1013
+ }], Fill: [{
1074
1014
  type: Input
1075
- }], BrowseDelayMs: [{
1015
+ }], Stacked: [{
1076
1016
  type: Input
1077
- }], header_tr: [{
1078
- type: ContentChild,
1079
- args: ['header', { static: false }]
1080
- }], loading_template: [{
1081
- type: ContentChild,
1082
- args: ['loading', { static: false }]
1083
- }], onSelectionChanged: [{
1084
- type: Output
1085
- }], onSeriesClicked: [{
1086
- type: Output
1087
- }], onLoadStart: [{
1088
- type: Output
1089
- }], onLoadEnd: [{
1090
- type: Output
1091
- }], chartLoaded: [{
1092
- type: Output
1093
1017
  }] } });
1094
1018
 
1095
1019
  /**
1096
- * Classe il cui unico scopo è gestire il setup e rendering di un LineChart
1020
+ * Classe il cui unico scopo è gestire il setup e rendering di un AreaChart
1097
1021
  */
1098
- class LineChartService {
1022
+ class AreaChartService {
1099
1023
  /** @ignore */
1100
- constructor(Adapter, dateExts) {
1024
+ constructor(Adapter) {
1101
1025
  this.Adapter = Adapter;
1102
- this.dateExts = dateExts;
1103
- /** @ignore */
1104
- this.DataGroupBucketSize = 1500;
1105
- /** @ignore */
1106
- this.OpacityOnSelected = 0.3;
1107
- /** @ignore */
1108
- this.OpacityOnFill = 0.75;
1109
- /** @ignore */
1110
- this.singleDataSet = false;
1111
1026
  //******************** Funzione di throttling per non spammare richieste in caso di animazioni attivate
1112
1027
  //TODO: spostarla in un metodo di utilità (esfaenza/extensions)
1113
1028
  /** @ignore */
1114
1029
  this.executionTimers = {};
1115
1030
  }
1116
1031
  /**
1117
- * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un LineChart
1032
+ * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un AreaChart
1118
1033
  */
1119
1034
  graphicate(data, settings) {
1120
- let dataConverted = this.Adapter ? this.Adapter.adaptDataForLineChart(data) : data;
1121
- let threshold = settings.DataGroupingThreshold ?? 3000;
1122
- this.singleDataSet = settings.MergeDatasets ?? false;
1035
+ if (settings.Timeline) {
1036
+ console.error("Timeline not supported for area chart");
1037
+ return null;
1038
+ }
1039
+ let dataConverted = this.Adapter ? this.Adapter.adaptDataForAreaChart(data) : data;
1123
1040
  let showTicks = settings.ShowTicks == null ? true : settings?.ShowTicks;
1124
- let dataShouldBeGrouped = Math.max(...dataConverted.series.map(t => t.values.length)) > threshold;
1125
- let showTimeline = settings.Timeline || dataShouldBeGrouped;
1126
- let seriesWithInterval = dataConverted.series.some(t => t.interval);
1127
- let interval = seriesWithInterval ? dataConverted.series.find(t => t.interval).interval : null;
1128
- let gapsAllowed = settings?.AllowGaps == null ? seriesWithInterval : settings?.AllowGaps;
1129
- let finalInstant = settings?.FinalInstants ?? true;
1041
+ let interval = dataConverted.interval;
1130
1042
  //Per evitare di dimenticarmeli e gestire comunque bene gli ngif ecc...
1131
1043
  am4core.options.autoDispose = true;
1132
1044
  this.ChartInstance = am4core.create(settings.Name, am4charts.XYChart);
1133
1045
  let ChartInstanceCasted = this.ChartInstance;
1134
- let yAxis = ChartInstanceCasted.yAxes.push(new am4charts.ValueAxis());
1135
- if (settings.YAxisTitle) {
1136
- yAxis.title.text = settings.YAxisTitle;
1137
- yAxis.title.fontWeight = "bold";
1138
- }
1139
- if (settings.Min)
1140
- yAxis.min = settings.Min;
1141
- if (settings.Max)
1142
- yAxis.max = settings.Max;
1143
- let limitNullOrUndef = dataConverted.limit == null || dataConverted.limit == undefined;
1144
- let limits = limitNullOrUndef ? [] : !dataConverted.limit.length ? [dataConverted.limit] : dataConverted.limit;
1145
- if (limits.length > 0) {
1146
- for (let i = 0; i < limits.length; i++) {
1147
- let limit = limits[i];
1148
- if (limit.upper != null && limit.upper != undefined && limit.lower != null && limit.lower != undefined) {
1149
- let range = yAxis.axisRanges.create();
1150
- range.value = limit.lower;
1151
- range.endValue = limit.upper;
1152
- if (limit.fillColor) {
1153
- range.contents.stroke = am4core.color(limit.fillColor);
1154
- range.contents.fill = range.contents.stroke;
1155
- }
1156
- range.label.inside = true;
1157
- range.label.text = limit.upperlabel;
1158
- range.label.fill = range.grid.stroke;
1159
- range.label.verticalCenter = "bottom";
1160
- range.label.stroke = am4core.color(limit.uppercolor || "#F92200");
1161
- range.grid.stroke = am4core.color(limit.uppercolor || "#F92200");
1162
- range.grid.strokeWidth = 2;
1163
- range.grid.strokeOpacity = 1;
1164
- }
1165
- else if ((limit.lower == null || limit.lower == undefined) && limit.upper != null && limit.upper != undefined) {
1166
- let range = yAxis.axisRanges.create();
1167
- range.value = limit.upper;
1168
- range.label.inside = true;
1169
- range.label.text = limit.upperlabel;
1170
- range.label.fill = range.grid.stroke;
1171
- range.label.verticalCenter = "bottom";
1172
- range.label.stroke = am4core.color(limit.uppercolor || "#F92200");
1173
- range.grid.stroke = am4core.color(limit.uppercolor || "#F92200");
1174
- range.grid.strokeWidth = 2;
1175
- range.grid.strokeOpacity = 1;
1176
- }
1177
- else if ((limit.upper == null || limit.upper == undefined) && limit.lower != null && limit.lower != undefined) {
1178
- let range = yAxis.axisRanges.create();
1179
- range.value = limit.lower;
1180
- range.label.inside = true;
1181
- range.label.text = limit.lowerlabel;
1182
- range.label.fill = range.grid.stroke;
1183
- range.label.verticalCenter = "bottom";
1184
- range.label.stroke = am4core.color(limit.lowercolor || "#F92200");
1185
- range.grid.stroke = am4core.color(limit.lowercolor || "#F92200");
1186
- range.grid.strokeWidth = 2;
1187
- range.grid.strokeOpacity = 1;
1188
- }
1189
- }
1190
- }
1191
- this.dateAxis = ChartInstanceCasted.xAxes.push(new am4charts.DateAxis());
1192
- // Per comatibilità col codice scritto quando non era a livello globale, mi scoccia sostituire
1193
- let dateAxis = this.dateAxis;
1194
- if (settings.XAxisTitle) {
1195
- dateAxis.title.text = settings.XAxisTitle;
1196
- dateAxis.title.fontWeight = "bold";
1197
- }
1198
- if (showTicks) {
1199
- dateAxis.renderer.ticks.template.disabled = false;
1200
- dateAxis.renderer.ticks.template.strokeOpacity = 1;
1201
- dateAxis.renderer.ticks.template.stroke = am4core.color("#495C43");
1202
- dateAxis.renderer.ticks.template.strokeWidth = 2;
1203
- dateAxis.renderer.ticks.template.length = 10;
1204
- dateAxis.renderer.ticks.template.location = 0;
1205
- }
1206
- dateAxis.renderer.minGridDistance = settings?.MinGridDistance ?? 50;
1207
- dateAxis.renderer.grid.template.location = 0;
1208
- dateAxis.minZoomCount = 5;
1209
- dateAxis.groupData = dataShouldBeGrouped;
1210
- dateAxis.groupCount = settings.DataGroupBucketSize ?? this.DataGroupBucketSize;
1211
- //Se ho almeno una serie ad intervallo e i settings non mi impediscono esplicitamente di usare i gaps, visualizzo i dati col gap
1212
- if (gapsAllowed) {
1213
- if (!seriesWithInterval) {
1214
- console.error("Per utilizzare la funzionalità dei gap è obbligatorio definire un intervallo nelle serie del grafico");
1215
- return null;
1216
- }
1217
- dateAxis.baseInterval = { count: interval.count, timeUnit: interval.timeunit };
1218
- }
1219
- if (showTimeline)
1220
- ChartInstanceCasted.scrollbarX = new am4charts.XYChartScrollbar();
1221
- let seriesToPush = [];
1222
- let seriesColors = [];
1223
- let defaultIndex = 0;
1224
- // Ordinamento dei dati se serve
1225
- dataConverted.series.forEach((s) => {
1226
- if (s.values[0] && !(s.values[0].d instanceof Date)) {
1227
- for (let v = 0; v < s.values.length; v++)
1228
- s.values[v].d = new Date(s.values[v].d);
1229
- }
1230
- var correctOrder = true;
1231
- var prevDate = null;
1232
- for (let v = 0; v < s.values.length; v++) {
1233
- if (!prevDate)
1234
- prevDate = s.values[v].d;
1235
- else if (s.values[v].d < prevDate) {
1236
- correctOrder = false;
1237
- break;
1238
- }
1239
- }
1240
- if (!correctOrder)
1241
- s.values.sort((d1, d2) => d1.d.getTime() - d2.d.getTime());
1242
- });
1243
- // Generazione di un unico dataset invece che N, per poter gestire un unico tooltip
1244
- if (this.singleDataSet) {
1245
- this.ChartInstance.data = this.generateSingleDataset(dataConverted);
1246
- ;
1247
- dateAxis.cursorTooltipEnabled = false;
1248
- }
1249
- dataConverted.series.forEach((s, index) => {
1250
- let stacked = s.stacked != null && s.stacked != undefined ? s.stacked : (settings?.Stacked ?? false);
1251
- let fill = stacked || (s.fill != null && s.fill != undefined ? s.fill : (settings?.Fill ?? false));
1252
- let series = settings?.Step ? new am4charts.StepLineSeries() : new am4charts.LineSeries();
1253
- series.dataFields.valueY = "v" + (this.singleDataSet ? index : "");
1254
- series.dataFields.dateX = "d";
1255
- series.measureUnit = s.uom;
1256
- series.name = s.name;
1257
- series.strokeWidth = settings?.StrokeSize ?? 1;
1258
- series.connect = !gapsAllowed;
1259
- series.minBulletDistance = 10;
1260
- series.tooltipText = this.singleDataSet ? "" : s.name ? "{name}: [bold]{valueY}[/]" : "[bold]{valueY}[/]";
1261
- series.tooltip.pointerOrientation = "vertical";
1262
- series.tooltip.background.fillOpacity = 0.5;
1263
- series.tooltip.label.padding(12, 12, 12, 12);
1264
- series.fillOpacity = fill ? this.OpacityOnFill : 0.0001;
1265
- series.stacked = stacked;
1266
- series.hidden = s.hidden;
1267
- //Dataset singolo, i dati sono registrati a livello di chart, creo il tooltip che permette di vederli tutti insieme
1268
- //altrimenti assegno i dati della serie direttamente alla serie
1269
- if (this.singleDataSet) {
1270
- series.tooltip.getFillFromObject = false;
1271
- series.tooltip.background.fill = am4core.color("#eee");
1272
- series.tooltip.label.fill = am4core.color("#00");
1273
- series.tooltip.defaultState.transitionDuration = 0;
1274
- series.tooltip.hiddenState.transitionDuration = 0;
1275
- //Utilizzo il mio dateService per la formattazione della data in modo che non debba mai gestire n formati fra n librerie... bellissimo
1276
- series.dateFormatter.format = (source) => {
1277
- if (interval && finalInstant && ["hour", "minute", "second"].includes(interval.timeunit)) {
1278
- let timepart = null;
1279
- switch (interval.timeunit) {
1280
- case "hour":
1281
- timepart = 'day';
1282
- break;
1283
- case "minute":
1284
- timepart = 'hour';
1285
- break;
1286
- case "second":
1287
- timepart = 'minute';
1288
- break;
1289
- }
1290
- if (timepart)
1291
- return this.dateExts.adjustDateToFinalInstant(source, timepart, interval ? interval.timeunit == "second" : false);
1292
- }
1293
- else
1294
- return this.dateExts.getFormatted(source, interval ? ["day", "week", "month", "year"].includes(interval.timeunit) : false, interval ? interval.timeunit == "second" : false);
1295
- };
1296
- series.adapter.add("tooltipText", () => {
1297
- var text = "[bold]{dateX.formatDate()}[/]\n";
1298
- this.ChartInstance.series.each((item) => {
1299
- let uom = " [font-style: italic]" + series.measureUnit || "" + "[/]";
1300
- text += "[" + item.stroke.hex + "]●[/] " + (item.name ? (item.name + ": ") : "") + "[bold]{" + item.dataFields.valueY + "}[/]" + uom + "\n";
1301
- });
1302
- return text;
1303
- });
1304
- }
1305
- else
1306
- series.data = s.values;
1307
- let segment = series.segments.template;
1308
- let hoverState = segment.states.create("hover");
1309
- hoverState.properties.strokeWidth = (settings?.StrokeSize ?? 1) + 1;
1310
- let dimmed = segment.states.create("dimmed");
1311
- dimmed.properties.stroke = am4core.color("#dadada");
1312
- //Se la serie ha un colore, uso quello, altrimenti pesco dai colori di default andando in ordine
1313
- if (s.color)
1314
- seriesColors.push(am4core.color(s.color));
1315
- else {
1316
- seriesColors.push(ChartInstanceCasted.colors.list[defaultIndex % ChartInstanceCasted.colors.list.length]);
1317
- defaultIndex++;
1318
- }
1319
- seriesToPush.push(series);
1320
- });
1321
- ChartInstanceCasted.colors.list = seriesColors;
1322
- //Scrivo le serie nel grafico
1323
- seriesToPush.forEach(s => {
1324
- ChartInstanceCasted.series.push(s);
1325
- if (showTimeline)
1326
- ChartInstanceCasted.scrollbarX.series.push(s);
1327
- });
1328
1046
  if (settings.Legend) {
1329
- this.ChartInstance.legend = new am4charts.Legend();
1330
- this.ChartInstance.legend.position = settings?.LegendPosition ?? 'right';
1331
- this.ChartInstance.legend.scrollable = true;
1332
- this.ChartInstance.legend.itemContainers.template.tooltipText = "{name}";
1333
- this.ChartInstance.legend.itemContainers.template.events.on("over", (event) => { this.processOver(event.target.dataItem.dataContext); });
1334
- this.ChartInstance.legend.itemContainers.template.events.on("out", () => { this.processOut(); });
1047
+ ChartInstanceCasted.legend = new am4charts.Legend();
1048
+ ChartInstanceCasted.legend.position = settings?.LegendPosition ?? 'right';
1049
+ ChartInstanceCasted.legend.itemContainers.template.tooltipText = "{category}";
1335
1050
  if (settings.LegendPadding) {
1336
1051
  let template = this.ChartInstance.legend.itemContainers.template;
1337
1052
  template.paddingTop = settings.LegendPadding.top ?? 0;
@@ -1340,69 +1055,63 @@ class LineChartService {
1340
1055
  template.paddingRight = settings.LegendPadding.right ?? 0;
1341
1056
  }
1342
1057
  }
1343
- this.ChartInstance.cursor = new am4charts.XYCursor();
1344
- //Prove******************************************************************************************************************************
1345
- // this.ChartInstance.cursor.events.on("cursorpositionchanged", (ev) => {
1346
- // //var value = dateAxis.positionToDate(dateAxis.toAxisPosition(ev.target.xPosition));
1347
- // var dt = dateAxis.series.values.find(t => t.dataItem.values.dateX);
1348
- // if (dt && dt.dataItem) {
1349
- // console.log(dt.dataItem.values);
1350
- // // this.ChartInstance.tooltipText = dt;
1351
- // }
1352
- // else {
1353
- // this.ChartInstance.tooltipText = "";
1354
- // }
1355
- // });
1356
- //******************************************************************************************************************************
1357
- this.ChartInstance.cursor.xAxis = dateAxis;
1358
- this.ChartInstance.cursor.yAxis = yAxis;
1359
- if (this.singleDataSet)
1360
- this.ChartInstance.cursor.maxTooltipDistance = -1;
1361
- //TODO: Cercare di capire perché è figlio di puttana......
1058
+ let yAxis = ChartInstanceCasted.yAxes.push(new am4charts.ValueAxis());
1059
+ yAxis.tooltip.disabled = true;
1060
+ if (settings.YAxisTitle) {
1061
+ yAxis.title.text = settings.YAxisTitle;
1062
+ yAxis.title.fontWeight = "bold";
1063
+ }
1064
+ yAxis.min = 0;
1065
+ let dateAxis = ChartInstanceCasted.xAxes.push(new am4charts.DateAxis());
1066
+ dateAxis.renderer.minGridDistance = settings?.MinGridDistance ?? 50;
1067
+ dateAxis.startLocation = 0.5;
1068
+ dateAxis.endLocation = 0.5;
1069
+ if (settings.XAxisTitle) {
1070
+ dateAxis.title.text = settings.XAxisTitle;
1071
+ dateAxis.title.fontWeight = "bold";
1072
+ }
1073
+ if (showTicks) {
1074
+ dateAxis.renderer.ticks.template.disabled = false;
1075
+ dateAxis.renderer.ticks.template.strokeOpacity = 1;
1076
+ dateAxis.renderer.ticks.template.stroke = am4core.color("#495C43");
1077
+ dateAxis.renderer.ticks.template.strokeWidth = 2;
1078
+ dateAxis.renderer.ticks.template.length = 10;
1079
+ dateAxis.renderer.ticks.template.location = 0;
1080
+ }
1081
+ if (!!interval)
1082
+ dateAxis.baseInterval = { count: interval.count, timeUnit: interval.timeunit };
1083
+ // Unisco il dataset e tiro fuori i dati
1084
+ let chartData = [];
1085
+ let seriesToMakeCache = {};
1086
+ let seriesToMake = [];
1087
+ for (let i = 0; i < dataConverted.groups.length; i++) {
1088
+ let group = dataConverted.groups[i];
1089
+ let dataItem = { date: group.name };
1090
+ for (let ii = 0; ii < group.values.length; ii++) {
1091
+ let val = group.values[ii];
1092
+ dataItem[val.k] = val.v;
1093
+ if (!seriesToMakeCache[val.k]) {
1094
+ seriesToMakeCache[val.k] = true;
1095
+ seriesToMake.push(val.k);
1096
+ }
1097
+ }
1098
+ chartData.push(dataItem);
1099
+ }
1100
+ ChartInstanceCasted.data = chartData;
1101
+ //---------------------------------------------------------
1102
+ seriesToMake.forEach(s => { this.createSeries(ChartInstanceCasted, s); });
1103
+ ChartInstanceCasted.cursor = new am4charts.XYCursor();
1104
+ ChartInstanceCasted.cursor.xAxis = dateAxis;
1362
1105
  dateAxis.events.on("startchanged", t => this.emitSelectionChanged(t, settings));
1363
1106
  dateAxis.events.on("endchanged", t => this.emitSelectionChanged(t, settings));
1364
1107
  return this;
1365
1108
  }
1366
1109
  /** @ignore */
1367
1110
  setSelection(from, to) {
1368
- this.dateAxis.zoomToDates(from, to, true, true);
1369
1111
  }
1370
1112
  /** @ignore */
1371
1113
  refreshData(data) {
1372
- let dataConverted = this.Adapter ? this.Adapter.adaptDataForLineChart(data) : data;
1373
- if (this.singleDataSet) {
1374
- var data = this.generateSingleDataset(dataConverted);
1375
- this.ChartInstance.addData(data);
1376
- return;
1377
- }
1378
- throw "Impossibile aggiornare i dati senza unire il dataset. Si prega di impostare [MergeDatasets] a true";
1379
- }
1380
- /** Partendo da dati divisi per seriue genera un dataset unito con la data come chiave e i vari valori dopo */
1381
- generateSingleDataset(data) {
1382
- let dto = {};
1383
- data.series.forEach((vs, index) => {
1384
- for (let i = 0; i < vs.values.length; i++) {
1385
- var dataitem = vs.values[i];
1386
- var indexer = new Date(dataitem.d).valueOf();
1387
- if (!dto[indexer])
1388
- dto[indexer] = {};
1389
- dto[indexer]['v' + index] = dataitem.v;
1390
- }
1391
- });
1392
- var dates = Object.keys(dto);
1393
- var ret = [];
1394
- for (let i = 0; i < dates.length; i++) {
1395
- let values = dto[dates[i]];
1396
- let item = { d: new Date(parseInt(dates[i])) };
1397
- var vals = Object.keys(values);
1398
- for (let ii = 0; ii < vals.length; ii++) {
1399
- let series = vals[ii];
1400
- let singleVal = values[series];
1401
- item[series] = singleVal;
1402
- }
1403
- ret.push(item);
1404
- }
1405
- return ret;
1114
+ //TODO:IMPL
1406
1115
  }
1407
1116
  /** @ignore */
1408
1117
  emitSelectionChanged(ev, settings) {
@@ -1417,40 +1126,20 @@ class LineChartService {
1417
1126
  }
1418
1127
  }
1419
1128
  /** @ignore */
1420
- processOver(hoveredSeries) {
1421
- hoveredSeries.zIndex = 999;
1422
- let fill = hoveredSeries.fillOpacity == this.OpacityOnFill;
1423
- hoveredSeries.segments.each((segment) => {
1424
- segment.setState("hover");
1425
- if (!fill)
1426
- segment.fillSprite.fillOpacity = this.OpacityOnSelected;
1427
- });
1428
- if (!fill)
1429
- hoveredSeries.legendDataItem.marker.children.getIndex(1).fillOpacity = this.OpacityOnSelected;
1430
- this.ChartInstance.series.each((series) => {
1431
- if (series != hoveredSeries) {
1432
- let fill = series.fillOpacity == this.OpacityOnFill;
1433
- series.segments.each((segment) => {
1434
- segment.setState("dimmed");
1435
- if (!fill)
1436
- segment.fillSprite.fillOpacity = 0;
1437
- });
1438
- }
1439
- });
1440
- }
1441
- /** @ignore */
1442
- processOut() {
1443
- this.ChartInstance.series.each((series, i) => {
1444
- series.zIndex = i;
1445
- let fill = series.fillOpacity == this.OpacityOnFill;
1446
- series.segments.each((segment) => {
1447
- segment.setState("default");
1448
- if (!fill)
1449
- segment.fillSprite.fillOpacity = 0;
1450
- });
1451
- if (!fill)
1452
- series.legendDataItem.marker.children.getIndex(1).fillOpacity = 0;
1453
- });
1129
+ createSeries(chart, name) {
1130
+ let series = chart.series.push(new am4charts.LineSeries());
1131
+ series.dataFields.dateX = "date";
1132
+ series.name = name[0].toUpperCase() + name.slice(1);
1133
+ series.dataFields.valueY = name;
1134
+ series.tooltipText = "[#000]{valueY.value}[/]";
1135
+ //series.tooltip.background.fill = am4core.color("#FFF");
1136
+ series.tooltip.getStrokeFromObject = true;
1137
+ series.tooltip.background.strokeWidth = 3;
1138
+ series.tooltip.getFillFromObject = false;
1139
+ series.fillOpacity = 0.6;
1140
+ series.strokeWidth = 2;
1141
+ series.stacked = true;
1142
+ return series;
1454
1143
  }
1455
1144
  /** @ignore */
1456
1145
  throttla(id, func, throttleTime) {
@@ -1462,6 +1151,71 @@ class LineChartService {
1462
1151
  }
1463
1152
  }
1464
1153
 
1154
+ /**
1155
+ * Componente specifico per la graficazione di un grafico ad Area
1156
+ */
1157
+ class EsAreaChartComponent extends BaseChartComponent {
1158
+ /**
1159
+ * @ignore
1160
+ */
1161
+ constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_THEME, lc) {
1162
+ super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, lc.Locale, ESC_THEME);
1163
+ this.adapter = adapter;
1164
+ }
1165
+ /**
1166
+ * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
1167
+ */
1168
+ getSpecificPropertiesToCheck() {
1169
+ return ["Data", "DataArray"];
1170
+ }
1171
+ /**
1172
+ * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
1173
+ *
1174
+ * @returns {AreaChartSettings} Settings castati al tipo giusto
1175
+ */
1176
+ getCastedSettings() {
1177
+ return (this.Settings ?? new AreaChartSettings());
1178
+ }
1179
+ /**
1180
+ * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
1181
+ *
1182
+ * @param {AreaChartSettings} settingsCasted Settings castati al tipo giusto
1183
+ */
1184
+ fillSpecificSettings(settingsCasted) {
1185
+ }
1186
+ /**
1187
+ * Effettua il rendering di questo grafico in base ai Settings
1188
+ *
1189
+ * @param {AreaChartSettings} settingsCasted Impostazioni di graficazione
1190
+ * @returns {AreaChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
1191
+ */
1192
+ graphicate(settingsCasted) {
1193
+ return new AreaChartService(this.adapter).graphicate(this.Data, settingsCasted);
1194
+ }
1195
+ }
1196
+ EsAreaChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsAreaChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_THEME }, { token: i4$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
1197
+ EsAreaChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsAreaChartComponent, selector: "es-area-chart", inputs: { Data: "Data", DataArray: "DataArray" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1198
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsAreaChartComponent, decorators: [{
1199
+ type: Component,
1200
+ args: [{ selector: 'es-area-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
1201
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
1202
+ type: Inject,
1203
+ args: [PLATFORM_ID]
1204
+ }] }, { type: undefined, decorators: [{
1205
+ type: Inject,
1206
+ args: [ESC_LOGS]
1207
+ }] }, { type: undefined, decorators: [{
1208
+ type: Inject,
1209
+ args: [ESC_ANIMATIONS]
1210
+ }] }, { type: undefined, decorators: [{
1211
+ type: Inject,
1212
+ args: [ESC_THEME]
1213
+ }] }, { type: i4$1.LocalizationService }]; }, propDecorators: { Data: [{
1214
+ type: Input
1215
+ }], DataArray: [{
1216
+ type: Input
1217
+ }] } });
1218
+
1465
1219
  /**
1466
1220
  * Classe il cui unico scopo è gestire il setup e rendering di un PieChart
1467
1221
  */
@@ -1575,13 +1329,101 @@ class PieChartService {
1575
1329
  }
1576
1330
 
1577
1331
  /**
1578
- * Classe il cui unico scopo è gestire il setup e rendering di un VerticalChart
1332
+ * Componente specifico per la graficazione di un grafico a Torta
1333
+ */
1334
+ class EsPieChartComponent extends BaseChartComponent {
1335
+ /**
1336
+ * @ignore
1337
+ */
1338
+ constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_THEME, lc) {
1339
+ super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, lc.Locale, ESC_THEME);
1340
+ this.adapter = adapter;
1341
+ }
1342
+ /**
1343
+ * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
1344
+ */
1345
+ getSpecificPropertiesToCheck() {
1346
+ return ["Data", "DataArray", "HideZeroes", "Mode3D", "LabelsWrap", "LabelsTruncate", "LabelsWidth", "LabelsVisible"];
1347
+ }
1348
+ /**
1349
+ * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
1350
+ *
1351
+ * @returns {PieChartSettings} Settings castati al tipo giusto
1352
+ */
1353
+ getCastedSettings() {
1354
+ return (this.Settings ?? new PieChartSettings());
1355
+ }
1356
+ /**
1357
+ * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
1358
+ *
1359
+ * @param {PieChartSettings} settingsCasted Settings castati al tipo giusto
1360
+ */
1361
+ fillSpecificSettings(settingsCasted) {
1362
+ settingsCasted.HideZeroes = settingsCasted.HideZeroes != null ? settingsCasted.HideZeroes : this.HideZeroes;
1363
+ settingsCasted.Mode3D = settingsCasted.Mode3D != null ? settingsCasted.Mode3D : this.Mode3D;
1364
+ settingsCasted.DonutRadiusPercentage = settingsCasted.DonutRadiusPercentage != null ? settingsCasted.DonutRadiusPercentage : this.DonutRadiusPercentage;
1365
+ settingsCasted.LabelsWrap = settingsCasted.LabelsWrap != null ? settingsCasted.LabelsWrap : this.LabelsWrap;
1366
+ settingsCasted.LabelsTruncate = settingsCasted.LabelsTruncate != null ? settingsCasted.LabelsTruncate : this.LabelsTruncate;
1367
+ settingsCasted.LabelsWidth = settingsCasted.LabelsWidth != null ? settingsCasted.LabelsWidth : this.LabelsWidth;
1368
+ settingsCasted.LabelsVisible = settingsCasted.LabelsVisible != null ? settingsCasted.LabelsVisible : this.LabelsVisible;
1369
+ }
1370
+ /**
1371
+ * Effettua il rendering di questo grafico in base ai Settings
1372
+ *
1373
+ * @param {PieChartSettings} settingsCasted Impostazioni di graficazione
1374
+ * @returns {PieChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
1375
+ */
1376
+ graphicate(settingsCasted) {
1377
+ return new PieChartService(this.adapter).graphicate(this.Data, settingsCasted);
1378
+ }
1379
+ }
1380
+ EsPieChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsPieChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_THEME }, { token: i4$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
1381
+ EsPieChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsPieChartComponent, selector: "es-pie-chart", inputs: { Data: "Data", DataArray: "DataArray", HideZeroes: "HideZeroes", Mode3D: "Mode3D", DonutRadiusPercentage: "DonutRadiusPercentage", LabelsWrap: "LabelsWrap", LabelsTruncate: "LabelsTruncate", LabelsWidth: "LabelsWidth", LabelsVisible: "LabelsVisible" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsPieChartComponent, decorators: [{
1383
+ type: Component,
1384
+ args: [{ selector: 'es-pie-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
1385
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
1386
+ type: Inject,
1387
+ args: [PLATFORM_ID]
1388
+ }] }, { type: undefined, decorators: [{
1389
+ type: Inject,
1390
+ args: [ESC_LOGS]
1391
+ }] }, { type: undefined, decorators: [{
1392
+ type: Inject,
1393
+ args: [ESC_ANIMATIONS]
1394
+ }] }, { type: undefined, decorators: [{
1395
+ type: Inject,
1396
+ args: [ESC_THEME]
1397
+ }] }, { type: i4$1.LocalizationService }]; }, propDecorators: { Data: [{
1398
+ type: Input
1399
+ }], DataArray: [{
1400
+ type: Input
1401
+ }], HideZeroes: [{
1402
+ type: Input
1403
+ }], Mode3D: [{
1404
+ type: Input
1405
+ }], DonutRadiusPercentage: [{
1406
+ type: Input
1407
+ }], LabelsWrap: [{
1408
+ type: Input
1409
+ }], LabelsTruncate: [{
1410
+ type: Input
1411
+ }], LabelsWidth: [{
1412
+ type: Input
1413
+ }], LabelsVisible: [{
1414
+ type: Input
1415
+ }] } });
1416
+
1417
+ /**
1418
+ * Classe il cui unico scopo è gestire il setup e rendering di un Vertical2DChart
1579
1419
  */
1580
- class VerticalChartService {
1420
+ class Vertical2DChartService {
1581
1421
  /** @ignore */
1582
1422
  constructor(Adapter) {
1583
1423
  this.Adapter = Adapter;
1584
1424
  /** @ignore */
1425
+ this.DefaultGroupPaddingPercentage = 5;
1426
+ /** @ignore */
1585
1427
  this.dangerZone = 50;
1586
1428
  /** @ignore */
1587
1429
  this.LabelWidth = 150;
@@ -1593,7 +1435,7 @@ class VerticalChartService {
1593
1435
  this.DefaultColumnWidthPercentage = 85;
1594
1436
  }
1595
1437
  /**
1596
- * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un VerticalChart
1438
+ * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un Vertical2DChart
1597
1439
  */
1598
1440
  graphicate(data, settings) {
1599
1441
  if (settings.Timeline) {
@@ -1604,9 +1446,6 @@ class VerticalChartService {
1604
1446
  am4core.options.autoDispose = true;
1605
1447
  this.ChartInstance = am4core.create(settings.Name, am4charts.XYChart);
1606
1448
  let ChartInstanceCasted = this.ChartInstance;
1607
- let dataConverted = this.Adapter ? this.Adapter.adaptDataForVerticalChart(data) : data;
1608
- ChartInstanceCasted.data = dataConverted.values;
1609
- let noStrokes = dataConverted.values.some(t => !!t.c);
1610
1449
  if (settings.Legend) {
1611
1450
  ChartInstanceCasted.legend = new am4charts.Legend();
1612
1451
  ChartInstanceCasted.legend.position = settings?.LegendPosition ?? 'right';
@@ -1629,7 +1468,10 @@ class VerticalChartService {
1629
1468
  categoryAxis.title.text = settings.XAxisTitle;
1630
1469
  categoryAxis.title.fontWeight = "bold";
1631
1470
  }
1632
- categoryAxis.dataFields.category = "k";
1471
+ yAxis.min = 0;
1472
+ categoryAxis.dataFields.category = 'key';
1473
+ categoryAxis.renderer.cellStartLocation = am4core.percent(settings.GroupPaddingPercentage ?? this.DefaultGroupPaddingPercentage).value;
1474
+ categoryAxis.renderer.cellEndLocation = am4core.percent(100 - (settings.GroupPaddingPercentage ?? this.DefaultGroupPaddingPercentage)).value;
1633
1475
  categoryAxis.renderer.grid.template.location = 0;
1634
1476
  categoryAxis.renderer.minGridDistance = settings?.MinGridDistance ?? 30;
1635
1477
  let label = categoryAxis.renderer.labels.template;
@@ -1657,24 +1499,24 @@ class VerticalChartService {
1657
1499
  }
1658
1500
  });
1659
1501
  }
1660
- // Create series
1661
- let series = ChartInstanceCasted.series.push(new am4charts.ColumnSeries());
1662
- series.dataFields.valueY = "v";
1663
- series.dataFields.categoryX = "k";
1664
- series.name = "";
1665
- let columnTemplate = series.columns.template;
1666
- columnTemplate.tooltipText = "{categoryX}: [bold]{valueY}[/] {t}";
1667
- columnTemplate.fillOpacity = .8;
1668
- columnTemplate.width = am4core.percent(settings.ColumnWidthPercentage ?? this.DefaultColumnWidthPercentage);
1669
- if (noStrokes) {
1670
- columnTemplate.strokeOpacity = 0;
1671
- columnTemplate.strokeWidth = 0;
1672
- columnTemplate.adapter.add("fill", (_, target) => am4core.color(target.dataItem.dataContext.c));
1673
- }
1674
- else {
1675
- columnTemplate.strokeWidth = 2;
1676
- columnTemplate.strokeOpacity = 1;
1502
+ let dataPreConverted = this.Adapter ? this.Adapter.adaptDataForVertical2DChart(data) : data;
1503
+ let dataConverted = [];
1504
+ for (let i = 0; i < dataPreConverted.groups.length; i++) {
1505
+ let item = dataPreConverted.groups[i];
1506
+ let obj = { key: item.name };
1507
+ for (let p = 0; p < item.values.length; p++) {
1508
+ let value = item.values[p];
1509
+ obj[value.k] = value.v;
1510
+ }
1511
+ dataConverted.push(obj);
1677
1512
  }
1513
+ ChartInstanceCasted.data = dataConverted;
1514
+ if (dataPreConverted.colorinfos)
1515
+ ChartInstanceCasted.colors.list = dataPreConverted.colorinfos.map(c => am4core.color(c.color));
1516
+ //Prendo la prima categoria e mi baso sulle proprietà per dfeinire le serie
1517
+ for (let prop in dataConverted[0])
1518
+ if (prop !== "key")
1519
+ this.createSeries(ChartInstanceCasted, settings, prop, prop);
1678
1520
  return this;
1679
1521
  }
1680
1522
  /** @ignore */
@@ -1684,18 +1526,146 @@ class VerticalChartService {
1684
1526
  refreshData(data) {
1685
1527
  //TODO:IMPL
1686
1528
  }
1529
+ /** @ignore */
1530
+ createSeries(chart, settings, value, name) {
1531
+ let series = chart.series.push(new am4charts.ColumnSeries());
1532
+ series.dataFields.valueY = value;
1533
+ series.dataFields.categoryX = 'key';
1534
+ series.name = name;
1535
+ series.columns.template.tooltipText = "{name} {categoryX}: [bold]{valueY}[/]";
1536
+ series.columns.template.fillOpacity = .8;
1537
+ series.columns.template.width = am4core.percent(settings.ColumnWidthPercentage ?? this.DefaultColumnWidthPercentage);
1538
+ series.events.on("hidden", () => this.arrangeColumns);
1539
+ series.events.on("shown", () => this.arrangeColumns);
1540
+ return series;
1541
+ }
1542
+ /** @ignore */
1543
+ arrangeColumns() {
1544
+ let ChartInstanceCasted = this.ChartInstance;
1545
+ let series = ChartInstanceCasted.series.getIndex(0);
1546
+ let xAxis = ChartInstanceCasted.xAxes.getIndex(0);
1547
+ let w = 1 - xAxis.renderer.cellStartLocation - (1 - xAxis.renderer.cellEndLocation);
1548
+ if (series.dataItems.length > 1) {
1549
+ let x0 = xAxis.getX(series.dataItems.getIndex(0), "categoryX");
1550
+ let x1 = xAxis.getX(series.dataItems.getIndex(1), "categoryX");
1551
+ let delta = ((x1 - x0) / ChartInstanceCasted.series.length) * w;
1552
+ if (am4core.isNumber(delta)) {
1553
+ let middle = ChartInstanceCasted.series.length / 2;
1554
+ let newIndex = 0;
1555
+ ChartInstanceCasted.series.each((series) => {
1556
+ if (!series.isHidden && !series.isHiding) {
1557
+ series.dummyData = newIndex;
1558
+ newIndex++;
1559
+ }
1560
+ else {
1561
+ series.dummyData = ChartInstanceCasted.series.indexOf(series);
1562
+ }
1563
+ });
1564
+ let visibleCount = newIndex;
1565
+ let newMiddle = visibleCount / 2;
1566
+ ChartInstanceCasted.series.each((series) => {
1567
+ let trueIndex = ChartInstanceCasted.series.indexOf(series);
1568
+ let newIndex = series.dummyData;
1569
+ let dx = (newIndex - trueIndex + middle - newMiddle) * delta;
1570
+ series.animate({ property: "dx", to: dx }, series.interpolationDuration, series.interpolationEasing);
1571
+ series.bulletsContainer.animate({ property: "dx", to: dx }, series.interpolationDuration, series.interpolationEasing);
1572
+ });
1573
+ }
1574
+ }
1575
+ }
1687
1576
  }
1688
1577
 
1689
1578
  /**
1690
- * Classe il cui unico scopo è gestire il setup e rendering di un Vertical2DChart
1579
+ * Componente specifico per la graficazione di un grafico a Barre con due dimensioni
1691
1580
  */
1692
- class Vertical2DChartService {
1581
+ class EsVertical2DChartComponent extends BaseChartComponent {
1582
+ /**
1583
+ * @ignore
1584
+ */
1585
+ constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_THEME, lc) {
1586
+ super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, lc.Locale, ESC_THEME);
1587
+ this.adapter = adapter;
1588
+ }
1589
+ /**
1590
+ * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
1591
+ */
1592
+ getSpecificPropertiesToCheck() {
1593
+ return ["Data", "DataArray"];
1594
+ }
1595
+ /**
1596
+ * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
1597
+ *
1598
+ * @returns {Vertical2DChartSettings} Settings castati al tipo giusto
1599
+ */
1600
+ getCastedSettings() {
1601
+ return (this.Settings ?? new Vertical2DChartSettings());
1602
+ }
1603
+ /**
1604
+ * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
1605
+ *
1606
+ * @param {Vertical2DChartSettings} settingsCasted Settings castati al tipo giusto
1607
+ */
1608
+ fillSpecificSettings(settingsCasted) {
1609
+ settingsCasted.ColumnWidthPercentage = settingsCasted.ColumnWidthPercentage != null ? settingsCasted.ColumnWidthPercentage : this.ColumnWidthPercentage;
1610
+ settingsCasted.GroupPaddingPercentage = settingsCasted.GroupPaddingPercentage != null ? settingsCasted.GroupPaddingPercentage : this.GroupPaddingPercentage;
1611
+ settingsCasted.LabelWidth = settingsCasted.LabelWidth != null ? settingsCasted.LabelWidth : this.LabelWidth;
1612
+ settingsCasted.LabelVerticalOrientationCutoffWidth = settingsCasted.LabelVerticalOrientationCutoffWidth != null ? settingsCasted.LabelVerticalOrientationCutoffWidth : this.LabelVerticalOrientationCutoffWidth;
1613
+ settingsCasted.LabelRightWhenCompressed = settingsCasted.LabelRightWhenCompressed != null ? settingsCasted.LabelRightWhenCompressed : this.LabelRightWhenCompressed;
1614
+ settingsCasted.LabelTopWhenCompressed = settingsCasted.LabelTopWhenCompressed != null ? settingsCasted.LabelTopWhenCompressed : this.LabelTopWhenCompressed;
1615
+ }
1616
+ /**
1617
+ * Effettua il rendering di questo grafico in base ai Settings
1618
+ *
1619
+ * @param {Vertical2DChartSettings} settingsCasted Impostazioni di graficazione
1620
+ * @returns {Vertical2DChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
1621
+ */
1622
+ graphicate(settingsCasted) {
1623
+ return new Vertical2DChartService(this.adapter).graphicate(this.Data, settingsCasted);
1624
+ }
1625
+ }
1626
+ EsVertical2DChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVertical2DChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_THEME }, { token: i4$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
1627
+ EsVertical2DChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsVertical2DChartComponent, selector: "es-vertical-2d-chart", inputs: { Data: "Data", DataArray: "DataArray", ColumnWidthPercentage: "ColumnWidthPercentage", GroupPaddingPercentage: "GroupPaddingPercentage", LabelWidth: "LabelWidth", LabelVerticalOrientationCutoffWidth: "LabelVerticalOrientationCutoffWidth", LabelRightWhenCompressed: "LabelRightWhenCompressed", LabelTopWhenCompressed: "LabelTopWhenCompressed" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1628
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVertical2DChartComponent, decorators: [{
1629
+ type: Component,
1630
+ args: [{ selector: 'es-vertical-2d-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
1631
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
1632
+ type: Inject,
1633
+ args: [PLATFORM_ID]
1634
+ }] }, { type: undefined, decorators: [{
1635
+ type: Inject,
1636
+ args: [ESC_LOGS]
1637
+ }] }, { type: undefined, decorators: [{
1638
+ type: Inject,
1639
+ args: [ESC_ANIMATIONS]
1640
+ }] }, { type: undefined, decorators: [{
1641
+ type: Inject,
1642
+ args: [ESC_THEME]
1643
+ }] }, { type: i4$1.LocalizationService }]; }, propDecorators: { Data: [{
1644
+ type: Input
1645
+ }], DataArray: [{
1646
+ type: Input
1647
+ }], ColumnWidthPercentage: [{
1648
+ type: Input
1649
+ }], GroupPaddingPercentage: [{
1650
+ type: Input
1651
+ }], LabelWidth: [{
1652
+ type: Input
1653
+ }], LabelVerticalOrientationCutoffWidth: [{
1654
+ type: Input
1655
+ }], LabelRightWhenCompressed: [{
1656
+ type: Input
1657
+ }], LabelTopWhenCompressed: [{
1658
+ type: Input
1659
+ }] } });
1660
+
1661
+ /**
1662
+ * Classe il cui unico scopo è gestire il setup e rendering di un VerticalChart
1663
+ */
1664
+ class VerticalChartService {
1693
1665
  /** @ignore */
1694
1666
  constructor(Adapter) {
1695
1667
  this.Adapter = Adapter;
1696
1668
  /** @ignore */
1697
- this.DefaultGroupPaddingPercentage = 5;
1698
- /** @ignore */
1699
1669
  this.dangerZone = 50;
1700
1670
  /** @ignore */
1701
1671
  this.LabelWidth = 150;
@@ -1707,7 +1677,7 @@ class Vertical2DChartService {
1707
1677
  this.DefaultColumnWidthPercentage = 85;
1708
1678
  }
1709
1679
  /**
1710
- * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un Vertical2DChart
1680
+ * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un VerticalChart
1711
1681
  */
1712
1682
  graphicate(data, settings) {
1713
1683
  if (settings.Timeline) {
@@ -1718,6 +1688,9 @@ class Vertical2DChartService {
1718
1688
  am4core.options.autoDispose = true;
1719
1689
  this.ChartInstance = am4core.create(settings.Name, am4charts.XYChart);
1720
1690
  let ChartInstanceCasted = this.ChartInstance;
1691
+ let dataConverted = this.Adapter ? this.Adapter.adaptDataForVerticalChart(data) : data;
1692
+ ChartInstanceCasted.data = dataConverted.values;
1693
+ let noStrokes = dataConverted.values.some(t => !!t.c);
1721
1694
  if (settings.Legend) {
1722
1695
  ChartInstanceCasted.legend = new am4charts.Legend();
1723
1696
  ChartInstanceCasted.legend.position = settings?.LegendPosition ?? 'right';
@@ -1740,10 +1713,7 @@ class Vertical2DChartService {
1740
1713
  categoryAxis.title.text = settings.XAxisTitle;
1741
1714
  categoryAxis.title.fontWeight = "bold";
1742
1715
  }
1743
- yAxis.min = 0;
1744
- categoryAxis.dataFields.category = 'key';
1745
- categoryAxis.renderer.cellStartLocation = am4core.percent(settings.GroupPaddingPercentage ?? this.DefaultGroupPaddingPercentage).value;
1746
- categoryAxis.renderer.cellEndLocation = am4core.percent(100 - (settings.GroupPaddingPercentage ?? this.DefaultGroupPaddingPercentage)).value;
1716
+ categoryAxis.dataFields.category = "k";
1747
1717
  categoryAxis.renderer.grid.template.location = 0;
1748
1718
  categoryAxis.renderer.minGridDistance = settings?.MinGridDistance ?? 30;
1749
1719
  let label = categoryAxis.renderer.labels.template;
@@ -1771,24 +1741,24 @@ class Vertical2DChartService {
1771
1741
  }
1772
1742
  });
1773
1743
  }
1774
- let dataPreConverted = this.Adapter ? this.Adapter.adaptDataForVertical2DChart(data) : data;
1775
- let dataConverted = [];
1776
- for (let i = 0; i < dataPreConverted.groups.length; i++) {
1777
- let item = dataPreConverted.groups[i];
1778
- let obj = { key: item.name };
1779
- for (let p = 0; p < item.values.length; p++) {
1780
- let value = item.values[p];
1781
- obj[value.k] = value.v;
1782
- }
1783
- dataConverted.push(obj);
1744
+ // Create series
1745
+ let series = ChartInstanceCasted.series.push(new am4charts.ColumnSeries());
1746
+ series.dataFields.valueY = "v";
1747
+ series.dataFields.categoryX = "k";
1748
+ series.name = "";
1749
+ let columnTemplate = series.columns.template;
1750
+ columnTemplate.tooltipText = "{categoryX}: [bold]{valueY}[/] {t}";
1751
+ columnTemplate.fillOpacity = .8;
1752
+ columnTemplate.width = am4core.percent(settings.ColumnWidthPercentage ?? this.DefaultColumnWidthPercentage);
1753
+ if (noStrokes) {
1754
+ columnTemplate.strokeOpacity = 0;
1755
+ columnTemplate.strokeWidth = 0;
1756
+ columnTemplate.adapter.add("fill", (_, target) => am4core.color(target.dataItem.dataContext.c));
1757
+ }
1758
+ else {
1759
+ columnTemplate.strokeWidth = 2;
1760
+ columnTemplate.strokeOpacity = 1;
1784
1761
  }
1785
- ChartInstanceCasted.data = dataConverted;
1786
- if (dataPreConverted.colorinfos)
1787
- ChartInstanceCasted.colors.list = dataPreConverted.colorinfos.map(c => am4core.color(c.color));
1788
- //Prendo la prima categoria e mi baso sulle proprietà per dfeinire le serie
1789
- for (let prop in dataConverted[0])
1790
- if (prop !== "key")
1791
- this.createSeries(ChartInstanceCasted, settings, prop, prop);
1792
1762
  return this;
1793
1763
  }
1794
1764
  /** @ignore */
@@ -1798,54 +1768,87 @@ class Vertical2DChartService {
1798
1768
  refreshData(data) {
1799
1769
  //TODO:IMPL
1800
1770
  }
1801
- /** @ignore */
1802
- createSeries(chart, settings, value, name) {
1803
- let series = chart.series.push(new am4charts.ColumnSeries());
1804
- series.dataFields.valueY = value;
1805
- series.dataFields.categoryX = 'key';
1806
- series.name = name;
1807
- series.columns.template.tooltipText = "{name} {categoryX}: [bold]{valueY}[/]";
1808
- series.columns.template.fillOpacity = .8;
1809
- series.columns.template.width = am4core.percent(settings.ColumnWidthPercentage ?? this.DefaultColumnWidthPercentage);
1810
- series.events.on("hidden", () => this.arrangeColumns);
1811
- series.events.on("shown", () => this.arrangeColumns);
1812
- return series;
1771
+ }
1772
+
1773
+ /**
1774
+ * Componente specifico per la graficazione di un grafico a Barre
1775
+ */
1776
+ class EsVerticalChartComponent extends BaseChartComponent {
1777
+ /**
1778
+ * @ignore
1779
+ */
1780
+ constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_THEME, lc) {
1781
+ super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, lc.Locale, ESC_THEME);
1782
+ this.adapter = adapter;
1813
1783
  }
1814
- /** @ignore */
1815
- arrangeColumns() {
1816
- let ChartInstanceCasted = this.ChartInstance;
1817
- let series = ChartInstanceCasted.series.getIndex(0);
1818
- let xAxis = ChartInstanceCasted.xAxes.getIndex(0);
1819
- let w = 1 - xAxis.renderer.cellStartLocation - (1 - xAxis.renderer.cellEndLocation);
1820
- if (series.dataItems.length > 1) {
1821
- let x0 = xAxis.getX(series.dataItems.getIndex(0), "categoryX");
1822
- let x1 = xAxis.getX(series.dataItems.getIndex(1), "categoryX");
1823
- let delta = ((x1 - x0) / ChartInstanceCasted.series.length) * w;
1824
- if (am4core.isNumber(delta)) {
1825
- let middle = ChartInstanceCasted.series.length / 2;
1826
- let newIndex = 0;
1827
- ChartInstanceCasted.series.each((series) => {
1828
- if (!series.isHidden && !series.isHiding) {
1829
- series.dummyData = newIndex;
1830
- newIndex++;
1831
- }
1832
- else {
1833
- series.dummyData = ChartInstanceCasted.series.indexOf(series);
1834
- }
1835
- });
1836
- let visibleCount = newIndex;
1837
- let newMiddle = visibleCount / 2;
1838
- ChartInstanceCasted.series.each((series) => {
1839
- let trueIndex = ChartInstanceCasted.series.indexOf(series);
1840
- let newIndex = series.dummyData;
1841
- let dx = (newIndex - trueIndex + middle - newMiddle) * delta;
1842
- series.animate({ property: "dx", to: dx }, series.interpolationDuration, series.interpolationEasing);
1843
- series.bulletsContainer.animate({ property: "dx", to: dx }, series.interpolationDuration, series.interpolationEasing);
1844
- });
1845
- }
1846
- }
1784
+ /**
1785
+ * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
1786
+ */
1787
+ getSpecificPropertiesToCheck() {
1788
+ return ["Data", "DataArray"];
1847
1789
  }
1848
- }
1790
+ /**
1791
+ * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
1792
+ *
1793
+ * @returns {VerticalChartSettings} Settings castati al tipo giusto
1794
+ */
1795
+ getCastedSettings() {
1796
+ return (this.Settings ?? new VerticalChartSettings());
1797
+ }
1798
+ /**
1799
+ * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
1800
+ *
1801
+ * @param {VerticalChartSettings} settingsCasted Settings castati al tipo giusto
1802
+ */
1803
+ fillSpecificSettings(settingsCasted) {
1804
+ settingsCasted.ColumnWidthPercentage = settingsCasted.ColumnWidthPercentage != null ? settingsCasted.ColumnWidthPercentage : this.ColumnWidthPercentage;
1805
+ settingsCasted.LabelWidth = settingsCasted.LabelWidth != null ? settingsCasted.LabelWidth : this.LabelWidth;
1806
+ settingsCasted.LabelVerticalOrientationCutoffWidth = settingsCasted.LabelVerticalOrientationCutoffWidth != null ? settingsCasted.LabelVerticalOrientationCutoffWidth : this.LabelVerticalOrientationCutoffWidth;
1807
+ settingsCasted.LabelRightWhenCompressed = settingsCasted.LabelRightWhenCompressed != null ? settingsCasted.LabelRightWhenCompressed : this.LabelRightWhenCompressed;
1808
+ settingsCasted.LabelTopWhenCompressed = settingsCasted.LabelTopWhenCompressed != null ? settingsCasted.LabelTopWhenCompressed : this.LabelTopWhenCompressed;
1809
+ }
1810
+ /**
1811
+ * Effettua il rendering di questo grafico in base ai Settings
1812
+ *
1813
+ * @param {VerticalChartSettings} settingsCasted Impostazioni di graficazione
1814
+ * @returns {VerticalChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
1815
+ */
1816
+ graphicate(settingsCasted) {
1817
+ return new VerticalChartService(this.adapter).graphicate(this.Data, settingsCasted);
1818
+ }
1819
+ }
1820
+ EsVerticalChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_THEME }, { token: i4$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
1821
+ EsVerticalChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsVerticalChartComponent, selector: "es-vertical-chart", inputs: { Data: "Data", DataArray: "DataArray", ColumnWidthPercentage: "ColumnWidthPercentage", LabelWidth: "LabelWidth", LabelVerticalOrientationCutoffWidth: "LabelVerticalOrientationCutoffWidth", LabelRightWhenCompressed: "LabelRightWhenCompressed", LabelTopWhenCompressed: "LabelTopWhenCompressed" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1822
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalChartComponent, decorators: [{
1823
+ type: Component,
1824
+ args: [{ selector: 'es-vertical-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
1825
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
1826
+ type: Inject,
1827
+ args: [PLATFORM_ID]
1828
+ }] }, { type: undefined, decorators: [{
1829
+ type: Inject,
1830
+ args: [ESC_LOGS]
1831
+ }] }, { type: undefined, decorators: [{
1832
+ type: Inject,
1833
+ args: [ESC_ANIMATIONS]
1834
+ }] }, { type: undefined, decorators: [{
1835
+ type: Inject,
1836
+ args: [ESC_THEME]
1837
+ }] }, { type: i4$1.LocalizationService }]; }, propDecorators: { Data: [{
1838
+ type: Input
1839
+ }], DataArray: [{
1840
+ type: Input
1841
+ }], ColumnWidthPercentage: [{
1842
+ type: Input
1843
+ }], LabelWidth: [{
1844
+ type: Input
1845
+ }], LabelVerticalOrientationCutoffWidth: [{
1846
+ type: Input
1847
+ }], LabelRightWhenCompressed: [{
1848
+ type: Input
1849
+ }], LabelTopWhenCompressed: [{
1850
+ type: Input
1851
+ }] } });
1849
1852
 
1850
1853
  /**
1851
1854
  * Classe il cui unico scopo è gestire il setup e rendering di un VerticalStackedChart
@@ -1944,169 +1947,114 @@ class VerticalStackedChartService {
1944
1947
  template.paddingBottom = settings.LegendPadding.bottom ?? 0;
1945
1948
  template.paddingLeft = settings.LegendPadding.left ?? 0;
1946
1949
  template.paddingRight = settings.LegendPadding.right ?? 0;
1947
- }
1948
- }
1949
- return this;
1950
- }
1951
- /** @ignore */
1952
- setSelection(from, to) {
1953
- }
1954
- /** @ignore */
1955
- refreshData(data) {
1956
- //TODO:IMPL
1957
- }
1958
- /** @ignore */
1959
- createSeriesStacked(chart, settings, field, name) {
1960
- // Set up series
1961
- let series = chart.series.push(new am4charts.ColumnSeries());
1962
- series.name = name;
1963
- series.dataFields.valueY = field;
1964
- series.dataFields.categoryX = "key";
1965
- series.sequencedInterpolation = true;
1966
- series.columns.template.tooltipText = "{name} {categoryX}: [bold]{valueY}[/]";
1967
- series.columns.template.fillOpacity = .8;
1968
- series.columns.template.width = am4core.percent(settings.ColumnWidthPercentage ?? this.DefaultColumnWidthPercentage);
1969
- // Make it stacked
1970
- series.stacked = true;
1971
- return series;
1972
- }
1973
- }
1974
-
1975
- /**
1976
- * Classe il cui unico scopo è gestire il setup e rendering di un AreaChart
1977
- */
1978
- class AreaChartService {
1979
- /** @ignore */
1980
- constructor(Adapter) {
1981
- this.Adapter = Adapter;
1982
- //******************** Funzione di throttling per non spammare richieste in caso di animazioni attivate
1983
- //TODO: spostarla in un metodo di utilità (esfaenza/extensions)
1984
- /** @ignore */
1985
- this.executionTimers = {};
1986
- }
1987
- /**
1988
- * Metodo che data una coppia Dati - Impostazioni li utilizza per creare e visualizzare un AreaChart
1989
- */
1990
- graphicate(data, settings) {
1991
- if (settings.Timeline) {
1992
- console.error("Timeline not supported for area chart");
1993
- return null;
1994
- }
1995
- let dataConverted = this.Adapter ? this.Adapter.adaptDataForAreaChart(data) : data;
1996
- let showTicks = settings.ShowTicks == null ? true : settings?.ShowTicks;
1997
- let interval = dataConverted.interval;
1998
- //Per evitare di dimenticarmeli e gestire comunque bene gli ngif ecc...
1999
- am4core.options.autoDispose = true;
2000
- this.ChartInstance = am4core.create(settings.Name, am4charts.XYChart);
2001
- let ChartInstanceCasted = this.ChartInstance;
2002
- if (settings.Legend) {
2003
- ChartInstanceCasted.legend = new am4charts.Legend();
2004
- ChartInstanceCasted.legend.position = settings?.LegendPosition ?? 'right';
2005
- ChartInstanceCasted.legend.itemContainers.template.tooltipText = "{category}";
2006
- if (settings.LegendPadding) {
2007
- let template = this.ChartInstance.legend.itemContainers.template;
2008
- template.paddingTop = settings.LegendPadding.top ?? 0;
2009
- template.paddingBottom = settings.LegendPadding.bottom ?? 0;
2010
- template.paddingLeft = settings.LegendPadding.left ?? 0;
2011
- template.paddingRight = settings.LegendPadding.right ?? 0;
2012
- }
2013
- }
2014
- let yAxis = ChartInstanceCasted.yAxes.push(new am4charts.ValueAxis());
2015
- yAxis.tooltip.disabled = true;
2016
- if (settings.YAxisTitle) {
2017
- yAxis.title.text = settings.YAxisTitle;
2018
- yAxis.title.fontWeight = "bold";
2019
- }
2020
- yAxis.min = 0;
2021
- let dateAxis = ChartInstanceCasted.xAxes.push(new am4charts.DateAxis());
2022
- dateAxis.renderer.minGridDistance = settings?.MinGridDistance ?? 50;
2023
- dateAxis.startLocation = 0.5;
2024
- dateAxis.endLocation = 0.5;
2025
- if (settings.XAxisTitle) {
2026
- dateAxis.title.text = settings.XAxisTitle;
2027
- dateAxis.title.fontWeight = "bold";
2028
- }
2029
- if (showTicks) {
2030
- dateAxis.renderer.ticks.template.disabled = false;
2031
- dateAxis.renderer.ticks.template.strokeOpacity = 1;
2032
- dateAxis.renderer.ticks.template.stroke = am4core.color("#495C43");
2033
- dateAxis.renderer.ticks.template.strokeWidth = 2;
2034
- dateAxis.renderer.ticks.template.length = 10;
2035
- dateAxis.renderer.ticks.template.location = 0;
2036
- }
2037
- if (!!interval)
2038
- dateAxis.baseInterval = { count: interval.count, timeUnit: interval.timeunit };
2039
- // Unisco il dataset e tiro fuori i dati
2040
- let chartData = [];
2041
- let seriesToMakeCache = {};
2042
- let seriesToMake = [];
2043
- for (let i = 0; i < dataConverted.groups.length; i++) {
2044
- let group = dataConverted.groups[i];
2045
- let dataItem = { date: group.name };
2046
- for (let ii = 0; ii < group.values.length; ii++) {
2047
- let val = group.values[ii];
2048
- dataItem[val.k] = val.v;
2049
- if (!seriesToMakeCache[val.k]) {
2050
- seriesToMakeCache[val.k] = true;
2051
- seriesToMake.push(val.k);
2052
- }
2053
- }
2054
- chartData.push(dataItem);
2055
- }
2056
- ChartInstanceCasted.data = chartData;
2057
- //---------------------------------------------------------
2058
- seriesToMake.forEach(s => { this.createSeries(ChartInstanceCasted, s); });
2059
- ChartInstanceCasted.cursor = new am4charts.XYCursor();
2060
- ChartInstanceCasted.cursor.xAxis = dateAxis;
2061
- dateAxis.events.on("startchanged", t => this.emitSelectionChanged(t, settings));
2062
- dateAxis.events.on("endchanged", t => this.emitSelectionChanged(t, settings));
2063
- return this;
2064
- }
2065
- /** @ignore */
2066
- setSelection(from, to) {
2067
- }
2068
- /** @ignore */
2069
- refreshData(data) {
2070
- //TODO:IMPL
2071
- }
2072
- /** @ignore */
2073
- emitSelectionChanged(ev, settings) {
2074
- if (settings.OnSelectionChangedCallback) {
2075
- this.throttla("selchange", () => {
2076
- var axis = ev.target;
2077
- var start = new Date(axis.minZoomed);
2078
- var end = new Date(axis.maxZoomed);
2079
- var initial = axis.min == axis.minZoomed && axis.max == axis.maxZoomed;
2080
- settings.OnSelectionChangedCallback({ from: start, to: end, initial: initial });
2081
- }, 150);
1950
+ }
2082
1951
  }
1952
+ return this;
2083
1953
  }
2084
1954
  /** @ignore */
2085
- createSeries(chart, name) {
2086
- let series = chart.series.push(new am4charts.LineSeries());
2087
- series.dataFields.dateX = "date";
2088
- series.name = name[0].toUpperCase() + name.slice(1);
2089
- series.dataFields.valueY = name;
2090
- series.tooltipText = "[#000]{valueY.value}[/]";
2091
- //series.tooltip.background.fill = am4core.color("#FFF");
2092
- series.tooltip.getStrokeFromObject = true;
2093
- series.tooltip.background.strokeWidth = 3;
2094
- series.tooltip.getFillFromObject = false;
2095
- series.fillOpacity = 0.6;
2096
- series.strokeWidth = 2;
2097
- series.stacked = true;
2098
- return series;
1955
+ setSelection(from, to) {
2099
1956
  }
2100
1957
  /** @ignore */
2101
- throttla(id, func, throttleTime) {
2102
- //Se ho la funzione che vuole eseguire ripulisco quel timeout
2103
- if (this.executionTimers[id])
2104
- clearTimeout(this.executionTimers[id]);
2105
- //Ricreo il timeout per eseguire quella funzione dopo throttleTime millisecondi
2106
- this.executionTimers[id] = setTimeout(() => { func(); this.executionTimers[id] = null; }, throttleTime);
1958
+ refreshData(data) {
1959
+ //TODO:IMPL
1960
+ }
1961
+ /** @ignore */
1962
+ createSeriesStacked(chart, settings, field, name) {
1963
+ // Set up series
1964
+ let series = chart.series.push(new am4charts.ColumnSeries());
1965
+ series.name = name;
1966
+ series.dataFields.valueY = field;
1967
+ series.dataFields.categoryX = "key";
1968
+ series.sequencedInterpolation = true;
1969
+ series.columns.template.tooltipText = "{name} {categoryX}: [bold]{valueY}[/]";
1970
+ series.columns.template.fillOpacity = .8;
1971
+ series.columns.template.width = am4core.percent(settings.ColumnWidthPercentage ?? this.DefaultColumnWidthPercentage);
1972
+ // Make it stacked
1973
+ series.stacked = true;
1974
+ return series;
2107
1975
  }
2108
1976
  }
2109
1977
 
1978
+ /**
1979
+ * Componente specifico per la graficazione di un grafico a Barre in modalità Stacked (una serie sopra l'altra)
1980
+ */
1981
+ class EsVerticalStackedChartComponent extends BaseChartComponent {
1982
+ /**
1983
+ * @ignore
1984
+ */
1985
+ constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_THEME, lc) {
1986
+ super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, lc.Locale, ESC_THEME);
1987
+ this.adapter = adapter;
1988
+ }
1989
+ /**
1990
+ * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
1991
+ */
1992
+ getSpecificPropertiesToCheck() {
1993
+ return ["Data", "DataArray"];
1994
+ }
1995
+ /**
1996
+ * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
1997
+ *
1998
+ * @returns {VerticalStackedChartSettings} Settings castati al tipo giusto
1999
+ */
2000
+ getCastedSettings() {
2001
+ return (this.Settings ?? new VerticalStackedChartSettings());
2002
+ }
2003
+ /**
2004
+ * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
2005
+ *
2006
+ * @param {VerticalStackedChartSettings} settingsCasted Settings castati al tipo giusto
2007
+ */
2008
+ fillSpecificSettings(settingsCasted) {
2009
+ settingsCasted.ColumnWidthPercentage = settingsCasted.ColumnWidthPercentage != null ? settingsCasted.ColumnWidthPercentage : this.ColumnWidthPercentage;
2010
+ settingsCasted.LabelWidth = settingsCasted.LabelWidth != null ? settingsCasted.LabelWidth : this.LabelWidth;
2011
+ settingsCasted.LabelVerticalOrientationCutoffWidth = settingsCasted.LabelVerticalOrientationCutoffWidth != null ? settingsCasted.LabelVerticalOrientationCutoffWidth : this.LabelVerticalOrientationCutoffWidth;
2012
+ settingsCasted.LabelRightWhenCompressed = settingsCasted.LabelRightWhenCompressed != null ? settingsCasted.LabelRightWhenCompressed : this.LabelRightWhenCompressed;
2013
+ settingsCasted.LabelTopWhenCompressed = settingsCasted.LabelTopWhenCompressed != null ? settingsCasted.LabelTopWhenCompressed : this.LabelTopWhenCompressed;
2014
+ }
2015
+ /**
2016
+ * Effettua il rendering di questo grafico in base ai Settings
2017
+ *
2018
+ * @param {VerticalStackedChartSettings} settingsCasted Impostazioni di graficazione
2019
+ * @returns {VerticalStackedChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
2020
+ */
2021
+ graphicate(settingsCasted) {
2022
+ return new VerticalStackedChartService(this.adapter).graphicate(this.Data, settingsCasted);
2023
+ }
2024
+ }
2025
+ EsVerticalStackedChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalStackedChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_THEME }, { token: i4$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
2026
+ EsVerticalStackedChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsVerticalStackedChartComponent, selector: "es-vertical-stacked-chart", inputs: { Data: "Data", DataArray: "DataArray", ColumnWidthPercentage: "ColumnWidthPercentage", LabelWidth: "LabelWidth", LabelVerticalOrientationCutoffWidth: "LabelVerticalOrientationCutoffWidth", LabelRightWhenCompressed: "LabelRightWhenCompressed", LabelTopWhenCompressed: "LabelTopWhenCompressed" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2027
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalStackedChartComponent, decorators: [{
2028
+ type: Component,
2029
+ args: [{ selector: 'es-vertical-stacked-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2030
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2031
+ type: Inject,
2032
+ args: [PLATFORM_ID]
2033
+ }] }, { type: undefined, decorators: [{
2034
+ type: Inject,
2035
+ args: [ESC_LOGS]
2036
+ }] }, { type: undefined, decorators: [{
2037
+ type: Inject,
2038
+ args: [ESC_ANIMATIONS]
2039
+ }] }, { type: undefined, decorators: [{
2040
+ type: Inject,
2041
+ args: [ESC_THEME]
2042
+ }] }, { type: i4$1.LocalizationService }]; }, propDecorators: { Data: [{
2043
+ type: Input
2044
+ }], DataArray: [{
2045
+ type: Input
2046
+ }], ColumnWidthPercentage: [{
2047
+ type: Input
2048
+ }], LabelWidth: [{
2049
+ type: Input
2050
+ }], LabelVerticalOrientationCutoffWidth: [{
2051
+ type: Input
2052
+ }], LabelRightWhenCompressed: [{
2053
+ type: Input
2054
+ }], LabelTopWhenCompressed: [{
2055
+ type: Input
2056
+ }] } });
2057
+
2110
2058
  /**
2111
2059
  * Componente specifico per la graficazione di un qualsiasi tipo di grafico.
2112
2060
  *
@@ -2116,8 +2064,8 @@ class EsChartComponent extends BaseChartComponent {
2116
2064
  /**
2117
2065
  * @ignore
2118
2066
  */
2119
- constructor(el, ChartLoader, ChartDispatcher, dateService, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME) {
2120
- super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME);
2067
+ constructor(el, ChartLoader, ChartDispatcher, dateService, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_THEME, lc) {
2068
+ super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, lc.Locale, ESC_THEME);
2121
2069
  this.dateService = dateService;
2122
2070
  this.adapter = adapter;
2123
2071
  }
@@ -2179,12 +2127,12 @@ class EsChartComponent extends BaseChartComponent {
2179
2127
  }
2180
2128
  }
2181
2129
  }
2182
- EsChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: i3.DateService }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_LOCALE }, { token: ESC_THEME }], target: i0.ɵɵFactoryTarget.Component });
2183
- EsChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsChartComponent, selector: "es-chart", inputs: { Type: "Type", Data: "Data", DataArray: "DataArray" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2130
+ EsChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: i4.DateService }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_THEME }, { token: i4$1.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
2131
+ EsChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsChartComponent, selector: "es-chart", inputs: { Type: "Type", Data: "Data", DataArray: "DataArray" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2184
2132
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartComponent, decorators: [{
2185
2133
  type: Component,
2186
2134
  args: [{ selector: 'es-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2187
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: i3.DateService }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2135
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: i4.DateService }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2188
2136
  type: Inject,
2189
2137
  args: [PLATFORM_ID]
2190
2138
  }] }, { type: undefined, decorators: [{
@@ -2193,13 +2141,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
2193
2141
  }] }, { type: undefined, decorators: [{
2194
2142
  type: Inject,
2195
2143
  args: [ESC_ANIMATIONS]
2196
- }] }, { type: undefined, decorators: [{
2197
- type: Inject,
2198
- args: [ESC_LOCALE]
2199
2144
  }] }, { type: undefined, decorators: [{
2200
2145
  type: Inject,
2201
2146
  args: [ESC_THEME]
2202
- }] }]; }, propDecorators: { Type: [{
2147
+ }] }, { type: i4$1.LocalizationService }]; }, propDecorators: { Type: [{
2203
2148
  type: Input
2204
2149
  }], Data: [{
2205
2150
  type: Input
@@ -2207,515 +2152,607 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
2207
2152
  type: Input
2208
2153
  }] } });
2209
2154
 
2155
+ /** Componenti esportati dal modulo */
2156
+ const COMPONENTS = [
2157
+ EsChartComponent,
2158
+ EsLineChartComponent,
2159
+ EsPieChartComponent,
2160
+ EsVertical2DChartComponent,
2161
+ EsVerticalChartComponent,
2162
+ EsVerticalStackedChartComponent,
2163
+ PageChartSelector,
2164
+ EsAreaChartComponent
2165
+ ];
2166
+ class EsChartsModule {
2167
+ static forRoot(config) {
2168
+ return {
2169
+ ngModule: EsChartsModule,
2170
+ providers: [
2171
+ { provide: ESC_ANIMATIONS, useValue: config?.animations == null || config?.animations == undefined ? true : config?.animations },
2172
+ { provide: ESC_THEME, useValue: config?.theme || 'spiritedaway' },
2173
+ { provide: ESC_LOGS, useValue: config?.debugMode || false },
2174
+ { provide: BaseAdapter, useClass: config?.adapter || BaseAdapter }
2175
+ ]
2176
+ };
2177
+ }
2178
+ }
2179
+ EsChartsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2180
+ EsChartsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, declarations: [EsChartComponent,
2181
+ EsLineChartComponent,
2182
+ EsPieChartComponent,
2183
+ EsVertical2DChartComponent,
2184
+ EsVerticalChartComponent,
2185
+ EsVerticalStackedChartComponent,
2186
+ PageChartSelector,
2187
+ EsAreaChartComponent], imports: [CommonModule], exports: [EsChartComponent,
2188
+ EsLineChartComponent,
2189
+ EsPieChartComponent,
2190
+ EsVertical2DChartComponent,
2191
+ EsVerticalChartComponent,
2192
+ EsVerticalStackedChartComponent,
2193
+ PageChartSelector,
2194
+ EsAreaChartComponent] });
2195
+ EsChartsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, imports: [CommonModule] });
2196
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, decorators: [{
2197
+ type: NgModule,
2198
+ args: [{
2199
+ imports: [CommonModule],
2200
+ declarations: [...COMPONENTS],
2201
+ exports: [...COMPONENTS]
2202
+ }]
2203
+ }] });
2204
+
2210
2205
  /**
2211
- * Componente specifico per la graficazione di un grafico ad Area
2206
+ * Classe di supporto al caricamento dinamico dei vari pezzi di amcharts che mi servono per il grafico (temi, locali, ecc...)
2207
+ *
2208
+ * Essenzialmente ogni volta che viene creato un grafico, questo acquisisce il tema e il locale applicato IN QUEL MOMENTO,
2209
+ * questo significa che per creare due grafici con temi diversi bisogna fare:
2210
+ *
2211
+ * 1) Caricamento tema 1
2212
+ *
2213
+ * 2) Creazione grafico 1
2214
+ *
2215
+ * 3) Scaricamento tema 1
2216
+ *
2217
+ * 3) Caricamento tema 2
2218
+ *
2219
+ * 4) Creazione grafico 2
2220
+ *
2212
2221
  */
2213
- class EsAreaChartComponent extends BaseChartComponent {
2222
+ class ChartLoader {
2214
2223
  /**
2215
2224
  * @ignore
2216
2225
  */
2217
- constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME) {
2218
- super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME);
2219
- this.adapter = adapter;
2220
- }
2221
- /**
2222
- * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
2223
- */
2224
- getSpecificPropertiesToCheck() {
2225
- return ["Data", "DataArray"];
2226
- }
2227
- /**
2228
- * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
2229
- *
2230
- * @returns {AreaChartSettings} Settings castati al tipo giusto
2231
- */
2232
- getCastedSettings() {
2233
- return (this.Settings ?? new AreaChartSettings());
2234
- }
2235
- /**
2236
- * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
2237
- *
2238
- * @param {AreaChartSettings} settingsCasted Settings castati al tipo giusto
2239
- */
2240
- fillSpecificSettings(settingsCasted) {
2226
+ constructor(logs) {
2227
+ this.logs = logs;
2228
+ /**
2229
+ * Indica se attualmente ho le animazioni caricate in modo da non ricaricarle inutilmente
2230
+ */
2231
+ this.AnimationsAreLoaded = false;
2232
+ /**
2233
+ * Indica l'ultimo tema caricato in modo da non ricaricarlo inutilmente qualora il prossimo grafico da creare richieda lo stesso tema
2234
+ */
2235
+ this.LastLoadedTheme = "";
2236
+ /**
2237
+ * Cache dei temi (moduli caricati dinamicamente)
2238
+ */
2239
+ this.themeCache = {};
2240
+ /**
2241
+ * Cache delle localizzazioni (moduli caricati dinamicamente)
2242
+ */
2243
+ this.localizationCache = {};
2241
2244
  }
2242
2245
  /**
2243
- * Effettua il rendering di questo grafico in base ai Settings
2246
+ * Applica il tema con le animazioni all'istanza globale di amCharts
2244
2247
  *
2245
- * @param {AreaChartSettings} settingsCasted Impostazioni di graficazione
2246
- * @returns {AreaChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
2247
- */
2248
- graphicate(settingsCasted) {
2249
- return new AreaChartService(this.adapter).graphicate(this.Data, settingsCasted);
2250
- }
2251
- }
2252
- EsAreaChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsAreaChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_LOCALE }, { token: ESC_THEME }], target: i0.ɵɵFactoryTarget.Component });
2253
- EsAreaChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsAreaChartComponent, selector: "es-area-chart", inputs: { Data: "Data", DataArray: "DataArray" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2254
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsAreaChartComponent, decorators: [{
2255
- type: Component,
2256
- args: [{ selector: 'es-area-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2257
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2258
- type: Inject,
2259
- args: [PLATFORM_ID]
2260
- }] }, { type: undefined, decorators: [{
2261
- type: Inject,
2262
- args: [ESC_LOGS]
2263
- }] }, { type: undefined, decorators: [{
2264
- type: Inject,
2265
- args: [ESC_ANIMATIONS]
2266
- }] }, { type: undefined, decorators: [{
2267
- type: Inject,
2268
- args: [ESC_LOCALE]
2269
- }] }, { type: undefined, decorators: [{
2270
- type: Inject,
2271
- args: [ESC_THEME]
2272
- }] }]; }, propDecorators: { Data: [{
2273
- type: Input
2274
- }], DataArray: [{
2275
- type: Input
2276
- }] } });
2277
-
2278
- /**
2279
- * Componente specifico per la graficazione di un grafico a Linea su un asse temporale
2280
- */
2281
- class EsLineChartComponent extends BaseChartComponent {
2248
+ * @param {Object} chartsCore Istanza globale di amCharts
2249
+ * @returns {Promise} Promise che identifica la fine del caricamento
2250
+ */
2251
+ applyAnimations(chartsCore) {
2252
+ if (!this.AnimationsAreLoaded) {
2253
+ return this.importIfNeeded('themes', ChartThemes.animated).then(() => {
2254
+ this.log("CORE: Applying theme " + ChartThemes.animated);
2255
+ chartsCore.useTheme(this.themeCache[ChartThemes.animated]);
2256
+ this.AnimationsAreLoaded = true;
2257
+ });
2258
+ }
2259
+ else {
2260
+ this.log("CORE: theme already applyed " + ChartThemes.animated);
2261
+ return new Promise((resolve) => { resolve(true); });
2262
+ }
2263
+ }
2282
2264
  /**
2283
- * @ignore
2265
+ * De-applica il tema con le animazioni dall'istanza globale di amCharts
2266
+ *
2267
+ * @param {Object} chartsCore Istanza globale di amCharts
2268
+ * @returns {Promise} Promise che identifica la fine dello scarico
2284
2269
  */
2285
- constructor(el, ChartLoader, ChartDispatcher, adapter, dateService, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME) {
2286
- super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME);
2287
- this.adapter = adapter;
2288
- this.dateService = dateService;
2270
+ unapplyAnimations(chartsCore) {
2271
+ if (this.AnimationsAreLoaded) {
2272
+ this.log("CORE: Animations in use, unapplying theme " + ChartThemes.animated);
2273
+ chartsCore.unuseTheme(this.themeCache[ChartThemes.animated]);
2274
+ this.AnimationsAreLoaded = false;
2275
+ }
2276
+ else
2277
+ this.log("CORE: Animations already unused, no need to unapply them");
2278
+ return new Promise((resolve) => { resolve(true); });
2289
2279
  }
2290
2280
  /**
2291
- * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
2281
+ * Applica il tema specificato all'istanza globale di amCharts
2282
+ *
2283
+ * @param {Object} chartsCore Istanza globale di amCharts
2284
+ * @param {'spiritedaway' | 'moonrisekingdom' | 'frozen' | 'dark' | 'kelly' | 'material' | 'dataviz' | 'none'} theme Tema da applicare
2285
+ * @returns {Promise} Promise che identifica la fine del caricamento
2292
2286
  */
2293
- getSpecificPropertiesToCheck() {
2294
- return ["Data", "DataArray", "Step", "DataGroupBucketSize", "DataGroupingThreshold", "StrokeSize", "Stacked", "AllowGaps", "MergeDatasets", "FinalInstants", "Fill", "Min", "Max"];
2287
+ applyTheme(chartsCore, theme) {
2288
+ // Ultimo tema applicato è lo stesso che mi è stato richiesto di applicare --> NO-OP
2289
+ if (this.LastLoadedTheme == theme) {
2290
+ this.log("CORE: theme already applied " + theme);
2291
+ return new Promise((resolve) => { resolve(true); });
2292
+ }
2293
+ // Scarico il tema precedente a prescindere, ormai non mi serve più
2294
+ this.unapplyPreviousTheme(chartsCore);
2295
+ // Il tema è il none --> registro la cosa e basta, il tema precedente è stato rimosso subito qui sopra ^
2296
+ if (theme == ChartThemes.none) {
2297
+ this.LastLoadedTheme = ChartThemes.none;
2298
+ return new Promise((resolve) => { resolve(true); });
2299
+ }
2300
+ // Il tema è diverso dal precedente e non è il tema vuoto --> Importo il tema specificato se non presente in memoria e lo applico al grafico attuale
2301
+ return this.importIfNeeded('themes', theme).then(() => {
2302
+ this.log("CORE: Applying theme " + theme);
2303
+ chartsCore.useTheme(this.themeCache[theme]);
2304
+ this.LastLoadedTheme = theme;
2305
+ });
2295
2306
  }
2296
2307
  /**
2297
- * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
2308
+ * De-applica il tema precedente dall'istanza globale di amCharts
2298
2309
  *
2299
- * @returns {LineChartSettings} Settings castati al tipo giusto
2310
+ * @param {Object} chartsCore Istanza globale di amCharts
2300
2311
  */
2301
- getCastedSettings() {
2302
- return (this.Settings ?? new LineChartSettings());
2312
+ unapplyPreviousTheme(chartsCore) {
2313
+ if (!this.LastLoadedTheme || this.LastLoadedTheme == ChartThemes.none)
2314
+ return;
2315
+ this.log("CORE: Unapplying previously used theme " + this.LastLoadedTheme);
2316
+ chartsCore.unuseTheme(this.themeCache[this.LastLoadedTheme]);
2303
2317
  }
2304
2318
  /**
2305
- * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
2319
+ * Applica il locale specificato all'istanza specifica del grafico
2306
2320
  *
2307
- * @param {LineChartSettings} settingsCasted Settings castati al tipo giusto
2321
+ * @param {amCharts.Chart} chart Istanza specifica del grafico a cui applicare il locale
2322
+ * @param {string} locale Locale da applicare
2323
+ * @returns {Promise} Promise che identifica la fine del caricamento
2308
2324
  */
2309
- fillSpecificSettings(settingsCasted) {
2310
- settingsCasted.Step = settingsCasted.Step != null ? settingsCasted.Step : this.Step;
2311
- settingsCasted.DataGroupBucketSize = settingsCasted.DataGroupBucketSize != null ? settingsCasted.DataGroupBucketSize : this.DataGroupBucketSize;
2312
- settingsCasted.StrokeSize = settingsCasted.StrokeSize != null ? settingsCasted.StrokeSize : this.StrokeSize;
2313
- settingsCasted.DataGroupingThreshold = settingsCasted.DataGroupingThreshold != null ? settingsCasted.DataGroupingThreshold : this.DataGroupingThreshold;
2314
- settingsCasted.AllowGaps = settingsCasted.AllowGaps != null ? settingsCasted.AllowGaps : this.AllowGaps;
2315
- settingsCasted.MergeDatasets = settingsCasted.MergeDatasets != null ? settingsCasted.MergeDatasets : this.MergeDatasets;
2316
- settingsCasted.FinalInstants = settingsCasted.FinalInstants != null ? settingsCasted.FinalInstants : this.FinalInstants;
2317
- settingsCasted.Min = settingsCasted.Min != null ? settingsCasted.Min : this.Min;
2318
- settingsCasted.Max = settingsCasted.Max != null ? settingsCasted.Max : this.Max;
2319
- settingsCasted.Fill = settingsCasted.Fill != null ? settingsCasted.Fill : this.Fill;
2320
- settingsCasted.Stacked = settingsCasted.Stacked != null ? settingsCasted.Stacked : this.Stacked;
2325
+ applyLocale(chart, locale) {
2326
+ return this.importIfNeeded('lang', locale).then(() => {
2327
+ this.log("Chart " + chart.htmlContainer.id + ": applying locale " + locale);
2328
+ chart.language.locale = this.localizationCache[locale];
2329
+ });
2321
2330
  }
2322
2331
  /**
2323
- * Effettua il rendering di questo grafico in base ai Settings
2332
+ * Permette di importare, se serve un dato tema o localizzazione
2324
2333
  *
2325
- * @param {LineChartSettings} settingsCasted Impostazioni di graficazione
2326
- * @returns {LineChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
2334
+ * @param {'lang' | 'themes'} what Oggetto da importare, se localizzazione o tema
2335
+ * @param {string} item Chiave dell'oggetto da importare
2336
+ *
2337
+ * @returns {Promise} Promise che identifica la fine del caricamento
2327
2338
  */
2328
- graphicate(settingsCasted) {
2329
- return new LineChartService(this.adapter, this.dateService).graphicate(this.Data, settingsCasted);
2339
+ importIfNeeded(what, item) {
2340
+ // Se sto cercando di caricare qualcosa di già caricato non faccio nulla
2341
+ if (!(what == 'themes' && !this.themeCache[item]) && !(what == 'lang' && !this.localizationCache[item])) {
2342
+ this.log("CORE: " + (what == 'lang' ? "Language " : "Theme ") + item + " already loaded");
2343
+ return new Promise((resolve) => { resolve(true); });
2344
+ }
2345
+ this.log("CORE: Loading " + (what == 'lang' ? "language " : "theme ") + item);
2346
+ /*
2347
+ * ****************************
2348
+ * ******** ATTENZIONE ********
2349
+ * ****************************
2350
+ *
2351
+ * Se stai vedendo questo codice di import e stai valutando di riscriverlo come:
2352
+ *
2353
+ * V V
2354
+ * import(`@amcharts/amcharts4/${what}/${item}`).then(module => {
2355
+ * if (what == 'themes') this.themeCache[item] = module.default;
2356
+ * else if (what == 'lang') this.localizationCache[item] = module.default;
2357
+ * });
2358
+ *
2359
+ * Sappi che è una pessima idea. Gli import sono valutati da webpack in compiletime per generare i chunk,
2360
+ * mettere la navigazione agli import con la concatenazione viene preso malissimo ed essenzialmente dice a webpack
2361
+ * di tirare su e bundlare l'intera node_modules. Divertente, no?
2362
+ *
2363
+ */
2364
+ switch (what) {
2365
+ case 'themes':
2366
+ switch (item) {
2367
+ case ChartThemes.spiritedaway:
2368
+ return import('@amcharts/amcharts4/themes/spiritedaway').then(theme => this.themeCache[item] = theme.default);
2369
+ case ChartThemes.moonrisekingdom:
2370
+ return import('@amcharts/amcharts4/themes/moonrisekingdom').then(theme => this.themeCache[item] = theme.default);
2371
+ case ChartThemes.frozen:
2372
+ return import('@amcharts/amcharts4/themes/frozen').then(theme => this.themeCache[item] = theme.default);
2373
+ case ChartThemes.dark:
2374
+ return import('@amcharts/amcharts4/themes/dark').then(theme => this.themeCache[item] = theme.default);
2375
+ case ChartThemes.kelly:
2376
+ return import('@amcharts/amcharts4/themes/kelly').then(theme => this.themeCache[item] = theme.default);
2377
+ case ChartThemes.material:
2378
+ return import('@amcharts/amcharts4/themes/material').then(theme => this.themeCache[item] = theme.default);
2379
+ case ChartThemes.dataviz:
2380
+ return import('@amcharts/amcharts4/themes/dataviz').then(theme => this.themeCache[item] = theme.default);
2381
+ case ChartThemes.animated:
2382
+ return import('@amcharts/amcharts4/themes/animated').then(theme => this.themeCache[item] = theme.default);
2383
+ }
2384
+ break;
2385
+ case 'lang':
2386
+ switch (item) {
2387
+ case 'it-IT':
2388
+ return import('@amcharts/amcharts4/lang/it_IT').then(lang => this.localizationCache[item] = lang.default);
2389
+ case 'en-US':
2390
+ return import('@amcharts/amcharts4/lang/en_US').then(lang => this.localizationCache[item] = lang.default);
2391
+ }
2392
+ }
2393
+ this.log("CORE: Loading Failed. " + (what == 'lang' ? "Language " : "Theme") + " not recognized: " + item);
2394
+ return new Promise((resolve) => { resolve(true); });
2395
+ }
2396
+ /**
2397
+ * @ignore
2398
+ */
2399
+ log(text) {
2400
+ if (this.logs)
2401
+ console.log("@esfaenza/es-charts: " + text);
2330
2402
  }
2331
2403
  }
2332
- EsLineChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsLineChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i3.DateService }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_LOCALE }, { token: ESC_THEME }], target: i0.ɵɵFactoryTarget.Component });
2333
- EsLineChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsLineChartComponent, selector: "es-line-chart", inputs: { Data: "Data", DataArray: "DataArray", Step: "Step", DataGroupBucketSize: "DataGroupBucketSize", DataGroupingThreshold: "DataGroupingThreshold", StrokeSize: "StrokeSize", AllowGaps: "AllowGaps", MergeDatasets: "MergeDatasets", FinalInstants: "FinalInstants", Min: "Min", Max: "Max", Fill: "Fill", Stacked: "Stacked" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2334
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsLineChartComponent, decorators: [{
2335
- type: Component,
2336
- args: [{ selector: 'es-line-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2337
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i3.DateService }, { type: i0.NgZone }, { type: Object, decorators: [{
2338
- type: Inject,
2339
- args: [PLATFORM_ID]
2340
- }] }, { type: undefined, decorators: [{
2404
+ ChartLoader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartLoader, deps: [{ token: ESC_LOGS }], target: i0.ɵɵFactoryTarget.Injectable });
2405
+ ChartLoader.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartLoader, providedIn: EsChartsModule });
2406
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ChartLoader, decorators: [{
2407
+ type: Injectable,
2408
+ args: [{ providedIn: EsChartsModule }]
2409
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
2341
2410
  type: Inject,
2342
2411
  args: [ESC_LOGS]
2343
- }] }, { type: undefined, decorators: [{
2344
- type: Inject,
2345
- args: [ESC_ANIMATIONS]
2346
- }] }, { type: undefined, decorators: [{
2347
- type: Inject,
2348
- args: [ESC_LOCALE]
2349
- }] }, { type: undefined, decorators: [{
2350
- type: Inject,
2351
- args: [ESC_THEME]
2352
- }] }]; }, propDecorators: { Data: [{
2353
- type: Input
2354
- }], DataArray: [{
2355
- type: Input
2356
- }], Step: [{
2357
- type: Input
2358
- }], DataGroupBucketSize: [{
2359
- type: Input
2360
- }], DataGroupingThreshold: [{
2361
- type: Input
2362
- }], StrokeSize: [{
2363
- type: Input
2364
- }], AllowGaps: [{
2365
- type: Input
2366
- }], MergeDatasets: [{
2367
- type: Input
2368
- }], FinalInstants: [{
2369
- type: Input
2370
- }], Min: [{
2371
- type: Input
2372
- }], Max: [{
2373
- type: Input
2374
- }], Fill: [{
2375
- type: Input
2376
- }], Stacked: [{
2377
- type: Input
2378
- }] } });
2412
+ }] }]; } });
2379
2413
 
2380
2414
  /**
2381
- * Componente specifico per la graficazione di un grafico a Torta
2415
+ * Componente Grafico Base che gestisce tutte le cose comuni dei vari grafici istanziabili, come la presenza o menu di una legenda,
2416
+ * il tema utilizzato, il locale del singolo grafico, ecc ecc...
2382
2417
  */
2383
- class EsPieChartComponent extends BaseChartComponent {
2384
- /**
2385
- * @ignore
2386
- */
2387
- constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME) {
2388
- super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME);
2389
- this.adapter = adapter;
2390
- }
2418
+ class BaseChartComponent {
2391
2419
  /**
2392
- * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
2420
+ * Costruttore
2421
+ *
2422
+ * @param {ElementRef} el Contenitore all'interno del cui viene creato il grafico. Utilizzato per estrapolarne la **ContainerHeight**
2423
+ * @param {Object} platformId piattaforma Angular (browser, ecc...) per essere sicuri che amcharts venga attivato solo lato browser. Non utilizzando SSR nelle applicazioni che consumano questa libreria non è particolarmente significativo, ma non si sa mai
2424
+ * @param {NgZone} zone NgZone di default per permettere di inizializzare il grafico all'infuori di Angular per avere qualche prestazione in più
2425
+ * @param {ChartLoader} Charter Istanza del Loader che si occuperà di caricare in memoria tutto ciò che serve per il grafico attuale (temi, locale, animazioni, ecc...)
2426
+ * @param {ChartDispatcher} Dispatcher Istanza del Dispatcher che si occupa di differire il caricamento dei grafici 1 dopo l'altro in modo che caricamenti pseudo paralleli incasinino tutto
2427
+ * @param {boolean} logs Indica se effettuare log a console o meno, iniettato dalle classi specializzate dal token ESC_LOGS
2428
+ * @param {boolean} animations Indica se per questo grafico devono essere attive o meno le animazioni. Impostazione generica presa dal token ESC_ANIMATIONS
2429
+ * @param {string} locale Indica il locale specifico per questo grafico. Impostazione generica presa dal LocalizationService
2430
+ * @param {string} theme Indica il tema specifico per questo grafico. Impostazione generica presa dal token ESC_THEME
2393
2431
  */
2394
- getSpecificPropertiesToCheck() {
2395
- return ["Data", "DataArray", "HideZeroes", "Mode3D", "LabelsWrap", "LabelsTruncate", "LabelsWidth", "LabelsVisible"];
2432
+ constructor(el, platformId, zone, Charter, Dispatcher, logs, animations, locale, theme) {
2433
+ this.el = el;
2434
+ this.platformId = platformId;
2435
+ this.zone = zone;
2436
+ this.Charter = Charter;
2437
+ this.Dispatcher = Dispatcher;
2438
+ this.logs = logs;
2439
+ this.animations = animations;
2440
+ this.locale = locale;
2441
+ this.theme = theme;
2442
+ /**
2443
+ * Nome del grafico, fondamentale assegnarlo per permettere alla libreria di schedularne la creazione
2444
+ */
2445
+ this.name = "";
2446
+ /**
2447
+ * Dopo aver navigato a un nuovo grafico verranno attesi questi millisecondi prima di richiedere i dati attraverso la **DataRetrieve**.
2448
+ *
2449
+ * Questo per evitare che l'utente cliccando velocemente "avanti" generi tonnellate di richieste inutili
2450
+ */
2451
+ this.BrowseDelayMs = 500;
2452
+ /**
2453
+ * Evento lanciato sulla selezione di un range di dati o dalla timeline o dal grafico. Valido per tutti i grafici che supportano serie basate sulle date
2454
+ */
2455
+ this.onSelectionChanged = new EventEmitter();
2456
+ /**
2457
+ * Evento lanciato dal click di una serie dalla Legenda, a patto che l'Input **HideSeriesOnLabelClick** sia impostato a false
2458
+ */
2459
+ this.onSeriesClicked = new EventEmitter();
2460
+ /**
2461
+ * Evento lanciato all'inizio del caricamento di una nuova pagina del grafico
2462
+ */
2463
+ this.onLoadStart = new EventEmitter();
2464
+ /**
2465
+ * Evento lanciato al termine del caricamento di una nuova pagina del grafico
2466
+ */
2467
+ this.onLoadEnd = new EventEmitter();
2468
+ /**
2469
+ * Evento lanciato al termine della creazione del grafico referenziando l'istanza nativa del grafico creato in modo da poter effettuare modifiche
2470
+ * post inizializzazione lato applicativo
2471
+ */
2472
+ this.chartLoaded = new EventEmitter();
2473
+ /**
2474
+ * Serve a decidere se sarà presente l'interfaccia di paginazione
2475
+ */
2476
+ this.isPaged = false;
2477
+ /**
2478
+ * @ignore
2479
+ */
2480
+ this.initDone = false;
2396
2481
  }
2397
2482
  /**
2398
- * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
2483
+ * Metodo di inizializzazione post valorizzazione degli input, utilizzato per valorizzare correttamente le proprietà essenziali del grafico (Animazioni, Tema e Locale)
2399
2484
  *
2400
- * @returns {PieChartSettings} Settings castati al tipo giusto
2485
+ * Viene data priorità ai Settings (HTML), priorità secondaria agli Input diretti (Lato HTML), priorità ultima alle impostazioni globali,
2486
+ * impostate in fase di import del modulo assegnando valori ai token ESC_ANIMATIONS, ESC_THEME
2401
2487
  */
2402
- getCastedSettings() {
2403
- return (this.Settings ?? new PieChartSettings());
2488
+ ngOnInit() {
2489
+ // Qui servono solo le variabili da conoscere PRE-graficazione per il caricamento dei moduli lazy del grafico
2490
+ this.Animations = this.Settings?.Animations != null ? this.Settings?.Animations : (this.Animations != null ? this.Animations : this.animations);
2491
+ this.Theme = this.Settings?.Theme != null ? this.Settings?.Theme : (this.Theme != null ? this.Theme : this.theme);
2492
+ this.Locale = this.Settings?.Locale != null ? this.Settings?.Locale : (this.Locale != null ? this.Locale : this.locale);
2493
+ this.isPaged = (this.DataArray && this.DataArray.length > 0 && !this.Data) || (this.DataDtos && this.DataDtos.length > 0 && !!this.DataRetrieve);
2494
+ this.log("Chart " + this.name + ": ngOnInit");
2404
2495
  }
2405
2496
  /**
2406
- * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
2497
+ * Implementazione utilizzata per controllare eventuali proprietà chiave del grafico e rigraficare tutto qualora si rivelasse necessario
2407
2498
  *
2408
- * @param {PieChartSettings} settingsCasted Settings castati al tipo giusto
2499
+ * @param {SimpleChanges} changes Indicazione dei cambiamenti sulle proprietà del grafico. Vedere documentazione Angular in merito
2409
2500
  */
2410
- fillSpecificSettings(settingsCasted) {
2411
- settingsCasted.HideZeroes = settingsCasted.HideZeroes != null ? settingsCasted.HideZeroes : this.HideZeroes;
2412
- settingsCasted.Mode3D = settingsCasted.Mode3D != null ? settingsCasted.Mode3D : this.Mode3D;
2413
- settingsCasted.DonutRadiusPercentage = settingsCasted.DonutRadiusPercentage != null ? settingsCasted.DonutRadiusPercentage : this.DonutRadiusPercentage;
2414
- settingsCasted.LabelsWrap = settingsCasted.LabelsWrap != null ? settingsCasted.LabelsWrap : this.LabelsWrap;
2415
- settingsCasted.LabelsTruncate = settingsCasted.LabelsTruncate != null ? settingsCasted.LabelsTruncate : this.LabelsTruncate;
2416
- settingsCasted.LabelsWidth = settingsCasted.LabelsWidth != null ? settingsCasted.LabelsWidth : this.LabelsWidth;
2417
- settingsCasted.LabelsVisible = settingsCasted.LabelsVisible != null ? settingsCasted.LabelsVisible : this.LabelsVisible;
2501
+ ngOnChanges(changes) {
2502
+ if (!this.initDone)
2503
+ return;
2504
+ this.log("Chart " + this.name + ": ngOnChanges");
2505
+ let propsToCheck = ["Timeline", "Legend", "Settings", "Animations", "Theme", "Locale", ...this.getSpecificPropertiesToCheck()];
2506
+ this.checkPropertiesAndRegraphicateAsNeeded(changes, propsToCheck);
2418
2507
  }
2419
2508
  /**
2420
- * Effettua il rendering di questo grafico in base ai Settings
2421
- *
2422
- * @param {PieChartSettings} settingsCasted Impostazioni di graficazione
2423
- * @returns {PieChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
2509
+ * Nel post inizializzazione, a patto che mi trovi in ambiente "browser", proseguo al caricamento del grafico sull'HTML
2424
2510
  */
2425
- graphicate(settingsCasted) {
2426
- return new PieChartService(this.adapter).graphicate(this.Data, settingsCasted);
2511
+ ngAfterViewInit() {
2512
+ if (!this.name)
2513
+ throw "a Unique name is mandatory to create a chart";
2514
+ this.log("Chart " + this.name + ": ngAfterViewInit, graphicating chart outside Angular");
2515
+ if (!this.isPaged)
2516
+ this.dispatchLoadChart();
2427
2517
  }
2428
- }
2429
- EsPieChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsPieChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_LOCALE }, { token: ESC_THEME }], target: i0.ɵɵFactoryTarget.Component });
2430
- EsPieChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsPieChartComponent, selector: "es-pie-chart", inputs: { Data: "Data", DataArray: "DataArray", HideZeroes: "HideZeroes", Mode3D: "Mode3D", DonutRadiusPercentage: "DonutRadiusPercentage", LabelsWrap: "LabelsWrap", LabelsTruncate: "LabelsTruncate", LabelsWidth: "LabelsWidth", LabelsVisible: "LabelsVisible" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2431
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsPieChartComponent, decorators: [{
2432
- type: Component,
2433
- args: [{ selector: 'es-pie-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2434
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2435
- type: Inject,
2436
- args: [PLATFORM_ID]
2437
- }] }, { type: undefined, decorators: [{
2438
- type: Inject,
2439
- args: [ESC_LOGS]
2440
- }] }, { type: undefined, decorators: [{
2441
- type: Inject,
2442
- args: [ESC_ANIMATIONS]
2443
- }] }, { type: undefined, decorators: [{
2444
- type: Inject,
2445
- args: [ESC_LOCALE]
2446
- }] }, { type: undefined, decorators: [{
2447
- type: Inject,
2448
- args: [ESC_THEME]
2449
- }] }]; }, propDecorators: { Data: [{
2450
- type: Input
2451
- }], DataArray: [{
2452
- type: Input
2453
- }], HideZeroes: [{
2454
- type: Input
2455
- }], Mode3D: [{
2456
- type: Input
2457
- }], DonutRadiusPercentage: [{
2458
- type: Input
2459
- }], LabelsWrap: [{
2460
- type: Input
2461
- }], LabelsTruncate: [{
2462
- type: Input
2463
- }], LabelsWidth: [{
2464
- type: Input
2465
- }], LabelsVisible: [{
2466
- type: Input
2467
- }] } });
2468
-
2469
- /**
2470
- * Componente specifico per la graficazione di un grafico a Barre con due dimensioni
2471
- */
2472
- class EsVertical2DChartComponent extends BaseChartComponent {
2473
2518
  /**
2474
- * @ignore
2519
+ * All'onDestroy scarico il grafico per liberare memoria
2475
2520
  */
2476
- constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME) {
2477
- super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME);
2478
- this.adapter = adapter;
2521
+ ngOnDestroy() {
2522
+ if (this.Chart) {
2523
+ this.log("Chart " + this.name + ": Unloading destroyed chart");
2524
+ this.browserOnly(() => { this.Chart.dispose(); this.Dispatcher.deregisterGraph(this.name); });
2525
+ }
2526
+ else
2527
+ this.log("Chart " + this.name + ": Unloading uncreated chart component. It probably was a duplicated");
2479
2528
  }
2480
2529
  /**
2481
- * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
2530
+ * Registra il grafico attuale nel Dispatcher in modo che venga caricato appena possibile
2482
2531
  */
2483
- getSpecificPropertiesToCheck() {
2484
- return ["Data", "DataArray"];
2532
+ dispatchLoadChart() {
2533
+ this.browserOnly(() => {
2534
+ this.Dispatcher.register(this.name, () => { return this.loadChart(); });
2535
+ });
2485
2536
  }
2486
2537
  /**
2487
- * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
2538
+ * Il caricamento del grafico funziona nel seguente modo:
2488
2539
  *
2489
- * @returns {Vertical2DChartSettings} Settings castati al tipo giusto
2490
- */
2491
- getCastedSettings() {
2492
- return (this.Settings ?? new Vertical2DChartSettings());
2493
- }
2494
- /**
2495
- * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
2540
+ * 1) Caricamento del tema e delle animazioni, qualora necessari
2496
2541
  *
2497
- * @param {Vertical2DChartSettings} settingsCasted Settings castati al tipo giusto
2498
- */
2499
- fillSpecificSettings(settingsCasted) {
2500
- settingsCasted.ColumnWidthPercentage = settingsCasted.ColumnWidthPercentage != null ? settingsCasted.ColumnWidthPercentage : this.ColumnWidthPercentage;
2501
- settingsCasted.GroupPaddingPercentage = settingsCasted.GroupPaddingPercentage != null ? settingsCasted.GroupPaddingPercentage : this.GroupPaddingPercentage;
2502
- settingsCasted.LabelWidth = settingsCasted.LabelWidth != null ? settingsCasted.LabelWidth : this.LabelWidth;
2503
- settingsCasted.LabelVerticalOrientationCutoffWidth = settingsCasted.LabelVerticalOrientationCutoffWidth != null ? settingsCasted.LabelVerticalOrientationCutoffWidth : this.LabelVerticalOrientationCutoffWidth;
2504
- settingsCasted.LabelRightWhenCompressed = settingsCasted.LabelRightWhenCompressed != null ? settingsCasted.LabelRightWhenCompressed : this.LabelRightWhenCompressed;
2505
- settingsCasted.LabelTopWhenCompressed = settingsCasted.LabelTopWhenCompressed != null ? settingsCasted.LabelTopWhenCompressed : this.LabelTopWhenCompressed;
2506
- }
2507
- /**
2508
- * Effettua il rendering di questo grafico in base ai Settings
2542
+ * 2) Caricamento delle impostazioni specifiche e integrazione con le impostazioni generiche
2509
2543
  *
2510
- * @param {Vertical2DChartSettings} settingsCasted Impostazioni di graficazione
2511
- * @returns {Vertical2DChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
2544
+ * 3) Graficazione
2545
+ *
2546
+ * 4) Caricamento del locale
2512
2547
  */
2513
- graphicate(settingsCasted) {
2514
- return new Vertical2DChartService(this.adapter).graphicate(this.Data, settingsCasted);
2548
+ loadChart() {
2549
+ this.log("Chart " + this.name + ": Start loading Modules if needed");
2550
+ return Promise.all([
2551
+ this.setupAmChartsThemes().then(() => {
2552
+ this.log("Chart " + this.name + ": Graphicating after modules load");
2553
+ var castedSettings = this.getCastedSettings();
2554
+ this.fillSettings(castedSettings);
2555
+ this.fillSpecificSettings(castedSettings);
2556
+ this.ChartService = this.graphicate(castedSettings);
2557
+ this.Chart = this.ChartService.ChartInstance;
2558
+ if (!this.Chart)
2559
+ this.log("Chart " + this.name + ": Could not create graph");
2560
+ // Unico punto reale in cui viene utilizzato il locale, tehe
2561
+ return this.Charter.applyLocale(this.Chart, this.Locale).then(() => { this.initDone = true; this.chartLoaded.emit(this); });
2562
+ })
2563
+ ]);
2515
2564
  }
2516
- }
2517
- EsVertical2DChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVertical2DChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_LOCALE }, { token: ESC_THEME }], target: i0.ɵɵFactoryTarget.Component });
2518
- EsVertical2DChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsVertical2DChartComponent, selector: "es-vertical-2d-chart", inputs: { Data: "Data", DataArray: "DataArray", ColumnWidthPercentage: "ColumnWidthPercentage", GroupPaddingPercentage: "GroupPaddingPercentage", LabelWidth: "LabelWidth", LabelVerticalOrientationCutoffWidth: "LabelVerticalOrientationCutoffWidth", LabelRightWhenCompressed: "LabelRightWhenCompressed", LabelTopWhenCompressed: "LabelTopWhenCompressed" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2519
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVertical2DChartComponent, decorators: [{
2520
- type: Component,
2521
- args: [{ selector: 'es-vertical-2d-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2522
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2523
- type: Inject,
2524
- args: [PLATFORM_ID]
2525
- }] }, { type: undefined, decorators: [{
2526
- type: Inject,
2527
- args: [ESC_LOGS]
2528
- }] }, { type: undefined, decorators: [{
2529
- type: Inject,
2530
- args: [ESC_ANIMATIONS]
2531
- }] }, { type: undefined, decorators: [{
2532
- type: Inject,
2533
- args: [ESC_LOCALE]
2534
- }] }, { type: undefined, decorators: [{
2535
- type: Inject,
2536
- args: [ESC_THEME]
2537
- }] }]; }, propDecorators: { Data: [{
2538
- type: Input
2539
- }], DataArray: [{
2540
- type: Input
2541
- }], ColumnWidthPercentage: [{
2542
- type: Input
2543
- }], GroupPaddingPercentage: [{
2544
- type: Input
2545
- }], LabelWidth: [{
2546
- type: Input
2547
- }], LabelVerticalOrientationCutoffWidth: [{
2548
- type: Input
2549
- }], LabelRightWhenCompressed: [{
2550
- type: Input
2551
- }], LabelTopWhenCompressed: [{
2552
- type: Input
2553
- }] } });
2554
-
2555
- /**
2556
- * Componente specifico per la graficazione di un grafico a Barre
2557
- */
2558
- class EsVerticalChartComponent extends BaseChartComponent {
2559
2565
  /**
2560
- * @ignore
2566
+ * Riempimento delle impostazioni nella classe Settings. Si danno priorità ai valori già impostati nei Settings,
2567
+ * integrando eventualmente con le proprietà del grafico
2568
+ *
2569
+ * @param {BaseSettings} settings Impostazioni base ricevute dalla specializzazione del grafico
2561
2570
  */
2562
- constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME) {
2563
- super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME);
2564
- this.adapter = adapter;
2571
+ fillSettings(settings) {
2572
+ // Merge degli Input con i Settings, dando priorità ai Settings
2573
+ settings.Theme = settings.Theme ? settings.Theme : this.Theme;
2574
+ settings.Locale = settings.Locale ? settings.Locale : this.Locale;
2575
+ settings.Animations = settings.Animations != null ? settings.Animations : this.Animations;
2576
+ settings.Legend = settings.Legend != null ? settings.Legend : this.Legend;
2577
+ settings.Name = settings.Name ? settings.Name : this.name;
2578
+ settings.Timeline = settings.Timeline != null ? settings.Timeline : this.Timeline;
2579
+ settings.AdaptLabelSizeAndOrientation = settings.AdaptLabelSizeAndOrientation != null ? settings.AdaptLabelSizeAndOrientation : this.AdaptLabelSizeAndOrientation;
2580
+ settings.XAxisTitle = settings.XAxisTitle ? settings.XAxisTitle : this.XTitle;
2581
+ settings.YAxisTitle = settings.YAxisTitle ? settings.YAxisTitle : this.YTitle;
2582
+ settings.LegendPosition = settings.LegendPosition ? settings.LegendPosition : this.LegendPosition;
2583
+ settings.HideSeriesOnLabelClick = settings.HideSeriesOnLabelClick != null ? settings.HideSeriesOnLabelClick : this.HideSeriesOnLabelClick;
2584
+ settings.MinGridDistance = settings.MinGridDistance != null ? settings.MinGridDistance : this.MinGridDistance;
2585
+ settings.LegendPadding = settings.LegendPadding ? settings.LegendPadding : this.LegendPadding ?? null;
2586
+ settings.ContainerHeight = this.el.nativeElement.parentElement.offsetHeight;
2587
+ settings.OnSeriesClickCallback = (series) => { this.onSeriesClicked.emit(series); };
2588
+ settings.OnSelectionChangedCallback = (event) => { this.onSelectionChanged.emit({ from: event.from, to: event.to, initial: event.initial }); };
2565
2589
  }
2566
2590
  /**
2567
- * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
2591
+ * Controlla i cambiamenti avvenuti alle proprietà chiave e rieffettua la graficazione qualora necessario
2592
+ *
2593
+ * @param {SimpleChanges} changes Indicazione della modifiche avvenute nei vari Input
2594
+ * @param {string[]} propsToCheck Lista degli Input da controllare per cui una modifica causa una rigraficazione
2568
2595
  */
2569
- getSpecificPropertiesToCheck() {
2570
- return ["Data", "DataArray"];
2596
+ checkPropertiesAndRegraphicateAsNeeded(changes, propsToCheck) {
2597
+ let toReGraphicate = false;
2598
+ for (let i = 0; i < propsToCheck.length; i++)
2599
+ toReGraphicate = toReGraphicate || (changes[propsToCheck[i]] && changes[propsToCheck[i]].currentValue);
2600
+ if (toReGraphicate)
2601
+ this.reloadChart();
2571
2602
  }
2572
2603
  /**
2573
- * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
2604
+ * Funzione che effettua un cambio di pagina per i grafici paginati. Qualora **data** fosse nullo significa che è iniziato un caricamento
2605
+ * e anche lato applicativo il DataRetrieve dovrà considerare che l'assenza di valori non è altro che un'indicazione di inizio caricamento
2606
+ *
2607
+ * Il caricamento di qualsiasi pagina genererà comunque una primo evento con **data** nullo in modo da indicare l'inizio caricamento e
2608
+ * in seconda istanza un altro evento in cui **data** sarà sempre valorizzato, o con il Dto da usare per recuperare i dati, o con i dati
2609
+ * veri e propri già presenti nel **DataArray**
2610
+ *
2611
+ * I callback **onLoadStart** e **onLoadEnd** vengono sempre chiamati
2574
2612
  *
2575
- * @returns {VerticalChartSettings} Settings castati al tipo giusto
2613
+ * @param {{ data: LineChartData | PieChartData | Vertical2DChartData | VerticalChartData | any, index: number }} nd Indice del caricamento dati, con eventualmente già i dati se disponibili
2576
2614
  */
2577
- getCastedSettings() {
2578
- return (this.Settings ?? new VerticalChartSettings());
2615
+ changePage(nd) {
2616
+ if (!nd.data) {
2617
+ this.loadingChart = true;
2618
+ // Serve per informare l'applicativo in listening sull'indice attualmente in visualizzazione.
2619
+ // La mancanza di dati indica che non devono essere effettuate ricerche per ora
2620
+ if (this.DataRetrieve)
2621
+ this.DataRetrieve(null, nd.index);
2622
+ this.onLoadStart.emit();
2623
+ return;
2624
+ }
2625
+ if (this.DataRetrieve)
2626
+ this.DataRetrieve(nd.data, nd.index).then(t => { this.changePageDataReceived(t); });
2627
+ else
2628
+ this.changePageDataReceived(nd.data);
2579
2629
  }
2580
2630
  /**
2581
- * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
2631
+ * Al termine del caricamento dei dati di una pagina questo metodo viene chiamato per rigraficare la situazione con i nuovi dati
2582
2632
  *
2583
- * @param {VerticalChartSettings} settingsCasted Settings castati al tipo giusto
2633
+ * @param {LineChartData | PieChartData | Vertical2DChartData | VerticalChartData | any} data Dati del grafico
2584
2634
  */
2585
- fillSpecificSettings(settingsCasted) {
2586
- settingsCasted.ColumnWidthPercentage = settingsCasted.ColumnWidthPercentage != null ? settingsCasted.ColumnWidthPercentage : this.ColumnWidthPercentage;
2587
- settingsCasted.LabelWidth = settingsCasted.LabelWidth != null ? settingsCasted.LabelWidth : this.LabelWidth;
2588
- settingsCasted.LabelVerticalOrientationCutoffWidth = settingsCasted.LabelVerticalOrientationCutoffWidth != null ? settingsCasted.LabelVerticalOrientationCutoffWidth : this.LabelVerticalOrientationCutoffWidth;
2589
- settingsCasted.LabelRightWhenCompressed = settingsCasted.LabelRightWhenCompressed != null ? settingsCasted.LabelRightWhenCompressed : this.LabelRightWhenCompressed;
2590
- settingsCasted.LabelTopWhenCompressed = settingsCasted.LabelTopWhenCompressed != null ? settingsCasted.LabelTopWhenCompressed : this.LabelTopWhenCompressed;
2635
+ changePageDataReceived(data) {
2636
+ this.loadingChart = false;
2637
+ this.onLoadEnd.emit();
2638
+ let firstBind = !this.Data;
2639
+ this.Data = data;
2640
+ if (!firstBind)
2641
+ this.reloadChart();
2642
+ else
2643
+ this.dispatchLoadChart();
2591
2644
  }
2592
2645
  /**
2593
- * Effettua il rendering di questo grafico in base ai Settings
2646
+ * Ricarica il grafico distruggendo il vecchio e ricreando il nuovo
2594
2647
  *
2595
- * @param {VerticalChartSettings} settingsCasted Impostazioni di graficazione
2596
- * @returns {VerticalChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
2648
+ * Le chiamate a questo metodo possono essere trasformate in chiamate al metodo **graphicate** della Service, se solo quel metodo fosse abbastanza intelligente per capire
2649
+ * le differenze fra il grafico com'era prima e come deve diventare, in modo da non ricrearlo ma semplicemente modificare quello che già è disegnato
2597
2650
  */
2598
- graphicate(settingsCasted) {
2599
- return new VerticalChartService(this.adapter).graphicate(this.Data, settingsCasted);
2651
+ reloadChart() {
2652
+ this.browserOnly(() => { if (!this.Chart.isDisposed())
2653
+ this.Chart.dispose(); this.Dispatcher.deregisterGraph(this.name); });
2654
+ this.Dispatcher.register(this.name, () => { return this.loadChart(); });
2600
2655
  }
2601
- }
2602
- EsVerticalChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_LOCALE }, { token: ESC_THEME }], target: i0.ɵɵFactoryTarget.Component });
2603
- EsVerticalChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsVerticalChartComponent, selector: "es-vertical-chart", inputs: { Data: "Data", DataArray: "DataArray", ColumnWidthPercentage: "ColumnWidthPercentage", LabelWidth: "LabelWidth", LabelVerticalOrientationCutoffWidth: "LabelVerticalOrientationCutoffWidth", LabelRightWhenCompressed: "LabelRightWhenCompressed", LabelTopWhenCompressed: "LabelTopWhenCompressed" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2604
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalChartComponent, decorators: [{
2605
- type: Component,
2606
- args: [{ selector: 'es-vertical-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2607
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2608
- type: Inject,
2609
- args: [PLATFORM_ID]
2610
- }] }, { type: undefined, decorators: [{
2611
- type: Inject,
2612
- args: [ESC_LOGS]
2613
- }] }, { type: undefined, decorators: [{
2614
- type: Inject,
2615
- args: [ESC_ANIMATIONS]
2616
- }] }, { type: undefined, decorators: [{
2617
- type: Inject,
2618
- args: [ESC_LOCALE]
2619
- }] }, { type: undefined, decorators: [{
2620
- type: Inject,
2621
- args: [ESC_THEME]
2622
- }] }]; }, propDecorators: { Data: [{
2623
- type: Input
2624
- }], DataArray: [{
2625
- type: Input
2626
- }], ColumnWidthPercentage: [{
2627
- type: Input
2628
- }], LabelWidth: [{
2629
- type: Input
2630
- }], LabelVerticalOrientationCutoffWidth: [{
2631
- type: Input
2632
- }], LabelRightWhenCompressed: [{
2633
- type: Input
2634
- }], LabelTopWhenCompressed: [{
2635
- type: Input
2636
- }] } });
2637
-
2638
- /**
2639
- * Componente specifico per la graficazione di un grafico a Barre in modalità Stacked (una serie sopra l'altra)
2640
- */
2641
- class EsVerticalStackedChartComponent extends BaseChartComponent {
2642
2656
  /**
2643
- * @ignore
2657
+ * Permette di aggiungere un blocco di dati in maniera "live" ad un grafico
2644
2658
  */
2645
- constructor(el, ChartLoader, ChartDispatcher, adapter, zone, platformId, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME) {
2646
- super(el, platformId, zone, ChartLoader, ChartDispatcher, ESC_LOGS, ESC_ANIMATIONS, ESC_LOCALE, ESC_THEME);
2647
- this.adapter = adapter;
2659
+ addData(chartData) {
2660
+ this.ChartService.refreshData(chartData);
2648
2661
  }
2662
+ ;
2649
2663
  /**
2650
- * Ottiene le proprietà specifiche per questa tipologia di grafico per cui serve rigraficare
2664
+ * Funzione che si occupa di caricare i temi necessari per il grafico in oggetto. Prima applica il tema, poi, se serve, applica le animazioni
2651
2665
  */
2652
- getSpecificPropertiesToCheck() {
2653
- return ["Data", "DataArray"];
2666
+ setupAmChartsThemes() {
2667
+ return Promise.all([
2668
+ this.Charter.applyTheme(am4core, this.Theme).then(() => {
2669
+ return this.Animations ? this.Charter.applyAnimations(am4core) : this.Charter.unapplyAnimations(am4core);
2670
+ })
2671
+ ]);
2654
2672
  }
2655
2673
  /**
2656
- * Ottiene i Settings (Ereditati dalla classe base, quindi del tipo generico **BaseSettings**) castati al tipo specifico per questo grafico
2657
- *
2658
- * @returns {VerticalStackedChartSettings} Settings castati al tipo giusto
2674
+ * @ignore
2659
2675
  */
2660
- getCastedSettings() {
2661
- return (this.Settings ?? new VerticalStackedChartSettings());
2676
+ log(log) {
2677
+ if (this.logs)
2678
+ console.log("@esfaenza/es-charts: " + log);
2662
2679
  }
2663
2680
  /**
2664
- * Integra i Settings base con tutti gli Input specifici di questo grafico, dando priorità ai Settings se definiti
2681
+ * Imposta lo zoom dal **from** al **to**
2665
2682
  *
2666
- * @param {VerticalStackedChartSettings} settingsCasted Settings castati al tipo giusto
2683
+ * @param {Date} from Inizio dello zoom
2684
+ * @param {Date} to Fine dello zoom
2667
2685
  */
2668
- fillSpecificSettings(settingsCasted) {
2669
- settingsCasted.ColumnWidthPercentage = settingsCasted.ColumnWidthPercentage != null ? settingsCasted.ColumnWidthPercentage : this.ColumnWidthPercentage;
2670
- settingsCasted.LabelWidth = settingsCasted.LabelWidth != null ? settingsCasted.LabelWidth : this.LabelWidth;
2671
- settingsCasted.LabelVerticalOrientationCutoffWidth = settingsCasted.LabelVerticalOrientationCutoffWidth != null ? settingsCasted.LabelVerticalOrientationCutoffWidth : this.LabelVerticalOrientationCutoffWidth;
2672
- settingsCasted.LabelRightWhenCompressed = settingsCasted.LabelRightWhenCompressed != null ? settingsCasted.LabelRightWhenCompressed : this.LabelRightWhenCompressed;
2673
- settingsCasted.LabelTopWhenCompressed = settingsCasted.LabelTopWhenCompressed != null ? settingsCasted.LabelTopWhenCompressed : this.LabelTopWhenCompressed;
2686
+ setSelection(from, to) {
2687
+ this.ChartService.setSelection(from, to);
2674
2688
  }
2675
2689
  /**
2676
- * Effettua il rendering di questo grafico in base ai Settings
2677
- *
2678
- * @param {VerticalStackedChartSettings} settingsCasted Impostazioni di graficazione
2679
- * @returns {VerticalStackedChartService} La service utilizzata per il rendering nello stato subito successivo al rendering effettuato
2690
+ * @ignore
2680
2691
  */
2681
- graphicate(settingsCasted) {
2682
- return new VerticalStackedChartService(this.adapter).graphicate(this.Data, settingsCasted);
2692
+ browserOnly(f) {
2693
+ if (isPlatformBrowser(this.platformId)) {
2694
+ this.zone.runOutsideAngular(() => {
2695
+ f();
2696
+ });
2697
+ }
2683
2698
  }
2684
2699
  }
2685
- EsVerticalStackedChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalStackedChartComponent, deps: [{ token: i0.ElementRef }, { token: ChartLoader }, { token: ChartDispatcher }, { token: BaseAdapter }, { token: i0.NgZone }, { token: PLATFORM_ID }, { token: ESC_LOGS }, { token: ESC_ANIMATIONS }, { token: ESC_LOCALE }, { token: ESC_THEME }], target: i0.ɵɵFactoryTarget.Component });
2686
- EsVerticalStackedChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: EsVerticalStackedChartComponent, selector: "es-vertical-stacked-chart", inputs: { Data: "Data", DataArray: "DataArray", ColumnWidthPercentage: "ColumnWidthPercentage", LabelWidth: "LabelWidth", LabelVerticalOrientationCutoffWidth: "LabelVerticalOrientationCutoffWidth", LabelRightWhenCompressed: "LabelRightWhenCompressed", LabelTopWhenCompressed: "LabelTopWhenCompressed" }, usesInheritance: true, ngImport: i0, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PageChartSelector, selector: "chart-pager", inputs: ["Items", "Dtos", "BrowseDelayMs", "StartIndex"], outputs: ["onPageChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2687
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsVerticalStackedChartComponent, decorators: [{
2688
- type: Component,
2689
- args: [{ selector: 'es-vertical-stacked-chart', changeDetection: ChangeDetectionStrategy.OnPush, template: "<chart-pager *ngIf=\"isPaged\" (onPageChange)=\"changePage($event)\" [Items]=\"DataArray\" [Dtos]=\"DataDtos\" [StartIndex]=\"DataDtoStartIndex\"\r\n [BrowseDelayMs]=\"BrowseDelayMs\">\r\n <ng-template #header_inner let-headerItem>\r\n <ng-container *ngTemplateOutlet=\"header_tr; context : {$implicit: headerItem}\"></ng-container>\r\n </ng-template>\r\n</chart-pager>\r\n\r\n<ng-container *ngIf=\"loadingChart && loading_template\">\r\n <div style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <ng-container *ngTemplateOutlet=\"loading_template\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<ng-container *ngIf=\"loadingChart && !loading_template\">\r\n <div class=\"esc-loading-overlay\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\">\r\n <p class=\"label\">Loading....</p>\r\n </div>\r\n</ng-container>\r\n\r\n<div [class.hide-block]=\"loadingChart\" id=\"{{name}}\" style=\"width: 100%;\" [style.height]=\"isPaged ? 'calc(100% - 44px)' : '100%'\"></div>", styles: [".esc-loading-overlay{background:rgba(153,153,153,.6);text-transform:uppercase;font-size:30px;font-weight:700;color:#fff;text-align:center;font-family:monospace}.esc-loading-overlay .label{margin:0;padding-top:7%}.hide-block{display:none}\n"] }]
2690
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: ChartLoader }, { type: ChartDispatcher }, { type: BaseAdapter }, { type: i0.NgZone }, { type: Object, decorators: [{
2691
- type: Inject,
2692
- args: [PLATFORM_ID]
2693
- }] }, { type: undefined, decorators: [{
2694
- type: Inject,
2695
- args: [ESC_LOGS]
2696
- }] }, { type: undefined, decorators: [{
2697
- type: Inject,
2698
- args: [ESC_ANIMATIONS]
2699
- }] }, { type: undefined, decorators: [{
2700
- type: Inject,
2701
- args: [ESC_LOCALE]
2702
- }] }, { type: undefined, decorators: [{
2703
- type: Inject,
2704
- args: [ESC_THEME]
2705
- }] }]; }, propDecorators: { Data: [{
2700
+ BaseChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseChartComponent, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive });
2701
+ BaseChartComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: BaseChartComponent, inputs: { XTitle: "XTitle", YTitle: "YTitle", Settings: "Settings", Legend: "Legend", LegendPosition: "LegendPosition", Timeline: "Timeline", name: "name", Animations: "Animations", Theme: "Theme", Locale: "Locale", HideSeriesOnLabelClick: "HideSeriesOnLabelClick", MinGridDistance: "MinGridDistance", AdaptLabelSizeAndOrientation: "AdaptLabelSizeAndOrientation", LegendPadding: "LegendPadding", DataDtos: "DataDtos", DataDtoStartIndex: "DataDtoStartIndex", DataRetrieve: "DataRetrieve", BrowseDelayMs: "BrowseDelayMs" }, outputs: { onSelectionChanged: "onSelectionChanged", onSeriesClicked: "onSeriesClicked", onLoadStart: "onLoadStart", onLoadEnd: "onLoadEnd", chartLoaded: "chartLoaded" }, queries: [{ propertyName: "header_tr", first: true, predicate: ["header"], descendants: true }, { propertyName: "loading_template", first: true, predicate: ["loading"], descendants: true }], usesOnChanges: true, ngImport: i0 });
2702
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseChartComponent, decorators: [{
2703
+ type: Directive
2704
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: Object }, { type: i0.NgZone }, { type: ChartLoader }, { type: ChartDispatcher }, { type: undefined }, { type: undefined }, { type: undefined }, { type: undefined }]; }, propDecorators: { XTitle: [{
2706
2705
  type: Input
2707
- }], DataArray: [{
2706
+ }], YTitle: [{
2708
2707
  type: Input
2709
- }], ColumnWidthPercentage: [{
2708
+ }], Settings: [{
2710
2709
  type: Input
2711
- }], LabelWidth: [{
2710
+ }], Legend: [{
2712
2711
  type: Input
2713
- }], LabelVerticalOrientationCutoffWidth: [{
2712
+ }], LegendPosition: [{
2714
2713
  type: Input
2715
- }], LabelRightWhenCompressed: [{
2714
+ }], Timeline: [{
2716
2715
  type: Input
2717
- }], LabelTopWhenCompressed: [{
2716
+ }], name: [{
2717
+ type: Input
2718
+ }], Animations: [{
2719
+ type: Input
2720
+ }], Theme: [{
2721
+ type: Input
2722
+ }], Locale: [{
2723
+ type: Input
2724
+ }], HideSeriesOnLabelClick: [{
2725
+ type: Input
2726
+ }], MinGridDistance: [{
2727
+ type: Input
2728
+ }], AdaptLabelSizeAndOrientation: [{
2729
+ type: Input
2730
+ }], LegendPadding: [{
2731
+ type: Input
2732
+ }], DataDtos: [{
2733
+ type: Input
2734
+ }], DataDtoStartIndex: [{
2735
+ type: Input
2736
+ }], DataRetrieve: [{
2718
2737
  type: Input
2738
+ }], BrowseDelayMs: [{
2739
+ type: Input
2740
+ }], header_tr: [{
2741
+ type: ContentChild,
2742
+ args: ['header', { static: false }]
2743
+ }], loading_template: [{
2744
+ type: ContentChild,
2745
+ args: ['loading', { static: false }]
2746
+ }], onSelectionChanged: [{
2747
+ type: Output
2748
+ }], onSeriesClicked: [{
2749
+ type: Output
2750
+ }], onLoadStart: [{
2751
+ type: Output
2752
+ }], onLoadEnd: [{
2753
+ type: Output
2754
+ }], chartLoaded: [{
2755
+ type: Output
2719
2756
  }] } });
2720
2757
 
2721
2758
  /**
@@ -2738,60 +2775,6 @@ class PagedChartData {
2738
2775
  }
2739
2776
  }
2740
2777
 
2741
- /** Componenti esportati dal modulo */
2742
- const COMPONENTS = [
2743
- EsChartComponent,
2744
- EsLineChartComponent,
2745
- EsPieChartComponent,
2746
- EsVertical2DChartComponent,
2747
- EsVerticalChartComponent,
2748
- EsVerticalStackedChartComponent,
2749
- PageChartSelector,
2750
- EsAreaChartComponent
2751
- ];
2752
- class EsChartsModule {
2753
- static forRoot(config) {
2754
- return {
2755
- ngModule: EsChartsModule,
2756
- providers: [
2757
- { provide: ESC_LOCALE, useValue: config?.locale || 'it-IT' },
2758
- { provide: ESC_ANIMATIONS, useValue: config?.animations == null ? true : config?.animations },
2759
- { provide: ESC_THEME, useValue: config?.theme || 'spiritedaway' },
2760
- { provide: ESC_LOGS, useValue: config?.debugMode == null ? false : config?.debugMode },
2761
- { provide: BaseAdapter, useClass: config?.adapter || BaseAdapter },
2762
- // Singleton cattiva by Ema. Verificare strade migliori
2763
- { provide: ChartLoader, useValue: new ChartLoader(config?.debugMode == null ? false : config?.debugMode) }
2764
- ]
2765
- };
2766
- }
2767
- }
2768
- EsChartsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2769
- EsChartsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, declarations: [EsChartComponent,
2770
- EsLineChartComponent,
2771
- EsPieChartComponent,
2772
- EsVertical2DChartComponent,
2773
- EsVerticalChartComponent,
2774
- EsVerticalStackedChartComponent,
2775
- PageChartSelector,
2776
- EsAreaChartComponent], imports: [CommonModule], exports: [EsChartComponent,
2777
- EsLineChartComponent,
2778
- EsPieChartComponent,
2779
- EsVertical2DChartComponent,
2780
- EsVerticalChartComponent,
2781
- EsVerticalStackedChartComponent,
2782
- PageChartSelector,
2783
- EsAreaChartComponent] });
2784
- EsChartsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, providers: [ChartDispatcher], imports: [CommonModule] });
2785
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: EsChartsModule, decorators: [{
2786
- type: NgModule,
2787
- args: [{
2788
- imports: [CommonModule],
2789
- declarations: [...COMPONENTS],
2790
- providers: [ChartDispatcher],
2791
- exports: [...COMPONENTS]
2792
- }]
2793
- }] });
2794
-
2795
2778
  /*
2796
2779
  * Public API Surface of es-charts
2797
2780
  */