@massimo-cassandro/minimo 1.18.0 → 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 +6 -8
- package/src/components/unsplash-page/unsplash-page.module.css +11 -6
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
import classnames from 'classnames';
|
|
2
|
+
import { useState, useEffect, useRef, Fragment } from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
// import styles from '../charts-base.module.scss';
|
|
5
|
+
import { nanoid } from 'nanoid';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
InfoBox versione su grafico linee
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
function InfoBox({
|
|
14
|
+
year = new Date().getFullYear(),
|
|
15
|
+
infoBoxItems = [],
|
|
16
|
+
infoBoxPositionRefs = [],
|
|
17
|
+
cfg = {},
|
|
18
|
+
mode = 'week',
|
|
19
|
+
data,
|
|
20
|
+
week,
|
|
21
|
+
month,
|
|
22
|
+
dataGroupEl,
|
|
23
|
+
skipWeek0
|
|
24
|
+
}) {
|
|
25
|
+
const [content, setContent] = useState(null),
|
|
26
|
+
infoBoxWrapperRef = useRef();
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
const weekMode = useMemo(() => {
|
|
30
|
+
return mode === 'week';
|
|
31
|
+
}, [mode]),
|
|
32
|
+
infoBoxWidth = useMemo(() => {
|
|
33
|
+
return weekMode? 300 : 240;
|
|
34
|
+
}, [weekMode]);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
|
|
38
|
+
// =>> getDatesOfWeek
|
|
39
|
+
const getDatesOfWeek = week => {
|
|
40
|
+
if(week) {
|
|
41
|
+
|
|
42
|
+
let startDay, endDay;
|
|
43
|
+
const daysToFirstMonday = cfg.jan1DayOfTheWeek === 1? 0 : cfg.jan1DayOfTheWeek === 0? 1 : 8 - cfg.jan1DayOfTheWeek;
|
|
44
|
+
// primo lunedì dell'anno
|
|
45
|
+
const firstMonday = daysToFirstMonday === 0 ? cfg.jan1 : new Date(+cfg.jan1 + daysToFirstMonday * 86400e3);
|
|
46
|
+
|
|
47
|
+
const dec31 = new Date(year, 11, 31),
|
|
48
|
+
lastDayOfLastWeek = new Date(+firstMonday + ((week - 1) * 7 * 86400e3) + (86400e3 * 6) );
|
|
49
|
+
|
|
50
|
+
// forza il primo giorno della prima settimana al 1 gennaio anche se non è lunedì
|
|
51
|
+
if(week === 1) {
|
|
52
|
+
startDay = cfg.jan1;
|
|
53
|
+
} else {
|
|
54
|
+
startDay = new Date(firstMonday.valueOf());
|
|
55
|
+
startDay = new Date(startDay.setDate(startDay.getDate() + 7 * (week - 2)));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// prima settimana con più di 4 gg, viene considerata a se stante
|
|
59
|
+
endDay = new Date(startDay.valueOf());
|
|
60
|
+
if(week === 1 && cfg.jan1DayOfTheWeek < 5) {
|
|
61
|
+
endDay = new Date(endDay.setDate(endDay.getDate() + 7 - cfg.jan1DayOfTheWeek));
|
|
62
|
+
} else {
|
|
63
|
+
endDay = new Date(endDay.setDate(endDay.getDate() + 6));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// forza l'ultmo giorno dell'ultima settimana al 31 dic anche se non è domenica
|
|
67
|
+
// e si tratta dell'ultima settimana
|
|
68
|
+
if(endDay.getFullYear() > year || week === cfg.weeks) {
|
|
69
|
+
endDay = dec31;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
// nel caso in cui la settimana sia la prima o l'ultima,viene restituito un terzo elemento
|
|
74
|
+
// a indicare, rispettivamente, se 1 gennaio corrisponde all'inizio reale della 1a settimana
|
|
75
|
+
// o se 31 dic corrisponde all'ultimo giorno dell'ultima settimana
|
|
76
|
+
|
|
77
|
+
if(week === 1) {
|
|
78
|
+
return [startDay, endDay, +firstMonday === +cfg.jan1];
|
|
79
|
+
|
|
80
|
+
} else if (week === cfg.weeks) {
|
|
81
|
+
return [startDay, endDay, +dec31 === +lastDayOfLastWeek];
|
|
82
|
+
|
|
83
|
+
} else {
|
|
84
|
+
return [startDay, endDay];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
} else {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
if(data) {
|
|
95
|
+
|
|
96
|
+
const weekDates = getDatesOfWeek(data.w),
|
|
97
|
+
dateToLocalOptions = {
|
|
98
|
+
month: 'long',
|
|
99
|
+
day: 'numeric'
|
|
100
|
+
},
|
|
101
|
+
setDateRangeText = () => {
|
|
102
|
+
if(data.w === 0) {
|
|
103
|
+
return null;
|
|
104
|
+
|
|
105
|
+
} else {
|
|
106
|
+
return <>
|
|
107
|
+
<span className="text-nowrap">
|
|
108
|
+
{weekDates[0].toLocaleString('it-IT',
|
|
109
|
+
weekDates[0].getMonth() !== weekDates[1].getMonth()? dateToLocalOptions
|
|
110
|
+
: {day: 'numeric'}
|
|
111
|
+
)}
|
|
112
|
+
</span>
|
|
113
|
+
{' \u2013 '}
|
|
114
|
+
<span className="text-nowrap">{weekDates[1].toLocaleString('it-IT', dateToLocalOptions)}</span>
|
|
115
|
+
</>;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
//weeks:
|
|
120
|
+
//props.data : {
|
|
121
|
+
// "w": 0, <- settimana, 0 = anno prec.
|
|
122
|
+
// "s": 519096, <- budget standard
|
|
123
|
+
// "p": 812136, <- budget positivo
|
|
124
|
+
// "n": 43242, <- budget negativo
|
|
125
|
+
// "c": 674824 <- budget consolidato (null se non presente)
|
|
126
|
+
// "cp": 612345 <- budget consolidato anno precedente
|
|
127
|
+
// }
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
setContent(<>
|
|
132
|
+
|
|
133
|
+
// {weekMode?
|
|
134
|
+
// <>
|
|
135
|
+
// <div className={styles.infoBoxTitle}>{props.data.w? <>Settimana {props.data.w}</> : <>Anno precedente</>}</div>
|
|
136
|
+
// <div className={styles.infoBoxDescr}>{setDateRangeText()}</div>
|
|
137
|
+
// </>
|
|
138
|
+
// :
|
|
139
|
+
// <>{mesi[props.month]}</>
|
|
140
|
+
// }
|
|
141
|
+
|
|
142
|
+
<div className={styles.infoBoxTitle}>{data.w? <>Settimana {data.w}</> : <>Anno precedente</>}</div>
|
|
143
|
+
<div className={styles.infoBoxDescr}>{setDateRangeText()}</div>
|
|
144
|
+
|
|
145
|
+
<table className={styles.infoBoxTable}>
|
|
146
|
+
<tbody>
|
|
147
|
+
{infoBoxItems.map((item, idx) => {
|
|
148
|
+
|
|
149
|
+
return <tr key={nanoid()}>
|
|
150
|
+
<th scope="row" className={item.tdClassName}>
|
|
151
|
+
{item.flagClassName && <span className={classnames(styles.infoBoxFlag, item.flagClassName)} />}
|
|
152
|
+
{item.label}
|
|
153
|
+
</th>
|
|
154
|
+
<td className={item.tdClassName}>{data[item.key] != null?
|
|
155
|
+
<span className="euro">{data[item.key].toLocaleString('it-IT')}</span>
|
|
156
|
+
: '\u2014'}
|
|
157
|
+
</td>
|
|
158
|
+
// =>> infobox: incremento
|
|
159
|
+
{(data[item.key] != null && idx === 0)?
|
|
160
|
+
<td className='pl-2 align-baseline' rowSpan={Object.keys(infoBoxItems).length}>
|
|
161
|
+
{formatDelta(data.c, data.cp)}
|
|
162
|
+
</td>
|
|
163
|
+
: ''
|
|
164
|
+
}
|
|
165
|
+
</tr>;
|
|
166
|
+
})}
|
|
167
|
+
</tbody>
|
|
168
|
+
</table>
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
// weekDates[3] (true/false) è presente solo per la prima e l'ultima settimana
|
|
172
|
+
{weekMode && <>
|
|
173
|
+
{data.w === 1 && !weekDates[3] &&
|
|
174
|
+
<div className={styles.infoBoxNote}>
|
|
175
|
+
NB: sono inclusi anche i giorni precedenti al primo lunedì dell’anno.
|
|
176
|
+
</div>
|
|
177
|
+
}
|
|
178
|
+
{data.w === cfg.weeks && !weekDates[3] &&
|
|
179
|
+
<div className={styles.infoBoxNote}>
|
|
180
|
+
NB: sono inclusi anche i giorni successivi alla domenica dell’ultima settimana.
|
|
181
|
+
</div>
|
|
182
|
+
}
|
|
183
|
+
</>}
|
|
184
|
+
|
|
185
|
+
</>);
|
|
186
|
+
}
|
|
187
|
+
}, [cfg.jan1, cfg.jan1DayOfTheWeek, cfg.weeks, data, infoBoxItems, month, year, weekMode]);
|
|
188
|
+
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
if(dataGroupEl && (week != null || month != null)) {
|
|
191
|
+
|
|
192
|
+
const infoBoxMargin = 8; // distanza dalla linea della griglia della settimana in esame
|
|
193
|
+
|
|
194
|
+
// lato in cui posizionare InfoBox rispetto all'asse della settimana
|
|
195
|
+
let side;
|
|
196
|
+
if(weekMode) {
|
|
197
|
+
side = week > cfg.weeks/2? 'left' : 'right';
|
|
198
|
+
} else {
|
|
199
|
+
side = month > 5? 'left' : 'right';
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
dataGroupEl?.classList.add(styles.dataGroupOn);
|
|
203
|
+
dataGroupEl?.closest(`.${styles.chart}`)?.classList.add(styles.infoBoxWrapperOn);
|
|
204
|
+
|
|
205
|
+
infoBoxWrapperRef.current.setAttribute('transform-origin',
|
|
206
|
+
`${side === 'left'? 'right' : 'left'} top`
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
infoBoxWrapperRef.current.dataset.side = side;
|
|
210
|
+
const infoBoxSize = infoBoxWrapperRef.current.querySelector(':scope > div').getBoundingClientRect();
|
|
211
|
+
// infoBoxWrapperRef.current.setAttribute('height', infoBoxSize.height);
|
|
212
|
+
// infoBoxWrapperRef.current.setAttribute('width', infoBoxSize.width);
|
|
213
|
+
|
|
214
|
+
// let puntoRif;
|
|
215
|
+
// for(const ref of infoBoxPositionRefs) {
|
|
216
|
+
// puntoRif = dataGroupEl.querySelector(`.${styles[ref]}`);
|
|
217
|
+
// if(puntoRif) {
|
|
218
|
+
// break;
|
|
219
|
+
// }
|
|
220
|
+
// }
|
|
221
|
+
|
|
222
|
+
// let y = puntoRif? +puntoRif.getAttribute('cy') : Infinity;
|
|
223
|
+
// y = Math.min(y, cfg.chart_area.top + cfg.chart_area.height - infoBoxSize.height - 5);
|
|
224
|
+
|
|
225
|
+
// posizionamento vicino alle asse X
|
|
226
|
+
let y = cfg.chart_area.top + cfg.chart_area.height - infoBoxSize.height - 5;
|
|
227
|
+
infoBoxWrapperRef.current.setAttribute('y', y);
|
|
228
|
+
|
|
229
|
+
let transformX = weekMode?
|
|
230
|
+
cfg.chart_area.left + ((week - (skipWeek0? 1 : 0)) * cfg.xStep) +
|
|
231
|
+
(side === 'left'? -infoBoxWidth - infoBoxMargin : infoBoxMargin)
|
|
232
|
+
:
|
|
233
|
+
cfg.chart_area.left + ((month - 1) * cfg.xStep) +
|
|
234
|
+
(side === 'left'? -infoBoxWidth - infoBoxMargin: infoBoxMargin) +
|
|
235
|
+
cfg.xStep / 2;
|
|
236
|
+
|
|
237
|
+
infoBoxWrapperRef.current.setAttribute('transform', `translate(${transformX} 0)`);
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
}, [infoBoxWidth, cfg, dataGroupEl, infoBoxPositionRefs, month, skipWeek0, week, weekMode]);
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
return (
|
|
246
|
+
<foreignObject className={styles.infoBoxWrapper}
|
|
247
|
+
x="0" y="-1000"
|
|
248
|
+
width={infoBoxWidth}
|
|
249
|
+
height={300}
|
|
250
|
+
ref={infoBoxWrapperRef}
|
|
251
|
+
>
|
|
252
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
|
253
|
+
{content}
|
|
254
|
+
</div>
|
|
255
|
+
// <div xmlns="http://www.w3.org/1999/xhtml" style={{
|
|
256
|
+
// position: 'absolute',
|
|
257
|
+
// top: 0, left: 0,
|
|
258
|
+
// width: '100%', height: '100%',
|
|
259
|
+
// backgroundColor: 'rgba(255,0,0, .2)'
|
|
260
|
+
// }}></div>
|
|
261
|
+
</foreignObject>
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
InfoBox.propTypes = {
|
|
265
|
+
data : PropTypes.object,
|
|
266
|
+
week : PropTypes.number,
|
|
267
|
+
month : PropTypes.number,
|
|
268
|
+
dataGroupEl : PropTypes.any,
|
|
269
|
+
year : PropTypes.number,
|
|
270
|
+
cfg : PropTypes.object,
|
|
271
|
+
mode : PropTypes.oneOf(['month', 'week']),
|
|
272
|
+
|
|
273
|
+
// array di classi di elementi all'interno di dataGroupEl dai quali ricavare
|
|
274
|
+
// la coordinata y per il posizionamento di InfoBox
|
|
275
|
+
// almeno uno deve essere sicuramente presente
|
|
276
|
+
infoBoxPositionRefs : PropTypes.arrayOf(PropTypes.string),
|
|
277
|
+
|
|
278
|
+
// elementi, etichette, classe td e classe indicatore colorato per la costruzione dell'infoBox
|
|
279
|
+
// nell'ordine in cui verranno mostrate
|
|
280
|
+
infoBoxItems : PropTypes.arrayOf(
|
|
281
|
+
PropTypes.shape({
|
|
282
|
+
key : PropTypes.string,
|
|
283
|
+
label : PropTypes.string,
|
|
284
|
+
tdClassName : PropTypes.string,
|
|
285
|
+
flagClassName : PropTypes.string,
|
|
286
|
+
dataPointClassName : PropTypes.string
|
|
287
|
+
})
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
*/
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
function InfoBox({
|
|
296
|
+
data,
|
|
297
|
+
dataGroupEl,
|
|
298
|
+
cfg,
|
|
299
|
+
// mode, // da eliminare
|
|
300
|
+
infoBoxWidth,
|
|
301
|
+
elementsCount,
|
|
302
|
+
styles,
|
|
303
|
+
title,
|
|
304
|
+
year = new Date().getFullYear(),
|
|
305
|
+
infoBoxItems = [],
|
|
306
|
+
// infoBoxPositionRefs = [],
|
|
307
|
+
extraRows = null
|
|
308
|
+
}) {
|
|
309
|
+
const [content, setContent] = useState(null),
|
|
310
|
+
infoBoxWrapperRef = useRef();
|
|
311
|
+
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
|
|
314
|
+
if(data) {
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
setContent(<>
|
|
318
|
+
|
|
319
|
+
<div className={styles.infoBoxTitle}>{title}</div>
|
|
320
|
+
|
|
321
|
+
<table className={styles.infoBoxTable}>
|
|
322
|
+
<tbody>
|
|
323
|
+
{infoBoxItems.map(item => {
|
|
324
|
+
return <tr key={nanoid()}>
|
|
325
|
+
<th scope="row" className={classnames(item.tdClassName)}>
|
|
326
|
+
{item.flagClassName && <span className={classnames(styles.infoBoxFlag, item.flagClassName)} />}
|
|
327
|
+
{item.label}
|
|
328
|
+
</th>
|
|
329
|
+
<td className={classnames(item.tdClassName)}>{data[item.key] != null?
|
|
330
|
+
<span className="euro">{data[item.key].toLocaleString('it-IT')}</span>
|
|
331
|
+
:
|
|
332
|
+
'—'}
|
|
333
|
+
</td>
|
|
334
|
+
</tr>;
|
|
335
|
+
})}
|
|
336
|
+
{extraRows.map(row => {
|
|
337
|
+
return <tr key={nanoid()}>
|
|
338
|
+
<th scope="row">{row.label}</th>
|
|
339
|
+
<td>{row.value? row.value : '—'} </td>
|
|
340
|
+
</tr>;
|
|
341
|
+
})}
|
|
342
|
+
</tbody>
|
|
343
|
+
</table>
|
|
344
|
+
|
|
345
|
+
</>);
|
|
346
|
+
}
|
|
347
|
+
}, [cfg, data, extraRows, infoBoxItems, styles, title, year]);
|
|
348
|
+
|
|
349
|
+
useEffect(() => {
|
|
350
|
+
if(dataGroupEl) {
|
|
351
|
+
|
|
352
|
+
const infoBoxMargin = 8; // distanza dalla linea della griglia della settimana in esame
|
|
353
|
+
|
|
354
|
+
// lato in cui posizionare InfoBox rispetto all'asse della settimana
|
|
355
|
+
const xKey = dataGroupEl.dataset.xKey,
|
|
356
|
+
side = xKey > Math.floor(elementsCount/2)-1? 'left' : 'right';
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
dataGroupEl.classList.add(styles.dataGroupOn);
|
|
360
|
+
dataGroupEl.closest(`.${styles.chart}`).classList.add(styles.infoBoxWrapperOn);
|
|
361
|
+
|
|
362
|
+
infoBoxWrapperRef.current.setAttribute('transform-origin',
|
|
363
|
+
`${side === 'left'? 'right' : 'left'} top`
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
infoBoxWrapperRef.current.dataset.side = side;
|
|
367
|
+
// const infoBoxSize = infoBoxWrapperRef.current.querySelector(':scope > div').getBoundingClientRect();
|
|
368
|
+
// infoBoxWrapperRef.current.setAttribute('height', infoBoxSize.height);
|
|
369
|
+
// infoBoxWrapperRef.current.setAttribute('width', infoBoxSize.width);
|
|
370
|
+
|
|
371
|
+
// let puntoRif;
|
|
372
|
+
// for(const ref of infoBoxPositionRefs) {
|
|
373
|
+
// puntoRif = dataGroupEl.querySelector(`.${styles[ref]}`);
|
|
374
|
+
// if(puntoRif) {
|
|
375
|
+
// break;
|
|
376
|
+
// }
|
|
377
|
+
// }
|
|
378
|
+
|
|
379
|
+
// let y = puntoRif? +puntoRif.getAttribute('cy') : Infinity;
|
|
380
|
+
// y = Math.min(y, cfg.chart_area.top + cfg.chart_area.height - infoBoxSize.height - 5);
|
|
381
|
+
|
|
382
|
+
// posizionamento vicino alle asse X
|
|
383
|
+
// let y = cfg.chart_area.top + cfg.chart_area.height - infoBoxSize.height - 5;
|
|
384
|
+
// infoBoxWrapperRef.current.setAttribute('y', y);
|
|
385
|
+
|
|
386
|
+
// il metodo precedente provoca all'inizio un posizionamento errato sull'asse y
|
|
387
|
+
infoBoxWrapperRef.current.setAttribute('y', cfg.chart_area.top +10);
|
|
388
|
+
|
|
389
|
+
let transformX = cfg.chart_area.left + (xKey * cfg.xStep) +
|
|
390
|
+
(side === 'left'? -infoBoxWidth - infoBoxMargin - cfg.xStep * .8 : infoBoxMargin);
|
|
391
|
+
|
|
392
|
+
infoBoxWrapperRef.current.setAttribute('transform', `translate(${transformX} 0)`);
|
|
393
|
+
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
}, [infoBoxWidth, cfg, dataGroupEl, styles, elementsCount]);
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
return (
|
|
400
|
+
<foreignObject className={styles.infoBoxWrapper}
|
|
401
|
+
x="0" y="-1000"
|
|
402
|
+
width={infoBoxWidth}
|
|
403
|
+
height={300}
|
|
404
|
+
ref={infoBoxWrapperRef}
|
|
405
|
+
>
|
|
406
|
+
<div xmlns="http://www.w3.org/1999/xhtml">
|
|
407
|
+
{content}
|
|
408
|
+
</div>
|
|
409
|
+
{/* <div xmlns="http://www.w3.org/1999/xhtml" style={{
|
|
410
|
+
position: 'absolute',
|
|
411
|
+
top: 0, left: 0,
|
|
412
|
+
width: '100%', height: '100%',
|
|
413
|
+
backgroundColor: 'rgba(255,0,0, .2)'
|
|
414
|
+
}}></div> */}
|
|
415
|
+
</foreignObject>
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
InfoBox.propTypes = {
|
|
420
|
+
data : PropTypes.object,
|
|
421
|
+
dataGroupEl : PropTypes.any,
|
|
422
|
+
year : PropTypes.number,
|
|
423
|
+
cfg : PropTypes.object,
|
|
424
|
+
|
|
425
|
+
// da eliminare
|
|
426
|
+
// mode : PropTypes.string,
|
|
427
|
+
|
|
428
|
+
// array di classi di elementi all'interno di dataGroupEl dai quali ricavare
|
|
429
|
+
// la coordinata y per il posizionamento di InfoBox
|
|
430
|
+
// almeno uno deve essere sicuramente presente
|
|
431
|
+
// infoBoxPositionRefs : PropTypes.arrayOf(PropTypes.string),
|
|
432
|
+
|
|
433
|
+
// elementi, etichette, classe td e classe indicatore colorato per la costruzione dell'infoBox
|
|
434
|
+
// nell'ordine in cui verranno mostrate
|
|
435
|
+
infoBoxItems : PropTypes.arrayOf(
|
|
436
|
+
PropTypes.shape({
|
|
437
|
+
key : PropTypes.string,
|
|
438
|
+
label : PropTypes.string,
|
|
439
|
+
tdClassName : PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
|
440
|
+
flagClassName : PropTypes.oneOfType([PropTypes.array, PropTypes.string]),
|
|
441
|
+
})
|
|
442
|
+
),
|
|
443
|
+
|
|
444
|
+
// larghezza da assegnare all'elemento foreignObject
|
|
445
|
+
infoBoxWidth: PropTypes.number,
|
|
446
|
+
|
|
447
|
+
// numero di elementi sui quali mostrare infoBox (per la posizione dx o sx)
|
|
448
|
+
elementsCount: PropTypes.number,
|
|
449
|
+
|
|
450
|
+
/** righe extra da aggiungere alla infobox */
|
|
451
|
+
extraRows: PropTypes.array
|
|
452
|
+
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
export default InfoBox;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
nelle funzioni dei singoli grafici aggiungere `const chartInstance = this;` e sostituire i `this` riferiti ad `adaChart` con `chartInstance`
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
****
|
|
5
|
+
|
|
6
|
+
Tutte le funzioni condivise, ad eccezione di `createSvgCanvas`, sono ora standalone e vanno importate dove necessario.
|
|
7
|
+
|
|
8
|
+
`chartUtils`, `textToSvgPath` e `parseStdAxisOpts` vanno importate e utilizzate direttamente, rimuovendo `this.` o `this.utils.` nel caso di quelle in `chart-utils.js`
|
|
9
|
+
|
|
10
|
+
* `import { parseContainer, truncateDecimal, toRadians, polarToCartesian, classnames, classnamesNull, calcArcCoords, calcAttrD, getElementFromContainer } from '../chart-utils.js';`
|
|
11
|
+
* `import { textToSvgPath } from '../svg-text-to-path.js'`;
|
|
12
|
+
* `import { parseStdAxisOpts } from '../parse-std-axis-opts.js'`;
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
`cartesianAxis`, `createTextEl`, `legenda`, vanno invocate passando come primo parametro l'istanza della classe, esempio:
|
|
16
|
+
|
|
17
|
+
* `import { cartesianAxis } from '../cartesian-axis.js';`
|
|
18
|
+
* `import { createTextEl } from '../create-text-element.js';`
|
|
19
|
+
* `import { legenda } from '../legenda.js';`
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const titleEl = await createTextEl (chartInstance, {
|
|
23
|
+
text: yAxisTitle,
|
|
24
|
+
textFill: yAxisTitleAttrs.fill?? '#000',
|
|
25
|
+
fontAttr: yAxisTitleAttrs,
|
|
26
|
+
fontFilePath: yAxisTitleFontFilePath,
|
|
27
|
+
parentElement: titleGroup
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
****
|
|
32
|
+
|
|
33
|
+
`createTextEl` non restituisce più bbox ed elemento ma solo quest'ultimo.
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
// Cambiare
|
|
37
|
+
|
|
38
|
+
const [labelBbox, labelEl] = await chartInstance.createTextEl({...})
|
|
39
|
+
|
|
40
|
+
// in
|
|
41
|
+
|
|
42
|
+
const labelEl = await createTextEl(chartInstance, {...}),
|
|
43
|
+
labelBbox = labelEl.bbox()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
****
|
|
47
|
+
|
|
48
|
+
L'argomento di parseContainer è ora un oggetto (`function parseContainer({container = null, width = null, height = null, emptyContainer = true}) {...}`), la funzione va quindi invocata specificando i parametri
|
|
49
|
+
|
|
50
|
+
parseContainer ora non svuota più l'elemento
|
|
51
|
+
****
|
|
52
|
+
|
|
53
|
+
gli argomenti di polarToCartesian non utilizzano più un oggetto per x e y
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Da fare
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
decidere se includere anche il grafico settimanale o no
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
documentare modalità di estensione della classe
|
|
5
|
+
|
|
6
|
+
https://claude.ai/share/551e5453-02fd-4a6c-8147-1197d6908a8d
|
|
7
|
+
|
|
8
|
+
```javascript
|
|
9
|
+
// my-project/charts/index.js
|
|
10
|
+
import { AdaCharts, barsChart, goalChart } from 'ada-charts'; // re-export originali
|
|
11
|
+
import { myCustomBar } from './my-custom-bar.js';
|
|
12
|
+
import { myTimeline } from './my-timeline.js';
|
|
13
|
+
|
|
14
|
+
// wrapper per i grafici del progetto (stesso pattern)
|
|
15
|
+
export const myCustomBarChart = (chartInstance, params) =>
|
|
16
|
+
myCustomBar.call(chartInstance, params);
|
|
17
|
+
|
|
18
|
+
export const myTimelineChart = (chartInstance, params) =>
|
|
19
|
+
myTimeline.call(chartInstance, params);
|
|
20
|
+
|
|
21
|
+
// re-esporta tutto dalla libreria base
|
|
22
|
+
export { AdaCharts, barsChart, goalChart };
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
custom chart:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// my-project/charts/my-custom-bar.js
|
|
29
|
+
export function myCustomBar(params) {
|
|
30
|
+
// `this` è l'istanza AdaCharts
|
|
31
|
+
const { data, color = '#333' } = params;
|
|
32
|
+
|
|
33
|
+
// usa i metodi/proprietà di AdaCharts normalmente
|
|
34
|
+
const svg = this.createSVG(); // o come AdaCharts espone il canvas
|
|
35
|
+
|
|
36
|
+
// logica del grafico...
|
|
37
|
+
return svg;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// parametri di configurazione
|
|
2
|
+
|
|
3
|
+
export default function () {
|
|
4
|
+
|
|
5
|
+
const cfg = {
|
|
6
|
+
|
|
7
|
+
asseY_steps : 4, // suddivisioni asse y
|
|
8
|
+
legenda : {
|
|
9
|
+
h : 25, // altezza spazio legenda
|
|
10
|
+
lines_width : 20, // larghezza righe legenda
|
|
11
|
+
circles_radius : 8, // raggio legenda aree
|
|
12
|
+
text_gap : 4, // spazio tra il simbolo e il testo
|
|
13
|
+
text_dy : 4,
|
|
14
|
+
elements_gap : 20 // spazio tra gli elementi della legenda
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
eti_asseY_width : 60, // spazio etichette asse y
|
|
18
|
+
eti_asseX_height : 30, // spazio etichette asse x (grafico settimanale)
|
|
19
|
+
padding : 10, // spazio extra attorno al bordo
|
|
20
|
+
|
|
21
|
+
// altezza o larghezza ticks (secondo l'orientamento)
|
|
22
|
+
ticks : 5,
|
|
23
|
+
|
|
24
|
+
// spazio tra le barre dello stesso gruppo negli istogrammi
|
|
25
|
+
bar_gap : 3,
|
|
26
|
+
|
|
27
|
+
// margine dx e sx tra ogni gruppo di barre dalla sezione
|
|
28
|
+
bar_margin : 6,
|
|
29
|
+
|
|
30
|
+
// altezza aggiuntiva delle aree di evidenziazione dei mesi (solo g. settimanale)
|
|
31
|
+
months_bg_extra_height : 30
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return cfg;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
// =>> chart area
|
|
39
|
+
// coordinate del rettangolo interno all'svg entro cui viene disegnato il grafico
|
|
40
|
+
// i lati sx e inferiore corrispondono agli assi
|
|
41
|
+
// la variabile cfg.chart_area contiene le distanze dal bordo dei 4 lati del rettangolo
|
|
42
|
+
// e le dimensioni dei lati
|
|
43
|
+
export function setChartArea(cfg, svgWidth, svgHeight) {
|
|
44
|
+
return {
|
|
45
|
+
top : cfg.legenda.h + cfg.padding,
|
|
46
|
+
right : svgWidth - cfg.padding,
|
|
47
|
+
bottom : svgHeight - cfg.eti_asseX_height - cfg.padding,
|
|
48
|
+
left : cfg.eti_asseY_width + cfg.padding,
|
|
49
|
+
width : svgWidth - (cfg.padding * 2) - cfg.eti_asseY_width,
|
|
50
|
+
height : svgHeight - (cfg.padding * 2) - cfg.legenda.h - cfg.eti_asseX_height
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// console.log(cfg.chart_area);
|
|
55
|
+
|
|
56
|
+
// =>> conversione valori in coordinate relative al grafico
|
|
57
|
+
export function valueToYCoord(value, cfg) {
|
|
58
|
+
// la coordinata y è ricavata dalla proporzione con il valore massimo e altezza del grafico
|
|
59
|
+
// => cfg.max_value : cfg.chart_area.height = value : y
|
|
60
|
+
// arrotondata a 4 cifre decimali
|
|
61
|
+
|
|
62
|
+
if(value == null) {
|
|
63
|
+
return 0;
|
|
64
|
+
}
|
|
65
|
+
return Math.round((cfg.chart_area.top + cfg.chart_area.height - ((value * cfg.chart_area.height) / cfg.max_value)) * 1e4) / 1e4;
|
|
66
|
+
}
|