@massimo-cassandro/minimo 1.18.1 → 1.18.2
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.
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/index.js +92 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/hbars.js +356 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/pie.js +245 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/radial-bars.js +177 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/rating-display.js +835 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/costruzione-assi.js +212 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/costruzione-linee.js +101 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/defaults.js +185 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/display-current.js +27 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/grid-areas.js +129 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/parse-opts.js +64 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile-src/paths-setup.js +73 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/settimanale-mensile.js +126 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/charts/signal-bars.js +290 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/src/week-utils.js +122 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/hbars-test.js +52 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/mcn-test.js +74 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/pie-test.js +16 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/radial-bars-test.js +48 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/settimanale-mensile-dati-settimanale.js +426 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/settimanale-mensile-test.js +260 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/browser-test/src/signal-bars-test.js +64 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/node-test.mjs +86 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/hBars-node-test.mjs +40 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/lines-node-test.mjs +73 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/mcn-node-test.mjs +64 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/pie-node-test.mjs +12 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/radialsBar-node-test.mjs +44 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/settimanale-mensile-node-test.mjs +258 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/node-test/src/signalBars-node-test.mjs +36 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/test-readme.md +24 -0
- package/charts/TODO charts/1a-vers DA RIFATTORIZZARE/test/textToPath-test.mjs +14 -0
- package/charts/TODO charts/???/InfoBox.js +456 -0
- package/charts/TODO charts/???/README-upg OLD/342/206/222NEW.md" +53 -0
- package/charts/TODO charts/???/README.md +1 -0
- package/charts/TODO charts/???/TODO.md +39 -0
- package/charts/TODO charts/???/base-cfg.js +66 -0
- package/charts/TODO charts/???/rating-displayOLD.js +837 -0
- package/charts/TODO charts/docs/TODO.md +1 -0
- package/charts/TODO charts/docs/costruzione display rating.md +145 -0
- package/charts/TODO charts/test/node-test.mjs +92 -0
- package/charts/TODO charts/test/test-readme.md +23 -0
- package/charts/TODO charts/test/test-src/rating-display-extra-test.js +132 -0
- package/charts/TODO charts/test/test-src/rating-display-test.js +155 -0
- package/charts/TODO charts/test/textToPath-test.mjs +14 -0
- package/charts/TODO.md +1 -1
- package/package.json +1 -1
- package/snippets/flash-messages.html.twig +34 -0
- package/src/components/unsplash-page/unsplash-page.js +3 -6
- package/src/components/unsplash-page/unsplash-page.module.css +11 -6
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// prima elaborazione e controlli delle impostazioni
|
|
2
|
+
|
|
3
|
+
import { getWeekOfDate } from '../../week-utils.js';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export function parseOpts(cfg) {
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
|
|
10
|
+
if(+cfg.width < 100 || +cfg.height < 100) {
|
|
11
|
+
throw '`width` e/o `height` mancanti o di dimensioni insufficienti (devono essere maggiori di 99px)';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if(!['settimanale', 'mensile'].includes(cfg.modo)) {
|
|
15
|
+
throw `‘modo’ deve essere ‘settimanale’ o ‘mensile’ (valore attuale: ‘${cfg.modo}’)`;
|
|
16
|
+
}
|
|
17
|
+
cfg.isSettimanale = cfg.modo === 'settimanale';
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// =>> PARAMETRI calcolati
|
|
21
|
+
//---------------
|
|
22
|
+
|
|
23
|
+
// solo settimanale
|
|
24
|
+
if(cfg.isSettimanale) {
|
|
25
|
+
|
|
26
|
+
// calcolo max_value (tiene conto della eventuale esclusione della settimana zero)
|
|
27
|
+
cfg.max_value = cfg.chartData.filter(row => cfg.skipWeek0? row.w > 0 : true).reduce((prev, curr) => {
|
|
28
|
+
return Math.max(prev, ...Object.values(curr));
|
|
29
|
+
}, 0);
|
|
30
|
+
|
|
31
|
+
// aggiustamento `eti_asseX_cfg.height` per fare spazio alle etichette con il nome dei mesi
|
|
32
|
+
cfg.eti_asseX_height *= 2.2;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
cfg.currentWeek = getWeekOfDate({year: cfg.anno});
|
|
36
|
+
cfg.currentMonth = new Date().getMonth() + 1; // base 1
|
|
37
|
+
|
|
38
|
+
// primo dell'anno
|
|
39
|
+
cfg.jan1 = new Date(Date.UTC(cfg.anno, 0, 1));
|
|
40
|
+
cfg.jan1DayOfTheWeek = cfg.jan1.getDay();
|
|
41
|
+
|
|
42
|
+
// il numero di settimane dell'anno non include la settimana 0, se presente,
|
|
43
|
+
// che indica il riporto anno precedente.
|
|
44
|
+
// se il 31 dicembre è prima di giovedì, viene considerato nella prima settimana dell'anno successivo
|
|
45
|
+
// e il numero di settimane dell'anno è 52
|
|
46
|
+
cfg.dec31WeekNum = getWeekOfDate({date: new Date(cfg.anno, 11, 31), year: cfg.anno});
|
|
47
|
+
cfg.weeks = cfg.dec31WeekNum === 1? 52 : cfg.dec31WeekNum;
|
|
48
|
+
|
|
49
|
+
cfg.mesi = ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic'];
|
|
50
|
+
|
|
51
|
+
// larghezza ogni step dell'asse X (= 1 settimana o mese)
|
|
52
|
+
if(cfg.isSettimanale) {
|
|
53
|
+
cfg.stepX_count = cfg.weeks + (cfg.skipWeek0? 0 : 1);
|
|
54
|
+
} else {
|
|
55
|
+
cfg.stepX_count = 12;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
return cfg;
|
|
60
|
+
|
|
61
|
+
} catch(e) {
|
|
62
|
+
console.error( 'AdaCharts → andamentoAnnuale → parseOpts', e ); // eslint-disable-line
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// elaborazione dati grafico, costruzione coordinate paths e punti
|
|
2
|
+
|
|
3
|
+
export function pathsSetup(cfg) {
|
|
4
|
+
|
|
5
|
+
// coordinate dei punti dei vari set di dati
|
|
6
|
+
// array delle varie serie di punti che saranno poi utilizzate per costruire gli elementi del grafico
|
|
7
|
+
// ogni elemento dell'array contiene le coordinate x,y di ogni punto
|
|
8
|
+
cfg.coords = {
|
|
9
|
+
budget_standard: [],
|
|
10
|
+
budget_positivo: [],
|
|
11
|
+
budget_negativo: [],
|
|
12
|
+
consolidato: [],
|
|
13
|
+
consolidato_forecast: [],
|
|
14
|
+
consolidato_prec: []
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// step iniziale o 1 se skipWeek0 = true e modo = 'settimanale'
|
|
18
|
+
const firstStep = (cfg.skipWeek0 && cfg.isSettimanale)? 1 : 0
|
|
19
|
+
|
|
20
|
+
// conversione valori in coordinate Y relative al grafico
|
|
21
|
+
,valueToY = (value) => {
|
|
22
|
+
// la coordinata y è ricavata dalla proporzione con il valore massimo e altezza del grafico
|
|
23
|
+
// arrotondata a 4 cifre decimali
|
|
24
|
+
|
|
25
|
+
// return chart_area.top + chart_area.height - ((value * chart_area.height) / max_value);
|
|
26
|
+
return Math.round(
|
|
27
|
+
(cfg.chart_area.top + cfg.chart_area.height - ((value * cfg.chart_area.height) / cfg.max_value)) * 1e4
|
|
28
|
+
) / 1e4;
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
;
|
|
32
|
+
|
|
33
|
+
// valore x iniziale
|
|
34
|
+
let x = cfg.chart_area.left;
|
|
35
|
+
|
|
36
|
+
for (let thisStep = firstStep; thisStep <= cfg.stepX_count; thisStep++) {
|
|
37
|
+
|
|
38
|
+
const dataItem = cfg.chartData.filter(row => row[cfg.isSettimanale? 'w' : 'm'] === thisStep )[0] ?? {};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
{
|
|
42
|
+
w: <num>, // numero settimana (se settimanale)
|
|
43
|
+
m: <num>, // numero mese (se mensile)
|
|
44
|
+
|
|
45
|
+
s: <num>, // valore scenario standard
|
|
46
|
+
p: <num>, // valore scenario positivo
|
|
47
|
+
n: <num>, // valore scenario negativo
|
|
48
|
+
c: <num>, // valore consolidato anno corrente (può essere null)
|
|
49
|
+
cp: <num>, // valore consolidato anno precedente
|
|
50
|
+
cf: <num> // valore consolidato forecast (può non essere presente o null)
|
|
51
|
+
}
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
// ['s', 'p', 'n', 'c', 'cp', 'cf'].forEach(k => {
|
|
55
|
+
// if(dataItem[k] != null) {
|
|
56
|
+
// cfg.coords.budget_standard.push([x, valueToY(dataItem[k] ?? 0)]);
|
|
57
|
+
// }
|
|
58
|
+
// });
|
|
59
|
+
|
|
60
|
+
if(dataItem.p != null) cfg.coords.budget_positivo.push([x, valueToY(dataItem.p)]);
|
|
61
|
+
if(dataItem.n != null) cfg.coords.budget_negativo.push([x, valueToY(dataItem.n)]);
|
|
62
|
+
if(dataItem.s != null) cfg.coords.budget_standard.push([x, valueToY(dataItem.s)]);
|
|
63
|
+
if(dataItem.c != null) cfg.coords.consolidato.push([x, valueToY(dataItem.c)]);
|
|
64
|
+
if(dataItem.cf != null) cfg.coords.consolidato_forecast.push([x, valueToY(dataItem.cf)]);
|
|
65
|
+
if(dataItem.cp != null) cfg.coords.consolidato_prec.push([x, valueToY(dataItem.cp)]);
|
|
66
|
+
|
|
67
|
+
x += +cfg.stepX_size;
|
|
68
|
+
x = +x.toFixed(4);
|
|
69
|
+
|
|
70
|
+
} // end for step x
|
|
71
|
+
|
|
72
|
+
return cfg;
|
|
73
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Grafico andamento economico annuale
|
|
4
|
+
* produce un grafico a linee con l'andamento annuale di un determinato parametro
|
|
5
|
+
* con dettagli settimanali o mensili
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// vedi test per la definizione delle opzioni
|
|
9
|
+
|
|
10
|
+
// TODO metodo migliore per condivisione variabili
|
|
11
|
+
// TODO parte interattiva
|
|
12
|
+
|
|
13
|
+
import { parseStdAxisOpts } from '../components/parse-std-axis-opts.js';
|
|
14
|
+
|
|
15
|
+
import { costruzioneAssi } from './settimanale-mensile-src/costruzione-assi.js';
|
|
16
|
+
import { default_opts } from './settimanale-mensile-src/defaults.js';
|
|
17
|
+
import { parseOpts } from './settimanale-mensile-src/parse-opts.js';
|
|
18
|
+
import { pathsSetup } from './settimanale-mensile-src/paths-setup.js';
|
|
19
|
+
import { gridAreas } from './settimanale-mensile-src/grid-areas.js';
|
|
20
|
+
import { displayCurrent } from './settimanale-mensile-src/display-current.js';
|
|
21
|
+
import { costruzioneLinee } from './settimanale-mensile-src/costruzione-linee.js';
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export async function settimanaleMensile(options) {
|
|
25
|
+
|
|
26
|
+
// =>> parse container
|
|
27
|
+
[options.container, options.width, options.height] = this.utils.parseContainer(options.container, options.width, options.height);
|
|
28
|
+
|
|
29
|
+
let cfg = {...default_opts, ...options};
|
|
30
|
+
|
|
31
|
+
cfg.debug = this.debug? this.debug : (cfg.debug?? false);
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
// =>> prima elaborazione e controlli delle impostazioni
|
|
35
|
+
cfg = parseOpts(cfg); // elaborazione specifica per questo grafico
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if(!cfg.container && (!cfg.width || !cfg.height)) {
|
|
39
|
+
throw '`container` non impostato e almeno uno tra `width` e `height` mancante';
|
|
40
|
+
}
|
|
41
|
+
// valore massimo da rappresentare
|
|
42
|
+
// se `skipWeek0 === true`, i dati della settimana zero non vanno inclusi nel calcolo
|
|
43
|
+
|
|
44
|
+
cfg.max_value = cfg.chartData
|
|
45
|
+
.filter(weekData => cfg.skipWeek0 === true? weekData.w > 0 : true)
|
|
46
|
+
.reduce((prev, curr) => {
|
|
47
|
+
return Math.max(prev, ...Object.values(curr));
|
|
48
|
+
}, 0);
|
|
49
|
+
|
|
50
|
+
const parsed_cfg = parseStdAxisOpts({ // elaborazione standard condivisa con grafici analoghi
|
|
51
|
+
max_value: cfg.max_value,
|
|
52
|
+
values: cfg.chartData.map(item => Object.values(item)).flat(),
|
|
53
|
+
legenda: cfg.legenda,
|
|
54
|
+
padding: cfg.padding,
|
|
55
|
+
width: cfg.width,
|
|
56
|
+
height: cfg.height,
|
|
57
|
+
eti_asseX_height: cfg.eti_asseX_height,
|
|
58
|
+
eti_asseY_width: cfg.eti_asseY_width,
|
|
59
|
+
stepY_count: cfg.stepY_count,
|
|
60
|
+
stepX_count: cfg.stepX_count,
|
|
61
|
+
ticksLength: cfg.ticksLength,
|
|
62
|
+
});
|
|
63
|
+
cfg = {...cfg, ...parsed_cfg};
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// =>> svg
|
|
67
|
+
cfg.svgCanvas = this.createSvgCanvas(cfg.container, cfg.debug)
|
|
68
|
+
.size(cfg.width, cfg.height)
|
|
69
|
+
.viewbox(0, 0, cfg.width, cfg.height)
|
|
70
|
+
.attr(cfg.svgAttrs??{});
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
// =>> elaborazione dati grafico, costruzione coordinate paths e punti
|
|
74
|
+
cfg = pathsSetup(cfg);
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
// =>> costruzione assi e griglia
|
|
78
|
+
cfg = await costruzioneAssi({
|
|
79
|
+
cfg: cfg,
|
|
80
|
+
adaChartIstance: this,
|
|
81
|
+
xLabels: cfg.isSettimanale? [...Array(cfg.weeks + 1).keys()].slice(cfg.skipWeek0? 1 : 0) : cfg.mesi,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// =>> aree colorate per l'evidenziazione dei mesi e seconda riga di etichette
|
|
85
|
+
// solo settimanale
|
|
86
|
+
if(cfg.isSettimanale) {
|
|
87
|
+
cfg = await gridAreas(cfg, this);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// =>> costruzione linee
|
|
91
|
+
cfg = costruzioneLinee(cfg);
|
|
92
|
+
|
|
93
|
+
// =>> evidenziazione settimana / mese corrente
|
|
94
|
+
cfg = displayCurrent(cfg);
|
|
95
|
+
cfg.lineeGroup.front();
|
|
96
|
+
|
|
97
|
+
// =>> Legenda
|
|
98
|
+
const legendaEl = await this.legenda(cfg.legenda);
|
|
99
|
+
legendaEl.attr({ 'data-cfg.debug-info': cfg.debug? 'Legenda' : null });
|
|
100
|
+
const legendaBbox = legendaEl.bbox();
|
|
101
|
+
|
|
102
|
+
legendaEl.dmove(
|
|
103
|
+
(cfg.width - legendaBbox.width) / 2,
|
|
104
|
+
cfg.padding
|
|
105
|
+
);
|
|
106
|
+
legendaEl.y(cfg.padding);
|
|
107
|
+
|
|
108
|
+
legendaEl.x((cfg.width - legendaBbox.width) / 2);
|
|
109
|
+
|
|
110
|
+
cfg.svgCanvas.add(legendaEl);
|
|
111
|
+
|
|
112
|
+
if(!cfg.container) {
|
|
113
|
+
return cfg.svgCanvas.svg();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if(cfg.debug) {
|
|
117
|
+
|
|
118
|
+
/* eslint-disable no-console */
|
|
119
|
+
console.log('\n****** grafico andamento annuale ******');
|
|
120
|
+
console.log(cfg);
|
|
121
|
+
console.log('************');
|
|
122
|
+
/* eslint-enable no-console */
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
}
|
|
126
|
+
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* signal bars (grafico a tacche)
|
|
3
|
+
*
|
|
4
|
+
* Mostra una serie di barre analoghe a quelle del segnale dei cellulari
|
|
5
|
+
* in cui le barre vengono mostrate attive se il valore di riferimento è maggiore o uguale
|
|
6
|
+
* a uno degli indici del range dato e inferiore al successivo.
|
|
7
|
+
* Di conseguenza, se il valore di riferimento è più basso del valore minimo del range
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export async function signalBars({
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/** container (selettore o elemento DOM), se null viene restituito il codice SVG */
|
|
15
|
+
container = null,
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
larghezza e altezza del grafico (px),
|
|
19
|
+
Se il container è presente e i parametro `width` e `height` sono `null`,
|
|
20
|
+
vengono utilizzate le dimensioni del container.
|
|
21
|
+
Se uno dei due valori non è impostato o ricavabile, viene generato un errore.
|
|
22
|
+
NB: il padding del container viene considerato nelle dimensioni del grafico,
|
|
23
|
+
è preferibile non impostarlo.
|
|
24
|
+
Il valore 'auto' di height fa sì che l'altezza dell'svg sia calcolata sulla base
|
|
25
|
+
del numero di barre e dei valori `barsGap` e `barsHeight`
|
|
26
|
+
*/
|
|
27
|
+
width = null, // null || <value>
|
|
28
|
+
height = 300, // <value> || null
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
range di valori che corrispondono alle varie tacche,
|
|
32
|
+
un valore inferiore al primo non "accende" nessuna tacca,
|
|
33
|
+
tra il primo (incluso), e il secondo (escluso), una tacca e così via.
|
|
34
|
+
Il numero di elementi determina il numero delle tacche
|
|
35
|
+
*/
|
|
36
|
+
ranges = [1,2,3,4],
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
se fornito, le barre 'accese' non vengono calcolate, ma si uutilizza questo valore
|
|
40
|
+
corrisponde al numero di barre attivate da sinistra verso destra.
|
|
41
|
+
Se presente, `value` può essere omesso ed è comunque ignorato
|
|
42
|
+
*/
|
|
43
|
+
activeBars = null,
|
|
44
|
+
|
|
45
|
+
/** Valore da rappresentare */
|
|
46
|
+
value = null,
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
etichetta da mostrare a destra o sotto le tacche. Se nulla mostra il valore di `value`,
|
|
50
|
+
stringa vuota o false per non avere etichetta
|
|
51
|
+
*/
|
|
52
|
+
label = null,
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
/** posizione dell'etichetta */
|
|
56
|
+
labelPosition = 'right', // right o bottom
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
Impostazioni font e colori per le etichette
|
|
60
|
+
Impostare solo se non si vogliono usare i colori di default
|
|
61
|
+
se impostato, è un oggetto analogo a quello definito in src/utils/init.js
|
|
62
|
+
*/
|
|
63
|
+
labelFont = null,
|
|
64
|
+
labelFill = '#000',
|
|
65
|
+
|
|
66
|
+
/** path del file font per la conversione in tracciati */
|
|
67
|
+
labelFontFilePath = null,
|
|
68
|
+
|
|
69
|
+
/** spazio tra l'etichetta e il grafico */
|
|
70
|
+
textBarsGap = 8,
|
|
71
|
+
|
|
72
|
+
/** spazio tra una barra e la successiva */
|
|
73
|
+
barsGap = 10,
|
|
74
|
+
|
|
75
|
+
/** corner radius */
|
|
76
|
+
barsCornerRadius = 3,
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
come il precedente, ma relatuvo alla larghezza della barra,
|
|
80
|
+
ad esempio un valore di `.5' crea della barre dalle estremità tonde
|
|
81
|
+
Se presente, il valore di `barsCornerRadius` viene ignorato
|
|
82
|
+
*/
|
|
83
|
+
barsRelativeCornerRadius = null,
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
attributi barre attive e disattive
|
|
87
|
+
ad esclusione di `stroke-width` da gestire separatamente con barsStrokeWidth per esigenze di calcolo
|
|
88
|
+
vedi https://svgjs.dev/docs/3.2/manipulating/#attributes
|
|
89
|
+
*/
|
|
90
|
+
barsStrokeWidth = 3,
|
|
91
|
+
barsOnAttr = {
|
|
92
|
+
fill: '#000'
|
|
93
|
+
// ,'fill-opacity': 0.5
|
|
94
|
+
,stroke: '#000'
|
|
95
|
+
,'stroke-width': 3
|
|
96
|
+
},
|
|
97
|
+
barsOffAttr = {
|
|
98
|
+
fill: '#000'
|
|
99
|
+
// ,'fill-opacity': 0.5
|
|
100
|
+
,stroke: '#fff'
|
|
101
|
+
,'stroke-width': 3
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
/** seimpostato, il valore massimo della larghezz delle barre */
|
|
105
|
+
maxBarWidth = null,
|
|
106
|
+
|
|
107
|
+
/** eventuali classi da aggiungere al grafico */
|
|
108
|
+
svgClassName = null,
|
|
109
|
+
labelClassName = null,
|
|
110
|
+
barOnClassName = null,
|
|
111
|
+
barOffClassName = null,
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
} = {}) {
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
if(ranges.filter(v => isNaN(v)).length) {
|
|
120
|
+
throw 'There are non-numeric values';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if(ranges.length < 2) {
|
|
124
|
+
throw '`ranges`: sono necessari alemno due valori';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if(typeof barsStrokeWidth !== 'number') {
|
|
128
|
+
throw '`barsStrokeWidth` deve essere un numero';
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if((value == null || typeof value !== 'number') && (activeBars == null || typeof activeBars !== 'number')) {
|
|
132
|
+
throw 'Almeno uno tra `value` e `activeBars` deve essere presente e deve essere un numero ' +
|
|
133
|
+
`(value: ${value}, activeBars: ${activeBars})`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if(!['right', 'bottom'].includes(labelPosition)) {
|
|
137
|
+
throw '`labelPosition` deve essere`right` o `bottom`';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// container
|
|
141
|
+
[, width, height] = this.utils.parseContainer(container, width, height);
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
if(barsGap == null) {
|
|
145
|
+
throw '`barsGap` deve essere impostato';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if(!width || !height) {
|
|
150
|
+
throw `width e/o height mancanti: width: ${width}, height: ${height}`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const svgCanvas = this.createSvgCanvas(container).size(width, height);
|
|
154
|
+
svgCanvas.viewbox(0, 0, width, height);
|
|
155
|
+
|
|
156
|
+
if(svgClassName) {
|
|
157
|
+
svgCanvas.addClass(svgClassName);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let labelX, labelY, barsAreaWidth, barWidth, barsAreaHeight, labelEl, label_bbox;
|
|
161
|
+
const barsCount = ranges.length;
|
|
162
|
+
|
|
163
|
+
if(label !== '' && label !== false) {
|
|
164
|
+
|
|
165
|
+
if(label == null) {
|
|
166
|
+
label = value.toLocaleString('it-IT', { maximumFractionDigits: 2 });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// =>> calcolo dimensioni del testo per ricavare lo spazio utile per le barre
|
|
170
|
+
// in base al posizionamento dell'etichetta
|
|
171
|
+
|
|
172
|
+
// =>> label
|
|
173
|
+
[label_bbox, labelEl] = await this.createTextEl ({
|
|
174
|
+
text: label,
|
|
175
|
+
textFill: labelFill,
|
|
176
|
+
fontAttr: labelFont,
|
|
177
|
+
fontFilePath: labelFontFilePath,
|
|
178
|
+
parentElement: svgCanvas
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
if(labelPosition === 'right') {
|
|
183
|
+
labelX = width - label_bbox.width;
|
|
184
|
+
labelY = (height - label_bbox.height) / 2;
|
|
185
|
+
barsAreaWidth = width - label_bbox.width - textBarsGap;
|
|
186
|
+
barsAreaHeight = height;
|
|
187
|
+
|
|
188
|
+
} else {
|
|
189
|
+
labelX = (width - label_bbox.width) / 2;
|
|
190
|
+
labelY = height - label_bbox.height;
|
|
191
|
+
barsAreaWidth = width;
|
|
192
|
+
barsAreaHeight = height - label_bbox.height - textBarsGap;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// posizionamento etichetta
|
|
196
|
+
labelEl.move(labelX, labelY);
|
|
197
|
+
|
|
198
|
+
if(labelClassName) {
|
|
199
|
+
labelEl.addClass(labelClassName);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
} else {
|
|
204
|
+
barsAreaWidth = width;
|
|
205
|
+
barsAreaHeight = height;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
barWidth = (
|
|
209
|
+
barsAreaWidth -
|
|
210
|
+
(barsGap * (barsCount - 1)) -
|
|
211
|
+
((barsStrokeWidth?? 0) * barsCount) // lo spessore della traccia è divisa tra interno ed esterno
|
|
212
|
+
) / barsCount;
|
|
213
|
+
barWidth = Math.min(maxBarWidth?? Infinity, barWidth);
|
|
214
|
+
|
|
215
|
+
const barsMaxHeight = barsAreaHeight - (barsStrokeWidth?? 0),
|
|
216
|
+
barsModuleHeight = barsMaxHeight / barsCount;
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
// coordinate x e y e altezza della prima barra
|
|
220
|
+
let barX = (
|
|
221
|
+
barsAreaWidth -
|
|
222
|
+
(barWidth * barsCount) -
|
|
223
|
+
(barsGap * (barsCount - 1)) -
|
|
224
|
+
((barsStrokeWidth?? 0) * barsCount)
|
|
225
|
+
) / 2 + ((barsStrokeWidth?? 0)/2),
|
|
226
|
+
barHeight = barsModuleHeight,
|
|
227
|
+
barY = barsAreaHeight - barHeight - ((barsStrokeWidth?? 0) / 2);
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
// indice dell'ultima barra da rappresentare con riempimento attivo
|
|
231
|
+
ranges.sort((a,b) => a - b);
|
|
232
|
+
let lastActiveBarIndex;
|
|
233
|
+
|
|
234
|
+
if(activeBars) {
|
|
235
|
+
lastActiveBarIndex = activeBars - 1;
|
|
236
|
+
|
|
237
|
+
} else {
|
|
238
|
+
const closestRangeValue = ranges.reduce((prev, curr) => {
|
|
239
|
+
return (Math.abs(Math.ceil(curr - value)) < Math.abs(Math.ceil(prev - value)) ? curr : prev);
|
|
240
|
+
});
|
|
241
|
+
lastActiveBarIndex = ranges.indexOf(closestRangeValue);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const bar_group = svgCanvas.group();
|
|
245
|
+
|
|
246
|
+
ranges.forEach((val, idx) => {
|
|
247
|
+
|
|
248
|
+
const barIsOn = idx <= lastActiveBarIndex;
|
|
249
|
+
|
|
250
|
+
const bar = bar_group.rect({
|
|
251
|
+
x: barX,
|
|
252
|
+
y: barY,
|
|
253
|
+
width: barWidth,
|
|
254
|
+
height: barHeight,
|
|
255
|
+
...(barIsOn? barsOnAttr : barsOffAttr),
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
if(barsRelativeCornerRadius != null || barsCornerRadius != null) {
|
|
259
|
+
|
|
260
|
+
barsCornerRadius= barsRelativeCornerRadius != null? barWidth/2 : barsCornerRadius;
|
|
261
|
+
|
|
262
|
+
bar.radius(barsCornerRadius);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if( barsStrokeWidth > 0 ) {
|
|
266
|
+
bar.stroke({ width: barsStrokeWidth });
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if(barOnClassName && barIsOn) {
|
|
270
|
+
bar.addClass(barOnClassName);
|
|
271
|
+
}
|
|
272
|
+
if(barOffClassName && !barIsOn) {
|
|
273
|
+
bar.addClass(barOffClassName);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
barHeight += barsModuleHeight;
|
|
277
|
+
barX += barWidth + barsStrokeWidth + barsGap;
|
|
278
|
+
barY -= barsModuleHeight;
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
if(!container) {
|
|
282
|
+
return svgCanvas.svg();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
} catch(e) {
|
|
287
|
+
console.error( 'AdaCharts → signalBars', e ); // eslint-disable-line
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Restituisce il numero della settimana corrente
|
|
4
|
+
* se la prima settimana ha meno di 4 gg e viene quindi assegnata all'ultima dell'anno precedente
|
|
5
|
+
* i giorni relativi vengono aggiunti alla prima settimana (che così ha più di 7 giorni)
|
|
6
|
+
* discorso analogo per l'ultima settimana
|
|
7
|
+
*
|
|
8
|
+
* @param {date} date
|
|
9
|
+
* @param {number} year
|
|
10
|
+
* @returns Number
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export function getWeekOfDate({date = new Date(), year = null}) {
|
|
15
|
+
|
|
16
|
+
// se year è null, si considera quello della data indicata
|
|
17
|
+
if(year == null) {
|
|
18
|
+
year = date.getFullYear();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// se la data non è nell'anno indicato, viene restituito null
|
|
22
|
+
if(date.getFullYear() !== year) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const dateMonth = date.getMonth(); // necessario congelarlo, date viene modificata più volte
|
|
27
|
+
|
|
28
|
+
date.setHours(0, 0, 0, 0);
|
|
29
|
+
|
|
30
|
+
// Thursday in current week decides the year.
|
|
31
|
+
date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
|
|
32
|
+
// January 4 is always in week 1.
|
|
33
|
+
let week1 = new Date(date.getFullYear(), 0, 4);
|
|
34
|
+
// Adjust to Thursday in week 1 and count number of weeks from date to week1.
|
|
35
|
+
let currentWeek = 1 + Math.round(
|
|
36
|
+
((date.getTime() - week1.getTime()) / 86400e3 - 3 + (week1.getDay() + 6) % 7) / 7
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// prima settimana con meno di 4 giorni, normalmente sarebbe calcolata nell'anno precedente
|
|
40
|
+
// ma in questo caso i giorni relativi vengono aggiunti alla prima settimana del nuovo anno
|
|
41
|
+
if(currentWeek >= 52 && dateMonth === 0) {
|
|
42
|
+
currentWeek = 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return currentWeek;
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Restituisce le date di inizio e fine della settimana dell'anno dati
|
|
52
|
+
*
|
|
53
|
+
* @param {number} week
|
|
54
|
+
* @param {number} year
|
|
55
|
+
* @returns Array
|
|
56
|
+
*/
|
|
57
|
+
export function getDatesOfWeek(week, year) {
|
|
58
|
+
if(week) {
|
|
59
|
+
|
|
60
|
+
let startDay, endDay;
|
|
61
|
+
|
|
62
|
+
const jan1 = new Date(Date.UTC(year, 0, 1, 0, 0, 0))
|
|
63
|
+
, jan1DayOfTheWeek = jan1.getDay()
|
|
64
|
+
// primo lunedì dell'anno
|
|
65
|
+
, daysToFirstMonday = jan1DayOfTheWeek === 1? 0 : jan1DayOfTheWeek === 0? 1 : 8 - jan1DayOfTheWeek
|
|
66
|
+
, firstMonday = daysToFirstMonday === 0 ? jan1 : new Date(+jan1 + daysToFirstMonday * 86400e3)
|
|
67
|
+
, dec31 = new Date(Date.UTC(year, 11, 31))
|
|
68
|
+
, lastDayOfThisWeek = new Date(+firstMonday + ((week - 1) * 7 * 86400e3) + (86400e3 * 6) )
|
|
69
|
+
, __weeks = 52 // ricavato dalla 'array dati, qui è usato un valore fittizio
|
|
70
|
+
;
|
|
71
|
+
|
|
72
|
+
// console.log('jan1', jan1.toUTCString());
|
|
73
|
+
// console.log('jan1DayOfTheWeek', jan1DayOfTheWeek);
|
|
74
|
+
// console.log('daysToFirstMonday', daysToFirstMonday);
|
|
75
|
+
// console.log('firstMonday', firstMonday.toUTCString());
|
|
76
|
+
// console.log('dec31', dec31.toUTCString());
|
|
77
|
+
// console.log('lastDayOfThisWeek', lastDayOfThisWeek.toUTCString());
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
// forza il primo giorno della prima settimana al 1 gennaio anche se non è lunedì
|
|
81
|
+
if(week === 1) {
|
|
82
|
+
startDay = jan1;
|
|
83
|
+
} else {
|
|
84
|
+
startDay = new Date(firstMonday.valueOf());
|
|
85
|
+
startDay = new Date(startDay.setDate(startDay.getDate() + 7 * (week - 2)));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// prima settimana con più di 4 gg, viene considerata a se stante
|
|
89
|
+
endDay = new Date(startDay.valueOf());
|
|
90
|
+
if(week === 1 && jan1DayOfTheWeek < 5) {
|
|
91
|
+
endDay = new Date(endDay.setDate(endDay.getDate() + 7 - jan1DayOfTheWeek));
|
|
92
|
+
} else {
|
|
93
|
+
endDay = new Date(endDay.setDate(endDay.getDate() + 6));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// forza l'ultmo giorno dell'ultima settimana al 31 dic anche se non è domenica
|
|
97
|
+
if(endDay.getFullYear() > year || week === __weeks) {
|
|
98
|
+
endDay = dec31;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
// nel caso in cui la settimana sia la prima o l'ultima,viene restituito un terzo elemento
|
|
104
|
+
// a indicare, rispettivamente, se 1 gennaio corrisponde all'inizione reale della 1a settimana
|
|
105
|
+
// o se 31 dic corrisponde all'ultimo giorno dell'ultima settimana
|
|
106
|
+
|
|
107
|
+
if(week === 1) {
|
|
108
|
+
return [startDay, endDay, +firstMonday === +jan1];
|
|
109
|
+
|
|
110
|
+
} else if (week === __weeks) {
|
|
111
|
+
return [startDay, endDay, +dec31 === +lastDayOfThisWeek];
|
|
112
|
+
|
|
113
|
+
} else {
|
|
114
|
+
return [startDay, endDay];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
} else {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
}
|