@esfaenza/es-charts 15.2.3 → 15.2.5

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