@massimo-cassandro/minimo 0.12.2 → 0.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -186,11 +186,14 @@ cols: [
|
|
|
186
186
|
|
|
187
187
|
_title, // Testo del tooltip sull'intestazione (attributo `title` dell'<abbr>).
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
//
|
|
191
|
-
//
|
|
192
|
-
//
|
|
193
|
-
//
|
|
189
|
+
_render, // Template HTML per il contenuto della cella.
|
|
190
|
+
// Accetta:
|
|
191
|
+
// - stringa mustache-like: i segnaposto [[chiave]] vengono sostituiti
|
|
192
|
+
// con i valori della riga (notazione punto: [[owner.nome]]).
|
|
193
|
+
// I segnaposto null usano _renderNullAs; se il padre dell'oggetto è
|
|
194
|
+
// null (es. Symfony restituisce owner: null) non viene emesso alcun
|
|
195
|
+
// warning (il dato è semplicemente assente, non un errore di config).
|
|
196
|
+
// - funzione (row) => string
|
|
194
197
|
|
|
195
198
|
_renderMode, // Preset di visualizzazione predefiniti. Valori disponibili:
|
|
196
199
|
// 'id' – colonna numerica, non ricercabile, allineata a destra
|
|
@@ -199,7 +202,7 @@ cols: [
|
|
|
199
202
|
// 'sf_datetime' – data/ora da oggetto Symfony ({ date, timezone })
|
|
200
203
|
|
|
201
204
|
_sortValue, // Percorso del campo da usare per l'ORDINAMENTO al posto del contenuto
|
|
202
|
-
// visualizzato. Utile quando la cella contiene HTML composto (
|
|
205
|
+
// visualizzato. Utile quando la cella contiene HTML composto (_render).
|
|
203
206
|
// Supporta notazione punto.
|
|
204
207
|
// Implementato tramite l'attributo data-order sulla cella, letto
|
|
205
208
|
// nativamente da simple-datatables.
|
|
@@ -238,12 +241,12 @@ const cols = [
|
|
|
238
241
|
{
|
|
239
242
|
_field: 'commessa',
|
|
240
243
|
_heading: 'Commessa / fornitore',
|
|
241
|
-
|
|
244
|
+
_render: '[[commessa]]<br><small class="text-muted">[[fornitore]]</small>',
|
|
242
245
|
},
|
|
243
246
|
{
|
|
244
247
|
_field: 'owner.cognome',
|
|
245
248
|
_heading: 'Owner',
|
|
246
|
-
|
|
249
|
+
_render: '[[owner.nome]] [[owner.cognome]]',
|
|
247
250
|
_sortValue: 'owner.cognome', // ordina per cognome
|
|
248
251
|
_searchValue: 'owner.cognome owner.nome', // cerca su cognome e nome (AND)
|
|
249
252
|
},
|
|
@@ -21,10 +21,25 @@ import caretRightIcon from '../../icons/caret-right.svg?inline';
|
|
|
21
21
|
* @typedef {object} ColDefinition
|
|
22
22
|
* @property {string} _heading Intestazione della colonna (obbligatorio).
|
|
23
23
|
* @property {string} _field Chiave del campo nell'oggetto dato (obbligatorio).
|
|
24
|
-
* @property {string} [
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* @property {string|Function} [_headingTitle] Testo del tooltip sull'intestazione (`<abbr title="…">`).
|
|
25
|
+
* Accetta:
|
|
26
|
+
* - stringa semplice (tooltip statico)
|
|
27
|
+
* - stringa mustache-like con segnaposto `[[key]]`
|
|
28
|
+
* (interpolati sui dati della prima riga disponibile;
|
|
29
|
+
* utile solo se il titolo varia per colonna, non per riga)
|
|
30
|
+
* - funzione `(row) => string` (row è null per le intestazioni)
|
|
31
|
+
* @property {string|Function} [_cellTitle] Testo del tooltip delle celle (attributo `title`).
|
|
32
|
+
* Accetta:
|
|
33
|
+
* - stringa semplice (tooltip statico uguale per tutte le righe)
|
|
34
|
+
* - stringa mustache-like con segnaposto `[[key]]`
|
|
35
|
+
* (i segnaposto vengono sostituiti con i valori della riga corrente)
|
|
36
|
+
* - funzione `(row) => string` (riceve l'oggetto riga corrente)
|
|
37
|
+
* @property {string|Function} [_render] Template HTML per il contenuto della cella.
|
|
38
|
+
* Accetta:
|
|
39
|
+
* - stringa mustache-like con segnaposto `[[key]]`
|
|
40
|
+
* (sostituiti con i valori dell'oggetto riga;
|
|
41
|
+
* i segnaposto non trovati usano `_renderNullAs`)
|
|
42
|
+
* - funzione `(row) => string`
|
|
28
43
|
* @property {string|Function} [_sortValue] Percorso del campo da usare per l'ORDINAMENTO al posto
|
|
29
44
|
* del contenuto visualizzato, oppure una funzione
|
|
30
45
|
* `(row) => string|number` per casi complessi
|
|
@@ -39,7 +54,7 @@ import caretRightIcon from '../../icons/caret-right.svg?inline';
|
|
|
39
54
|
* @property {string} [_renderNullAs] Stringa da mostrare al posto di valori null/undefined.
|
|
40
55
|
* Default: `'—'` (trattino em).
|
|
41
56
|
* Applicato al valore della cella e ai segnaposto
|
|
42
|
-
* di `
|
|
57
|
+
* di `_render` che si risolvono a null.
|
|
43
58
|
* @property {'id'|'email'|'sf_datetime'} [_renderMode]
|
|
44
59
|
* Modalità di visualizzazione predefinita:
|
|
45
60
|
* - `id` – colonna numerica, non ricercabile, allineata a destra
|
|
@@ -92,6 +107,60 @@ function getNestedValue(obj, path) {
|
|
|
92
107
|
}
|
|
93
108
|
|
|
94
109
|
|
|
110
|
+
/**
|
|
111
|
+
* resolveTemplate
|
|
112
|
+
*
|
|
113
|
+
* Risolve un template in base al suo tipo:
|
|
114
|
+
* - Funzione: invocata con `row`, deve restituire una stringa.
|
|
115
|
+
* - Stringa mustache-like ([[key]]): i segnaposto vengono sostituiti con i
|
|
116
|
+
* valori corrispondenti dell'oggetto riga.
|
|
117
|
+
* - Stringa semplice: restituita così com'è (utile per tooltip statici).
|
|
118
|
+
*
|
|
119
|
+
* Quando `row` è null/undefined (caso intestazioni) le funzioni vengono
|
|
120
|
+
* comunque chiamate con null; la stringa mustache-like viene restituita
|
|
121
|
+
* letteralmente perché non ci sono dati da interpolare.
|
|
122
|
+
*
|
|
123
|
+
* @param {string|Function} tpl Template da risolvere.
|
|
124
|
+
* @param {object|null} row Oggetto riga corrente (null per le intestazioni).
|
|
125
|
+
* @param {object} [opts] Opzioni aggiuntive.
|
|
126
|
+
* @param {string} [opts.nullAs] Stringa da usare come fallback per i segnaposto
|
|
127
|
+
* che si risolvono a null (default: `''`).
|
|
128
|
+
* Se non fornita i segnaposto non trovati diventano ''.
|
|
129
|
+
* @param {number} [opts.warnColIdx] Se fornito, emette console.error quando una
|
|
130
|
+
* chiave foglia non esiste sul padre (indica un errore
|
|
131
|
+
* di configurazione, non un dato assente).
|
|
132
|
+
* @returns {string|null} Stringa risolta, oppure null se `tpl` è falsy.
|
|
133
|
+
*/
|
|
134
|
+
function resolveTemplate(tpl, row, { nullAs = '', warnColIdx } = {}) {
|
|
135
|
+
if (!tpl) return null;
|
|
136
|
+
|
|
137
|
+
if (typeof tpl === 'function') {
|
|
138
|
+
return tpl(row) ?? null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Stringa mustache-like: interpola solo se row è disponibile
|
|
142
|
+
if (row != null && /\[\[.*?\]\]/.test(tpl)) {
|
|
143
|
+
return decodeURIComponent(tpl).replace(
|
|
144
|
+
/\[\[(.*?)\]\]/g,
|
|
145
|
+
(_, key) => {
|
|
146
|
+
const resolved = getNestedValue(row, key);
|
|
147
|
+
if (warnColIdx !== undefined) {
|
|
148
|
+
const pathParts = key.split('.');
|
|
149
|
+
const parentObj = pathParts.length > 1
|
|
150
|
+
? getNestedValue(row, pathParts.slice(0, -1).join('.'))
|
|
151
|
+
: row;
|
|
152
|
+
if (parentObj != null && !Object.prototype.hasOwnProperty.call(parentObj, pathParts.at(-1))) {
|
|
153
|
+
// eslint-disable-next-line no-console
|
|
154
|
+
console.error(`[s-datatable] Chiave "${key}" non trovata nella struttura dati (colonna ${warnColIdx})`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return resolved ?? nullAs;
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return tpl;
|
|
163
|
+
}
|
|
95
164
|
|
|
96
165
|
class SimpleDatatableAdapter extends HTMLElement {
|
|
97
166
|
constructor() {
|
|
@@ -343,11 +412,12 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
343
412
|
rawData = parsed.data;
|
|
344
413
|
}
|
|
345
414
|
|
|
346
|
-
this.headings = cols.map(item =>
|
|
347
|
-
item.
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
415
|
+
this.headings = cols.map(item => {
|
|
416
|
+
const title = resolveTemplate(item._headingTitle, null);
|
|
417
|
+
return title
|
|
418
|
+
? `<abbr title="${title}">${item._heading}</abbr>`
|
|
419
|
+
: item._heading;
|
|
420
|
+
});
|
|
351
421
|
|
|
352
422
|
this.data = rawData.map((row, idx) => ({
|
|
353
423
|
attributes: { 'data-jidx': idx },
|
|
@@ -370,36 +440,12 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
370
440
|
: null;
|
|
371
441
|
|
|
372
442
|
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
value = decodeURIComponent(col_item._renderTpl).replace(
|
|
380
|
-
/\[\[(.*?)\]\]/g,
|
|
381
|
-
(match, key) => {
|
|
382
|
-
const resolved = getNestedValue(row, key);
|
|
383
|
-
const pathParts = key.split('.');
|
|
384
|
-
const parentObj = pathParts.length > 1
|
|
385
|
-
? getNestedValue(row, pathParts.slice(0, -1).join('.'))
|
|
386
|
-
: row;
|
|
387
|
-
|
|
388
|
-
// Segnala solo se il padre esiste ma la chiave foglia manca
|
|
389
|
-
// (errore di configurazione). Se il padre è null il dato è
|
|
390
|
-
// semplicemente assente (es. Symfony restituisce owner: null).
|
|
391
|
-
if (parentObj != null && !Object.prototype.hasOwnProperty.call(parentObj, pathParts.at(-1))) {
|
|
392
|
-
// eslint-disable-next-line no-console
|
|
393
|
-
console.error(`[s-datatable] Chiave "${key}" non trovata nella struttura dati (colonna ${col_idx})`);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
return resolved ?? nullAs;
|
|
397
|
-
}
|
|
398
|
-
);
|
|
399
|
-
|
|
400
|
-
} else if (typeof col_item._renderTpl === 'function') {
|
|
401
|
-
value = col_item._renderTpl(row);
|
|
402
|
-
}
|
|
443
|
+
// _render: template per il rendering del valore.
|
|
444
|
+
// Accetta stringa mustache-like ([[key]]) o funzione (row) => string.
|
|
445
|
+
// Delega a resolveTemplate, passando nullAs e l'indice di colonna
|
|
446
|
+
// per i warning di chiavi mancanti.
|
|
447
|
+
if (col_item._render) {
|
|
448
|
+
value = resolveTemplate(col_item._render, row, { nullAs, warnColIdx: col_idx });
|
|
403
449
|
|
|
404
450
|
} else if (col_item._renderMode === 'sf_datetime' && value != null) {
|
|
405
451
|
value = value.date.replace(' ', 'T') +
|
|
@@ -408,7 +454,7 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
408
454
|
|
|
409
455
|
// Applica _renderNullAs al valore della cella se null/undefined
|
|
410
456
|
// e la cella non ha già un template che gestisce la visualizzazione.
|
|
411
|
-
if (value == null &&
|
|
457
|
+
if (value == null && col_item._render == null) {
|
|
412
458
|
value = nullAs;
|
|
413
459
|
}
|
|
414
460
|
|
|
@@ -431,10 +477,21 @@ class SimpleDatatableAdapter extends HTMLElement {
|
|
|
431
477
|
// - `data` → contenuto visualizzato (obbligatorio)
|
|
432
478
|
// - `order` → valore alternativo per l'ordinamento (campo nativo)
|
|
433
479
|
// - `attributes['data-search']` → stringa su cui opera searchMethod
|
|
434
|
-
|
|
480
|
+
// - `attributes['title']` → tooltip della cella (_cellTitle)
|
|
481
|
+
|
|
482
|
+
// Risolvi _cellTitle: stringa semplice, mustache-like o funzione(row)
|
|
483
|
+
const cellTitle = resolveTemplate(col_item._cellTitle, row);
|
|
484
|
+
|
|
485
|
+
if (sortValue !== null || searchValue !== null || cellTitle !== null) {
|
|
435
486
|
const cellObj = { data: value ?? '' };
|
|
436
487
|
if (sortValue !== null) cellObj.order = sortValue;
|
|
437
|
-
|
|
488
|
+
|
|
489
|
+
// Unifica data-search e title in un unico oggetto attributes
|
|
490
|
+
const attrs = {};
|
|
491
|
+
if (searchValue !== null) attrs['data-search'] = searchValue;
|
|
492
|
+
if (cellTitle !== null) attrs['title'] = cellTitle;
|
|
493
|
+
if (Object.keys(attrs).length) cellObj.attributes = attrs;
|
|
494
|
+
|
|
438
495
|
return cellObj;
|
|
439
496
|
}
|
|
440
497
|
|