@esfaenza/es-charts 15.2.3 → 15.2.4

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