wuic-framework-lib 1.0.20 → 1.1.0
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/fesm2022/{wuic-framework-lib-chart-list.component-B44k_wZe.mjs → wuic-framework-lib-chart-list.component-C9_EDkGu.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-code-editor.component-D1dy4Dl9.mjs → wuic-framework-lib-code-editor.component-D_p7LGSQ.mjs} +4 -4
- package/fesm2022/{wuic-framework-lib-designer.component-CnOQbvEH.mjs → wuic-framework-lib-designer.component-Dx6RraAn.mjs} +4 -4
- package/fesm2022/{wuic-framework-lib-first-run-wizard.component-C9lswoxG.mjs → wuic-framework-lib-first-run-wizard.component-Cp8IKDb9.mjs} +4 -4
- package/fesm2022/{wuic-framework-lib-framework-docs.component-B6qNTs5H.mjs → wuic-framework-lib-framework-docs.component-CxckBsIX.mjs} +406 -10
- package/fesm2022/{wuic-framework-lib-pivot-builder.component-DMk26H0M.mjs → wuic-framework-lib-pivot-builder.component-C-ceJi48.mjs} +10 -10
- package/fesm2022/{wuic-framework-lib-prompt-dialog-fallback-host.component-y3shST6g.mjs → wuic-framework-lib-prompt-dialog-fallback-host.component-DPZCgxOB.mjs} +3 -3
- package/fesm2022/{wuic-framework-lib-report-designer.component-BnngR2eL.mjs → wuic-framework-lib-report-designer.component-3-hUYft8.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-report-viewer.component-LGNRIQh2.mjs → wuic-framework-lib-report-viewer.component-D4QD_wPl.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-scheduler-list.component-DbcFMwx5.mjs → wuic-framework-lib-scheduler-list.component-C0nY8Wd6.mjs} +2 -2
- package/fesm2022/{wuic-framework-lib-spreadsheet-list-sf.component-DXyRX0YK.mjs → wuic-framework-lib-spreadsheet-list-sf.component-C9sWgq61.mjs} +443 -4
- package/fesm2022/{wuic-framework-lib-workflow-designer.component-Bm719AWV.mjs → wuic-framework-lib-workflow-designer.component-8mv_Rbz9.mjs} +4 -4
- package/fesm2022/{wuic-framework-lib-wuic-framework-lib-CGCZvtKK.mjs → wuic-framework-lib-wuic-framework-lib-DJZAYFw8.mjs} +4887 -3819
- package/fesm2022/wuic-framework-lib.mjs +1 -1
- package/package.json +1 -1
- package/types/wuic-framework-lib.d.ts +1575 -1005
|
@@ -7,7 +7,7 @@ import * as i8 from '@ngx-translate/core';
|
|
|
7
7
|
import { TranslateModule } from '@ngx-translate/core';
|
|
8
8
|
import * as i7 from '@syncfusion/ej2-angular-spreadsheet';
|
|
9
9
|
import { SpreadsheetModule } from '@syncfusion/ej2-angular-spreadsheet';
|
|
10
|
-
import { W as WtoolboxService, M as MetadataProviderService, U as UserInfoService, b as DataSourceComponent, I as ImportExportButtonComponent } from './wuic-framework-lib-wuic-framework-lib-
|
|
10
|
+
import { W as WtoolboxService, M as MetadataProviderService, U as UserInfoService, b as DataSourceComponent, I as ImportExportButtonComponent } from './wuic-framework-lib-wuic-framework-lib-DJZAYFw8.mjs';
|
|
11
11
|
import { registerLicense } from '@syncfusion/ej2-base';
|
|
12
12
|
import * as i1 from '@angular/platform-browser';
|
|
13
13
|
import * as i1$1 from '@angular/router';
|
|
@@ -360,6 +360,78 @@ class SpreadsheetListSfComponent {
|
|
|
360
360
|
datasource;
|
|
361
361
|
hardcodedDatasource;
|
|
362
362
|
hideToolbar = false;
|
|
363
|
+
// ============================================================
|
|
364
|
+
// Lock-awareness API (opt-in, additive — non rompe API legacy)
|
|
365
|
+
// ------------------------------------------------------------
|
|
366
|
+
// GENERIC + METADATA-DRIVEN (no app-specific naming hardcoded).
|
|
367
|
+
//
|
|
368
|
+
// Configurazione PER ROUTE in `_metadati__tabelle.md_props_bag`:
|
|
369
|
+
// {
|
|
370
|
+
// "archetypes": {
|
|
371
|
+
// "spreadsheet": {
|
|
372
|
+
// "lock": {
|
|
373
|
+
// "endpointBase": "/api/spreadsheet",
|
|
374
|
+
// "primaryScopeField": "program_id", // field usato come URL path segment
|
|
375
|
+
// "requiredScopeFields": ["program_id"], // field obbligatori per acquire-lock
|
|
376
|
+
// "autoEnableOnScope": true, // se tutti i required presenti → auto-acquire
|
|
377
|
+
// "heartbeatIntervalSec": 60 // override (default 60)
|
|
378
|
+
// },
|
|
379
|
+
// "formulas": { ... }
|
|
380
|
+
// }
|
|
381
|
+
// }
|
|
382
|
+
// }
|
|
383
|
+
//
|
|
384
|
+
// Lo `lockScope` e' un dictionary generico chiave→valore (es. `{program_id:1, year:2026}`),
|
|
385
|
+
// tipicamente popolato dalla lazy-wrapper leggendo i query param della URL.
|
|
386
|
+
// Il component:
|
|
387
|
+
// - In ngAfterViewInit (o post-dataBound se config in mdpropsbag) chiama
|
|
388
|
+
// POST {endpointBase}/lock-range/{lockScope[primaryScopeField]} con body = scope.
|
|
389
|
+
// - Avvia heartbeat timer (default 60s) verso {endpointBase}/heartbeat.
|
|
390
|
+
// - Espone metodi pubblici saveCellsBatch() + releaseLock() + acquireLock().
|
|
391
|
+
// - In ngOnDestroy chiama POST {endpointBase}/release-lock con lockToken.
|
|
392
|
+
//
|
|
393
|
+
// Vedi `SpreadsheetController.cs` di una app concreta (es. CostCnh) per il
|
|
394
|
+
// contratto endpoint. La forma della request: path /:primaryScope, body = scope.
|
|
395
|
+
// ============================================================
|
|
396
|
+
/**
|
|
397
|
+
* Forza attivazione lock-awareness ANCHE se `mdpropsbag.archetypes.spreadsheet.lock.autoEnableOnScope`
|
|
398
|
+
* e' false o assente. Default: false (la decisione viene presa dalla mdpropsbag).
|
|
399
|
+
* Util per scenari programmatici dove un parent override-a la config.
|
|
400
|
+
*/
|
|
401
|
+
enableLockAwareness = false;
|
|
402
|
+
/**
|
|
403
|
+
* Scope di lock generico (record key→value). Tipicamente popolato dalla
|
|
404
|
+
* lazy-wrapper a partire dai query param della URL (es. `?program_id=1&year=2026`),
|
|
405
|
+
* oppure passato esplicitamente da un parent. La mdpropsbag dichiara quale
|
|
406
|
+
* field e' il "primary" (usato come path segment) e quali sono required.
|
|
407
|
+
*/
|
|
408
|
+
lockScope = {};
|
|
409
|
+
/**
|
|
410
|
+
* Override `heartbeatIntervalSec` se settato (>0). Altrimenti viene letto da
|
|
411
|
+
* `mdpropsbag.archetypes.spreadsheet.lock.heartbeatIntervalSec` (default 60).
|
|
412
|
+
*/
|
|
413
|
+
heartbeatIntervalSec;
|
|
414
|
+
// ============================================================
|
|
415
|
+
// Formula / Ribbon UX (additive, default-off per backward compat)
|
|
416
|
+
// ------------------------------------------------------------
|
|
417
|
+
// Syncfusion EJ2 Spreadsheet supporta 350+ funzioni (SUM, AVG, IF, VLOOKUP,
|
|
418
|
+
// INDEX/MATCH, dates, math, financial, logical, lookup) e references inter-cell
|
|
419
|
+
// (=A1+B1, =SUM(C5:C10)). Per attivarle:
|
|
420
|
+
// - [enableCalculation]="true" → engine formula attivo (default era già true Syncfusion)
|
|
421
|
+
// - [showFormulaBar]="true" → barra formula visibile (modifica formula da UI)
|
|
422
|
+
// - [showRibbon]="true" → ribbon completo (funzioni, format, charts)
|
|
423
|
+
//
|
|
424
|
+
// Quando user inserisce '=A1+B1' in una cella:
|
|
425
|
+
// - Syncfusion CALCOLA il valore numerico per display
|
|
426
|
+
// - cellSave event riceve { value: computed, formula: '=A1+B1' }
|
|
427
|
+
// - Component invia entrambi al backend via saveCellsBatch (campo formulaText opzionale)
|
|
428
|
+
// - Backend persiste value in cp.facts.<field> + formula_text in cp.facts_formula (1:1)
|
|
429
|
+
// - Su reload, snapshot re-injection formula in cell → user vede formula in formula bar
|
|
430
|
+
// ============================================================
|
|
431
|
+
/** Mostra formula bar Syncfusion (default false per backward compat). NB: Syncfusion engine formule sempre attivo. */
|
|
432
|
+
showFormulaBar = false;
|
|
433
|
+
/** Mostra ribbon Syncfusion completo (default false). */
|
|
434
|
+
showRibbon = false;
|
|
363
435
|
/**
|
|
364
436
|
* Provider letto da `<wuic-import-export-button>` al click su Export XLS.
|
|
365
437
|
* Arrow function per preservare il binding di `this` quando passata come Input.
|
|
@@ -378,6 +450,14 @@ class SpreadsheetListSfComponent {
|
|
|
378
450
|
onSpreadsheetRowInserted = new EventEmitter();
|
|
379
451
|
onSpreadsheetRowsDeleted = new EventEmitter();
|
|
380
452
|
onSpreadsheetBatchSaved = new EventEmitter();
|
|
453
|
+
/** Emesso dopo successful acquire/refresh lock (vedi SpreadsheetController.lock-range). */
|
|
454
|
+
onLockAcquired = new EventEmitter();
|
|
455
|
+
/** Emesso se acquire-lock ritorna outcome='conflict' (altro utente sta editando). */
|
|
456
|
+
onLockConflict = new EventEmitter();
|
|
457
|
+
/** Emesso al successful release (ngOnDestroy o release esplicito). */
|
|
458
|
+
onLockReleased = new EventEmitter();
|
|
459
|
+
/** Emesso quando heartbeat fallisce (lock scaduto o released da altro). */
|
|
460
|
+
onLockExpired = new EventEmitter();
|
|
381
461
|
// ============================================================
|
|
382
462
|
// Public state (API PUBBLICA COMPATIBILE COL VECCHIO)
|
|
383
463
|
// ============================================================
|
|
@@ -485,6 +565,14 @@ class SpreadsheetListSfComponent {
|
|
|
485
565
|
* enableVirtualization: true è il default Syncfusion, lasciato per performance.
|
|
486
566
|
*/
|
|
487
567
|
sfScrollSettings = { isFinite: true, enableVirtualization: true };
|
|
568
|
+
// ─── Lock-awareness state (Sprint 9.4 framework integration) ─────────────
|
|
569
|
+
/** Token UUID lock corrente. Settato da acquireLock(), letto da save/heartbeat/release. */
|
|
570
|
+
lockToken;
|
|
571
|
+
/** Lock id (numerico) per audit join con cp.spreadsheet_change_log. */
|
|
572
|
+
lockId;
|
|
573
|
+
/** Lock expiry UTC. UI puo' mostrare countdown. */
|
|
574
|
+
lockExpiresUtc;
|
|
575
|
+
heartbeatTimer;
|
|
488
576
|
// ============================================================
|
|
489
577
|
// Constructor
|
|
490
578
|
// ============================================================
|
|
@@ -533,6 +621,13 @@ class SpreadsheetListSfComponent {
|
|
|
533
621
|
}
|
|
534
622
|
});
|
|
535
623
|
}
|
|
624
|
+
// Sprint 9.4 — auto-acquire lock se opt-in @Input.
|
|
625
|
+
// Quando l'opt-in viene da `mdpropsbag.archetypes.spreadsheet.lock.autoEnableOnScope`,
|
|
626
|
+
// l'acquire viene rinviato a `tryAutoAcquireLockFromMetadata()` chiamato post-dataBound
|
|
627
|
+
// (quando metaInfo e' loaded dal datasource).
|
|
628
|
+
if (this.enableLockAwareness) {
|
|
629
|
+
void this.acquireLock();
|
|
630
|
+
}
|
|
536
631
|
}
|
|
537
632
|
ngOnDestroy() {
|
|
538
633
|
this.datasourceReadySubscription?.unsubscribe();
|
|
@@ -540,6 +635,15 @@ class SpreadsheetListSfComponent {
|
|
|
540
635
|
this.themeObserver?.disconnect();
|
|
541
636
|
this.stopColHeaderObserver();
|
|
542
637
|
this.clearPendingLayoutPassTimeouts();
|
|
638
|
+
// Sprint 9.4 — cleanup lock
|
|
639
|
+
if (this.heartbeatTimer) {
|
|
640
|
+
clearInterval(this.heartbeatTimer);
|
|
641
|
+
this.heartbeatTimer = undefined;
|
|
642
|
+
}
|
|
643
|
+
if (this.lockToken) {
|
|
644
|
+
// best-effort release (fire-and-forget — non bloccare destroy)
|
|
645
|
+
void this.releaseLock().catch(() => { });
|
|
646
|
+
}
|
|
543
647
|
try {
|
|
544
648
|
this.sfSpreadsheet?.destroy?.();
|
|
545
649
|
}
|
|
@@ -1487,6 +1591,11 @@ class SpreadsheetListSfComponent {
|
|
|
1487
1591
|
for (const d of delays) {
|
|
1488
1592
|
setTimeout(() => this.syncColumnHeadersWithMetadata(), d);
|
|
1489
1593
|
}
|
|
1594
|
+
// Apply metadata-driven formulas (from mdpropsbag.archetypes.spreadsheet.formulas)
|
|
1595
|
+
this.applyMetadataFormulas();
|
|
1596
|
+
// Auto-acquire lock se mdpropsbag.archetypes.spreadsheet.lock.autoEnableOnScope=true
|
|
1597
|
+
// e tutti i requiredScopeFields sono presenti in lockScope. Idempotente.
|
|
1598
|
+
this.tryAutoAcquireLockFromMetadata();
|
|
1490
1599
|
}
|
|
1491
1600
|
/**
|
|
1492
1601
|
* Sostituisce il testo delle celle nell'header column-letter nativo di
|
|
@@ -3845,8 +3954,320 @@ class SpreadsheetListSfComponent {
|
|
|
3845
3954
|
onWindowResize() {
|
|
3846
3955
|
this.scheduleLayoutPass();
|
|
3847
3956
|
}
|
|
3957
|
+
// ============================================================
|
|
3958
|
+
// Metadata-driven formulas (Sprint 9.4)
|
|
3959
|
+
// ------------------------------------------------------------
|
|
3960
|
+
// Le formule sono definite dichiarativamente in metadata route:
|
|
3961
|
+
// _metadati__tabelle.mdpropsbag → archetypes.spreadsheet.formulas
|
|
3962
|
+
// Shape:
|
|
3963
|
+
// {
|
|
3964
|
+
// "<target_column_name>": "=<expression with {col_name} tokens>",
|
|
3965
|
+
// "balance": "={planned}-{actual}",
|
|
3966
|
+
// "variance_pct": "=IF({planned}=0,0,({actual}/{planned})*100)",
|
|
3967
|
+
// "remaining": "={planned}-{actual}-{committed}"
|
|
3968
|
+
// }
|
|
3969
|
+
// Pattern:
|
|
3970
|
+
// - {col_name} viene sostituito a runtime con l'indirizzo cella Syncfusion
|
|
3971
|
+
// della colonna corrispondente sulla riga corrente (es. row 2 → C2, D2)
|
|
3972
|
+
// - L'engine Syncfusion (enableCalculation=true) ricalcola i valori automaticamente
|
|
3973
|
+
// - Quando user modifica una cella source, le celle dipendenti si aggiornano
|
|
3974
|
+
// - On save (cellSave event), il VALUE COMPUTED viene persistito su DB,
|
|
3975
|
+
// la formula non viene memorizzata (resta nei metadati, ri-applicata al refresh)
|
|
3976
|
+
// ============================================================
|
|
3977
|
+
/**
|
|
3978
|
+
* Risolve la lista colonne visibili (idx → col name) dal metaInfo corrente.
|
|
3979
|
+
* Indice 0-based; il caller mappa a column letter A/B/C tramite indexToColumnLetter().
|
|
3980
|
+
*/
|
|
3981
|
+
getVisibleColumnNames() {
|
|
3982
|
+
if (!this.metaInfo?.columnMetadata)
|
|
3983
|
+
return [];
|
|
3984
|
+
return this.metaInfo.columnMetadata
|
|
3985
|
+
.filter(c => !c.mc_hide_in_edit)
|
|
3986
|
+
.map(c => c.mc_nome_colonna || '');
|
|
3987
|
+
}
|
|
3988
|
+
/** Converte indice 0-based in letter A1-notation (0 → 'A', 25 → 'Z', 26 → 'AA'). */
|
|
3989
|
+
indexToColumnLetter(idx) {
|
|
3990
|
+
let s = '';
|
|
3991
|
+
let n = idx;
|
|
3992
|
+
while (n >= 0) {
|
|
3993
|
+
s = String.fromCharCode(65 + (n % 26)) + s;
|
|
3994
|
+
n = Math.floor(n / 26) - 1;
|
|
3995
|
+
}
|
|
3996
|
+
return s;
|
|
3997
|
+
}
|
|
3998
|
+
/**
|
|
3999
|
+
* Risolve il blocco formulas da `metaInfo.tableMetadata.md_props_bag.archetypes.spreadsheet.formulas`.
|
|
4000
|
+
* Ritorna `{}` se non configurato.
|
|
4001
|
+
*/
|
|
4002
|
+
getMetadataFormulas() {
|
|
4003
|
+
const tm = this.metaInfo?.tableMetadata;
|
|
4004
|
+
if (!tm)
|
|
4005
|
+
return {};
|
|
4006
|
+
const pb = tm.md_props_bag || tm.mdpropsbag || tm.extraProps?.md_props_bag;
|
|
4007
|
+
const arch = pb?.archetypes?.spreadsheet;
|
|
4008
|
+
const formulas = arch?.formulas;
|
|
4009
|
+
if (!formulas || typeof formulas !== 'object')
|
|
4010
|
+
return {};
|
|
4011
|
+
return formulas;
|
|
4012
|
+
}
|
|
4013
|
+
/**
|
|
4014
|
+
* Applica le formule metadata-driven a tutte le righe correntemente caricate.
|
|
4015
|
+
* Chiamato post-dataBound. Usa Syncfusion `updateCell({formula: '=...'}, address)`.
|
|
4016
|
+
* Idempotente: ri-chiamabile (sovrascrive la formula con la stessa).
|
|
4017
|
+
*/
|
|
4018
|
+
applyMetadataFormulas() {
|
|
4019
|
+
const formulas = this.getMetadataFormulas();
|
|
4020
|
+
if (!formulas || Object.keys(formulas).length === 0)
|
|
4021
|
+
return;
|
|
4022
|
+
if (!this.sfSpreadsheet)
|
|
4023
|
+
return;
|
|
4024
|
+
const visibleCols = this.getVisibleColumnNames();
|
|
4025
|
+
if (visibleCols.length === 0)
|
|
4026
|
+
return;
|
|
4027
|
+
// Map column name → A1 letter
|
|
4028
|
+
const colIndex = {};
|
|
4029
|
+
visibleCols.forEach((name, idx) => { colIndex[name] = this.indexToColumnLetter(idx); });
|
|
4030
|
+
const rowOffset = 2; // Syncfusion riga 1 = header (showFieldAsHeader), dati partono da riga 2
|
|
4031
|
+
const rowCount = (this.pagedRecords?.length || this.records?.length || 0);
|
|
4032
|
+
for (const [targetCol, formulaTemplate] of Object.entries(formulas)) {
|
|
4033
|
+
const targetLetter = colIndex[targetCol];
|
|
4034
|
+
if (!targetLetter) {
|
|
4035
|
+
console.warn(`[wuic-spreadsheet] formula target column '${targetCol}' not visible — skipped`);
|
|
4036
|
+
continue;
|
|
4037
|
+
}
|
|
4038
|
+
for (let r = 0; r < rowCount; r++) {
|
|
4039
|
+
const sheetRow = rowOffset + r;
|
|
4040
|
+
// Sostituisci tutti i token {colName} con <colLetter><rowNumber>
|
|
4041
|
+
const resolved = formulaTemplate.replace(/\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g, (_m, colName) => {
|
|
4042
|
+
const letter = colIndex[colName];
|
|
4043
|
+
if (!letter) {
|
|
4044
|
+
console.warn(`[wuic-spreadsheet] formula token {${colName}} → column not visible, leaving as-is`);
|
|
4045
|
+
return `{${colName}}`;
|
|
4046
|
+
}
|
|
4047
|
+
return `${letter}${sheetRow}`;
|
|
4048
|
+
});
|
|
4049
|
+
const address = `${targetLetter}${sheetRow}`;
|
|
4050
|
+
try {
|
|
4051
|
+
this.sfSpreadsheet.updateCell?.({ formula: resolved }, address);
|
|
4052
|
+
}
|
|
4053
|
+
catch (e) {
|
|
4054
|
+
console.warn(`[wuic-spreadsheet] updateCell failed at ${address}:`, e);
|
|
4055
|
+
}
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
// ============================================================
|
|
4060
|
+
// Lock-awareness public API (Sprint 9.4 — generic, metadata-driven)
|
|
4061
|
+
// ------------------------------------------------------------
|
|
4062
|
+
// Tutta la config (endpoint base, primaryScopeField, required fields,
|
|
4063
|
+
// heartbeat interval, auto-enable) viene letta da
|
|
4064
|
+
// `metaInfo.tableMetadata.md_props_bag.archetypes.spreadsheet.lock`.
|
|
4065
|
+
// L'@Input `lockScope` (Record<string,any>) e' il dictionary generico
|
|
4066
|
+
// dei valori di lock (es. `{program_id:1, year:2026, scenario_id:7}`),
|
|
4067
|
+
// passato dalla lazy-wrapper a partire dai query param della URL.
|
|
4068
|
+
// ============================================================
|
|
4069
|
+
/**
|
|
4070
|
+
* Estrae la config lock da `mdpropsbag.archetypes.spreadsheet.lock`.
|
|
4071
|
+
* Defaults conservativi se la config manca.
|
|
4072
|
+
*/
|
|
4073
|
+
getLockConfig() {
|
|
4074
|
+
const pb = this.metaInfo?.tableMetadata?.md_props_bag
|
|
4075
|
+
|| this.metaInfo?.tableMetadata?.mdpropsbag
|
|
4076
|
+
|| {};
|
|
4077
|
+
const arch = pb?.archetypes?.spreadsheet?.lock || {};
|
|
4078
|
+
return {
|
|
4079
|
+
endpointBase: typeof arch.endpointBase === 'string' && arch.endpointBase.length > 0
|
|
4080
|
+
? arch.endpointBase
|
|
4081
|
+
: '/api/spreadsheet',
|
|
4082
|
+
primaryScopeField: typeof arch.primaryScopeField === 'string' && arch.primaryScopeField.length > 0
|
|
4083
|
+
? arch.primaryScopeField
|
|
4084
|
+
: null,
|
|
4085
|
+
requiredScopeFields: Array.isArray(arch.requiredScopeFields)
|
|
4086
|
+
? arch.requiredScopeFields.filter((s) => typeof s === 'string')
|
|
4087
|
+
: (arch.primaryScopeField ? [arch.primaryScopeField] : []),
|
|
4088
|
+
autoEnableOnScope: arch.autoEnableOnScope === true,
|
|
4089
|
+
heartbeatIntervalSec: typeof this.heartbeatIntervalSec === 'number' && this.heartbeatIntervalSec > 0
|
|
4090
|
+
? this.heartbeatIntervalSec
|
|
4091
|
+
: (typeof arch.heartbeatIntervalSec === 'number' && arch.heartbeatIntervalSec > 0
|
|
4092
|
+
? arch.heartbeatIntervalSec
|
|
4093
|
+
: 60),
|
|
4094
|
+
};
|
|
4095
|
+
}
|
|
4096
|
+
/**
|
|
4097
|
+
* Valida che lo scope contenga tutti i required fields.
|
|
4098
|
+
* Ritorna lista dei missing (vuota = scope valido).
|
|
4099
|
+
*/
|
|
4100
|
+
validateLockScope(cfg) {
|
|
4101
|
+
return cfg.requiredScopeFields.filter((f) => this.lockScope?.[f] == null);
|
|
4102
|
+
}
|
|
4103
|
+
/**
|
|
4104
|
+
* Trigger auto-acquire post-dataBound (quando metaInfo e' loaded). Idempotente:
|
|
4105
|
+
* non riacquista se gia' c'e' un lockToken attivo. Chiamabile manualmente.
|
|
4106
|
+
* Condizioni per auto-acquire:
|
|
4107
|
+
* - lockToken non gia' attivo
|
|
4108
|
+
* - mdpropsbag.archetypes.spreadsheet.lock.autoEnableOnScope === true
|
|
4109
|
+
* - tutti i requiredScopeFields presenti in lockScope
|
|
4110
|
+
*/
|
|
4111
|
+
tryAutoAcquireLockFromMetadata() {
|
|
4112
|
+
if (this.lockToken)
|
|
4113
|
+
return;
|
|
4114
|
+
const cfg = this.getLockConfig();
|
|
4115
|
+
if (!cfg.autoEnableOnScope)
|
|
4116
|
+
return;
|
|
4117
|
+
const missing = this.validateLockScope(cfg);
|
|
4118
|
+
if (missing.length > 0) {
|
|
4119
|
+
console.info(`[wuic-spreadsheet] auto-acquire skipped — missing scope: ${missing.join(', ')}`);
|
|
4120
|
+
return;
|
|
4121
|
+
}
|
|
4122
|
+
this.enableLockAwareness = true;
|
|
4123
|
+
void this.acquireLock();
|
|
4124
|
+
}
|
|
4125
|
+
/**
|
|
4126
|
+
* Acquisisce lock pessimistic su `lockScope`. Endpoint:
|
|
4127
|
+
* POST {endpointBase}/lock-range/{lockScope[primaryScopeField]} body = lockScope
|
|
4128
|
+
* Emette onLockAcquired (acquired|refreshed) o onLockConflict.
|
|
4129
|
+
* Auto-avvia heartbeat timer se outcome=acquired|refreshed.
|
|
4130
|
+
*/
|
|
4131
|
+
async acquireLock() {
|
|
4132
|
+
const cfg = this.getLockConfig();
|
|
4133
|
+
if (!cfg.primaryScopeField) {
|
|
4134
|
+
console.warn('[wuic-spreadsheet] acquireLock skipped: primaryScopeField non configurato in mdpropsbag.archetypes.spreadsheet.lock');
|
|
4135
|
+
return { outcome: 'skipped' };
|
|
4136
|
+
}
|
|
4137
|
+
const primaryVal = this.lockScope?.[cfg.primaryScopeField];
|
|
4138
|
+
if (primaryVal == null) {
|
|
4139
|
+
console.warn(`[wuic-spreadsheet] acquireLock skipped: lockScope[${cfg.primaryScopeField}] non valorizzato`);
|
|
4140
|
+
return { outcome: 'skipped' };
|
|
4141
|
+
}
|
|
4142
|
+
const missing = this.validateLockScope(cfg);
|
|
4143
|
+
if (missing.length > 0) {
|
|
4144
|
+
console.warn(`[wuic-spreadsheet] acquireLock skipped: missing required scope fields: ${missing.join(', ')}`);
|
|
4145
|
+
return { outcome: 'skipped' };
|
|
4146
|
+
}
|
|
4147
|
+
const url = `${cfg.endpointBase}/lock-range/${encodeURIComponent(String(primaryVal))}`;
|
|
4148
|
+
// Body = lockScope MENO il primaryScopeField (gia' in URL path)
|
|
4149
|
+
const body = {};
|
|
4150
|
+
for (const [k, v] of Object.entries(this.lockScope || {})) {
|
|
4151
|
+
if (k === cfg.primaryScopeField)
|
|
4152
|
+
continue;
|
|
4153
|
+
if (v == null)
|
|
4154
|
+
continue;
|
|
4155
|
+
body[k] = v;
|
|
4156
|
+
}
|
|
4157
|
+
try {
|
|
4158
|
+
const resp = await this.http.post(url, body, { withCredentials: true }).toPromise();
|
|
4159
|
+
if (!resp?.ok) {
|
|
4160
|
+
if (resp?.outcome === 'conflict') {
|
|
4161
|
+
this.onLockConflict.emit({
|
|
4162
|
+
conflictUserId: resp.conflictUserId ?? null,
|
|
4163
|
+
lockExpiresUtc: resp.lockExpiresUtc ? new Date(resp.lockExpiresUtc) : null,
|
|
4164
|
+
});
|
|
4165
|
+
return { outcome: 'conflict', conflictUserId: resp.conflictUserId };
|
|
4166
|
+
}
|
|
4167
|
+
return { outcome: resp?.outcome ?? 'failed' };
|
|
4168
|
+
}
|
|
4169
|
+
this.lockToken = resp.lockToken;
|
|
4170
|
+
this.lockId = resp.lockId;
|
|
4171
|
+
this.lockExpiresUtc = new Date(resp.lockExpiresUtc);
|
|
4172
|
+
this.onLockAcquired.emit({
|
|
4173
|
+
lockToken: resp.lockToken,
|
|
4174
|
+
lockId: resp.lockId,
|
|
4175
|
+
lockExpiresUtc: this.lockExpiresUtc,
|
|
4176
|
+
outcome: resp.outcome,
|
|
4177
|
+
});
|
|
4178
|
+
this.startHeartbeat(cfg.heartbeatIntervalSec);
|
|
4179
|
+
return { outcome: resp.outcome, lockToken: resp.lockToken };
|
|
4180
|
+
}
|
|
4181
|
+
catch (e) {
|
|
4182
|
+
console.error('[wuic-spreadsheet] acquireLock failed', e);
|
|
4183
|
+
return { outcome: 'error' };
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
/**
|
|
4187
|
+
* Single heartbeat (extends TTL). Auto-called dal timer ogni heartbeatIntervalSec.
|
|
4188
|
+
* Emette onLockExpired se backend ritorna 410 Gone.
|
|
4189
|
+
*/
|
|
4190
|
+
async heartbeat() {
|
|
4191
|
+
if (!this.lockToken)
|
|
4192
|
+
return false;
|
|
4193
|
+
const cfg = this.getLockConfig();
|
|
4194
|
+
try {
|
|
4195
|
+
const resp = await this.http.post(`${cfg.endpointBase}/heartbeat`, { lockToken: this.lockToken }, { withCredentials: true }).toPromise();
|
|
4196
|
+
if (resp?.ok) {
|
|
4197
|
+
this.lockExpiresUtc = new Date(resp.lockExpiresUtc);
|
|
4198
|
+
return true;
|
|
4199
|
+
}
|
|
4200
|
+
this.onLockExpired.emit();
|
|
4201
|
+
this.stopHeartbeat();
|
|
4202
|
+
return false;
|
|
4203
|
+
}
|
|
4204
|
+
catch (e) {
|
|
4205
|
+
if (e?.status === 410) {
|
|
4206
|
+
this.onLockExpired.emit();
|
|
4207
|
+
this.stopHeartbeat();
|
|
4208
|
+
}
|
|
4209
|
+
console.warn('[wuic-spreadsheet] heartbeat failed', e?.status ?? e);
|
|
4210
|
+
return false;
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
4213
|
+
/**
|
|
4214
|
+
* Batch save delle modifiche (alternativa al CRUD-per-row standard).
|
|
4215
|
+
* Useful per applicare copy/paste range o bulk edit con singolo round-trip.
|
|
4216
|
+
* @param changes array di { factsId, field, newValue }
|
|
4217
|
+
*/
|
|
4218
|
+
async saveCellsBatch(changes) {
|
|
4219
|
+
if (!this.lockToken) {
|
|
4220
|
+
console.warn('[wuic-spreadsheet] saveCellsBatch: nessun lockToken — call acquireLock() first');
|
|
4221
|
+
return null;
|
|
4222
|
+
}
|
|
4223
|
+
if (!changes || changes.length === 0)
|
|
4224
|
+
return { applied: 0, failed: 0 };
|
|
4225
|
+
const cfg = this.getLockConfig();
|
|
4226
|
+
try {
|
|
4227
|
+
const resp = await this.http.post(`${cfg.endpointBase}/save-cells`, { lockToken: this.lockToken, changes }, { withCredentials: true }).toPromise();
|
|
4228
|
+
return { applied: resp?.applied ?? 0, failed: resp?.failed ?? 0 };
|
|
4229
|
+
}
|
|
4230
|
+
catch (e) {
|
|
4231
|
+
console.error('[wuic-spreadsheet] saveCellsBatch failed', e);
|
|
4232
|
+
return null;
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
/**
|
|
4236
|
+
* Rilascia lock esplicitamente. Idempotente. Stop heartbeat timer.
|
|
4237
|
+
* Auto-chiamato in ngOnDestroy.
|
|
4238
|
+
*/
|
|
4239
|
+
async releaseLock() {
|
|
4240
|
+
if (!this.lockToken)
|
|
4241
|
+
return 0;
|
|
4242
|
+
this.stopHeartbeat();
|
|
4243
|
+
const tok = this.lockToken;
|
|
4244
|
+
this.lockToken = undefined;
|
|
4245
|
+
this.lockExpiresUtc = undefined;
|
|
4246
|
+
const cfg = this.getLockConfig();
|
|
4247
|
+
try {
|
|
4248
|
+
const resp = await this.http.post(`${cfg.endpointBase}/release-lock`, { lockToken: tok }, { withCredentials: true }).toPromise();
|
|
4249
|
+
const released = resp?.released ?? 0;
|
|
4250
|
+
this.onLockReleased.emit({ released });
|
|
4251
|
+
return released;
|
|
4252
|
+
}
|
|
4253
|
+
catch (e) {
|
|
4254
|
+
console.warn('[wuic-spreadsheet] releaseLock failed', e);
|
|
4255
|
+
return 0;
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
startHeartbeat(intervalSec = 60) {
|
|
4259
|
+
this.stopHeartbeat();
|
|
4260
|
+
const intervalMs = Math.max(15, intervalSec) * 1000;
|
|
4261
|
+
this.heartbeatTimer = setInterval(() => { void this.heartbeat(); }, intervalMs);
|
|
4262
|
+
}
|
|
4263
|
+
stopHeartbeat() {
|
|
4264
|
+
if (this.heartbeatTimer) {
|
|
4265
|
+
clearInterval(this.heartbeatTimer);
|
|
4266
|
+
this.heartbeatTimer = undefined;
|
|
4267
|
+
}
|
|
4268
|
+
}
|
|
3848
4269
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SpreadsheetListSfComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.Title }, { token: i1$1.ActivatedRoute }, { token: i1$2.HttpClient }, { token: WtoolboxService }, { token: MetadataProviderService }, { token: UserInfoService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3849
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SpreadsheetListSfComponent, isStandalone: true, selector: "wuic-spreadsheet-list-sf", inputs: { hardcodedRoute: "hardcodedRoute", parentRecord: "parentRecord", parentMetaInfo: "parentMetaInfo", datasource: "datasource", hardcodedDatasource: "hardcodedDatasource", hideToolbar: "hideToolbar" }, outputs: { onSpreadsheetDataBound: "onSpreadsheetDataBound", onSpreadsheetBeforePageChange: "onSpreadsheetBeforePageChange", onSpreadsheetPageChange: "onSpreadsheetPageChange", onSpreadsheetRowInserted: "onSpreadsheetRowInserted", onSpreadsheetRowsDeleted: "onSpreadsheetRowsDeleted", onSpreadsheetBatchSaved: "onSpreadsheetBatchSaved" }, host: { listeners: { "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "sfSpreadsheet", first: true, predicate: ["sfSpreadsheet"], descendants: true }, { propertyName: "lookupSource", first: true, predicate: ["lookupSource"], descendants: true }], ngImport: i0, template: "<!--\n Layout root wrapper:\n 1. Toolbar WUIC custom (insert / save batch / export / refresh)\n 2. Syncfusion Spreadsheet host\n 3. Pagination custom (Syncfusion non ha pagination built-in, quindi la\n rendiamo sotto il foglio con nav + page-size dropdown)\n 4. Lookup datasource (invisibile, pattern identico al vecchio componente)\n-->\n\n<!-- Bootstrap CSS Syncfusion (~500 KiB): si monta solo quando questo\n componente lazy \u00E8 istanziato \u2192 CSS NON nel bundle iniziale globale,\n risparmia ~500 KiB su tutte le pagine che non aprono spreadsheet. -->\n<wuic-syncfusion-styles-bootstrap></wuic-syncfusion-styles-bootstrap>\n\n<div class=\"wuic-sf-spreadsheet-wrapper\">\n\n @if (!hideToolbar && metaInfo) {\n <!-- Stile allineato a <wuic-list-grid>: stessa caption-bar, stessi p-button\n PrimeNG con icona + label, stesso componente import/export. -->\n <div class=\"grid-caption-bar wuic-sf-caption-bar\" role=\"toolbar\" aria-label=\"Spreadsheet toolbar\">\n <div class=\"grid-caption-left\">\n @if (!metaInfo.tableMetadata.md_hide_refresh) {\n <p-button icon=\"pi pi-refresh\" label=\"{{'refresh_grid' | translate}}\"\n (onClick)=\"onToolbarRefresh()\" />\n }\n @if (canInsertRows()) {\n <p-button icon=\"pi pi-plus\" label=\"{{'add_grid' | translate}}\"\n (onClick)=\"onToolbarInsert()\" />\n }\n @if (!metaInfo.tableMetadata.md_hide_export_xls) {\n <!-- Include dialog con progress bar + bottoni \"Stoppa e salva\n parziale\" / \"Stoppa\" / \"Continua in background\". -->\n <wuic-import-export-button\n [routeName]=\"metaInfo.tableMetadata.md_route_name\"\n [tableMetadata]=\"metaInfo.tableMetadata\"\n [filterInfoProvider]=\"getCurrentFilterInfoForExport\"></wuic-import-export-button>\n }\n @if (isBatchSaveEnabled()) {\n <p-button icon=\"pi pi-save\" label=\"{{'list_grid.save_changes' | translate}}\"\n (onClick)=\"onToolbarSaveBatch()\" />\n }\n </div>\n </div>\n }\n\n <div class=\"wuic-sf-spreadsheet-host\">\n @if (metaInfo && sfSheets.length > 0) {\n <ejs-spreadsheet #sfSpreadsheet\n [sheets]=\"sfSheets\"\n [height]=\"sfHeight\"\n [width]=\"sfWidth\"\n [scrollSettings]=\"sfScrollSettings\"\n [showRibbon]=\"false\"\n [showFormulaBar]=\"false\"\n [showSheetTabs]=\"false\"\n [allowEditing]=\"true\"\n [allowSorting]=\"true\"\n [allowFiltering]=\"false\"\n [allowResizing]=\"true\"\n [allowInsert]=\"canInsertRows()\"\n [allowDelete]=\"canDeleteRows()\"\n [enableContextMenu]=\"true\"\n [enableKeyboardNavigation]=\"true\"\n [enableClipboard]=\"true\"\n (created)=\"onSyncfusionCreated()\"\n (dataBound)=\"onSyncfusionDataBound()\"\n (cellSave)=\"onSyncfusionCellSave($event)\"\n (beforeCellSave)=\"onSyncfusionBeforeCellSave($event)\"\n (beforeCellRender)=\"onSyncfusionBeforeCellRender($event)\"\n (cellEdit)=\"onSyncfusionCellEdit($event)\"\n (contextMenuBeforeOpen)=\"onSyncfusionContextMenuBeforeOpen($event)\"\n (contextMenuItemSelect)=\"onSyncfusionContextMenuItemSelect($event)\"\n (actionBegin)=\"onSyncfusionActionBegin($event)\"\n (actionComplete)=\"onSyncfusionActionComplete($event)\"\n (dialogBeforeOpen)=\"onSyncfusionDialogBeforeOpen($event)\">\n </ejs-spreadsheet>\n }\n </div>\n\n @if (totalPages > 1 || totalRecords > pageSize) {\n <div class=\"wuic-sf-pagination\" role=\"navigation\" aria-label=\"Paginazione\">\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(1, pageSize) : setClientPage(1)\"\n title=\"Prima pagina\">\n <i class=\"pi pi-angle-double-left\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex - 1, pageSize) : setClientPage(pageIndex - 1)\"\n title=\"Pagina precedente\">\n <i class=\"pi pi-angle-left\"></i>\n </button>\n <span class=\"wuic-sf-page-info\">\n Pagina <strong>{{ pageIndex }}</strong> di <strong>{{ totalPages }}</strong>\n <span class=\"wuic-sf-page-total\">({{ totalRecords }} record)</span>\n </span>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex + 1, pageSize) : setClientPage(pageIndex + 1)\"\n title=\"Pagina successiva\">\n <i class=\"pi pi-angle-right\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(totalPages, pageSize) : setClientPage(totalPages)\"\n title=\"Ultima pagina\">\n <i class=\"pi pi-angle-double-right\"></i>\n </button>\n <select class=\"wuic-sf-page-size\" [value]=\"pageSize\"\n (change)=\"setPageSize($any($event.target).value)\"\n title=\"Record per pagina\">\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n </select>\n </div>\n }\n\n</div>\n\n@if (!hardcodedRoute) {\n <wuic-data-source #lookupSource [autoload]=\"true\" [routeFromRouting]=\"false\"\n [route]=\"currentRoute\" [parentRecord]=\"currentRecord\"\n [parentMetaInfo]=\"metaInfo\"></wuic-data-source>\n}\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}.wuic-sf-spreadsheet-wrapper{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;overflow:hidden}.wuic-sf-caption-bar{flex:0 0 auto;padding:5px}.grid-caption-left{display:flex;align-items:stretch;gap:.5rem;flex-wrap:nowrap;min-height:2.25rem;height:2.25rem}.wuic-sf-spreadsheet-host{flex:1 1 auto;min-height:0;width:100%;position:relative;overflow:visible}::ng-deep .e-dialog.e-popup-open,::ng-deep .e-excelfilter,::ng-deep .e-filter-popup{z-index:10010!important;min-width:240px}::ng-deep .e-excelfilter .e-footer-content,::ng-deep .e-filter-popup .e-footer-content{display:flex!important;justify-content:flex-end;gap:6px;padding:8px 12px!important}.wuic-sf-spreadsheet-host ejs-spreadsheet{display:block;width:100%;height:100%}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header .e-header-cell-div{font-weight:700!important;text-align:left!important;padding-left:6px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wuic-sf-pagination{display:flex;gap:6px;align-items:center;justify-content:flex-end;padding:6px 10px;background-color:var(--wuic-surface-a, #ffffff);border-top:1px solid var(--wuic-surface-border, #e5e7eb);flex:0 0 auto;font-size:13px}.wuic-sf-page-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;cursor:pointer;color:var(--wuic-text-color, #1f2937);transition:background-color .12s ease,border-color .12s ease}.wuic-sf-page-btn:hover:not(:disabled){background-color:var(--wuic-hover-bg, #f3f4f6);border-color:var(--wuic-primary-color, #6366f1)}.wuic-sf-page-btn:disabled{opacity:.35;cursor:not-allowed}.wuic-sf-page-info{margin:0 8px;white-space:nowrap;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-info strong{color:var(--wuic-text-color, #1f2937)}.wuic-sf-page-total{margin-left:6px;font-size:12px;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-size{margin-left:8px;height:30px;padding:0 8px;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;color:var(--wuic-text-color, #1f2937);cursor:pointer}:host-context(.theme-dark) .wuic-sf-pagination,:host-context([data-theme=\"dark\"]) .wuic-sf-pagination{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn,:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn,:host-context(.theme-dark) .wuic-sf-page-size,:host-context([data-theme=\"dark\"]) .wuic-sf-page-size{color:#f3f4f6;border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn:hover:not(:disabled),:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn:hover:not(:disabled){background-color:#374151}:host-context(.theme-dark) .wuic-sf-page-info,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info{color:#9ca3af}:host-context(.theme-dark) .wuic-sf-page-info strong,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info strong{color:#f3f4f6}:host-context(.theme-dark) .wuic-sf-page-total,:host-context([data-theme=\"dark\"]) .wuic-sf-page-total{color:#9ca3af}:host ::ng-deep .e-spreadsheet{font-family:var(--wuic-font-family, inherit)}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .e-header-cell.wuic-sf-colname-header{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep .e-spreadsheet .e-sheet-content .e-filter-btn{opacity:0!important;pointer-events:none!important;width:0!important;height:0!important;min-width:0!important;padding:0!important;margin:0!important;overflow:hidden!important;position:absolute!important;right:0;top:0}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header{position:relative!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn{position:absolute;right:2px;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;background:transparent;border:none;border-radius:3px;cursor:pointer;color:#475569;flex-shrink:0;transition:background-color .12s,color .12s;z-index:2}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#e2e8f0;color:#1f2937}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg{display:block;pointer-events:none}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet svg,:host ::ng-deep .e-spreadsheet svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#2563eb}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-colname-header .e-header-cell-div{padding-right:22px!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn{color:#cbd5e1}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#334155;color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#60a5fa}:host ::ng-deep .e-spreadsheet .e-sheet-panel{background-color:var(--wuic-surface-a, #ffffff)}:host-context(.theme-dark) ::ng-deep .e-spreadsheet,:host-context([data-theme=\"dark\"]) ::ng-deep .e-spreadsheet,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-sheet-panel,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-main-panel{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-cell{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-row .e-header-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-row-header .e-header-cell{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell.row-danger{background-color:#7f1d1d!important;color:#fecaca!important}:host ::ng-deep .e-cell.row-danger{background-color:#fee2e2!important}:host ::ng-deep .e-cell.row-warning{background-color:#fef3c7!important}:host ::ng-deep .e-cell.row-success{background-color:#d1fae5!important}::ng-deep .wuic-sf-filter-popup{position:fixed;z-index:99999;min-width:260px;max-width:340px;background:#fff;color:#111827;border:1px solid #d1d5db;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:inherit;font-size:13px;display:flex;flex-direction:column;overflow:hidden;-webkit-user-select:none;user-select:none}::ng-deep .wuic-sf-filter-popup-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#f3f4f6;border-bottom:1px solid #e5e7eb;font-weight:600}::ng-deep .wuic-sf-filter-popup-title{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-close{background:transparent;border:none;cursor:pointer;font-size:18px;line-height:1;padding:0 4px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-close:hover{color:#111827}::ng-deep .wuic-sf-filter-popup-sort{display:flex;flex-direction:column;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-sort-btn{background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#111827;display:flex;align-items:center;gap:6px}::ng-deep .wuic-sf-filter-popup-sort-btn:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-sort-icon{font-size:10px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-clear{border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-clear-btn{width:100%;background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#2563eb}::ng-deep .wuic-sf-filter-popup-clear-btn:hover:not(:disabled){background:#eff6ff}::ng-deep .wuic-sf-filter-popup-clear-btn:disabled{color:#9ca3af;cursor:not-allowed}::ng-deep .wuic-sf-filter-popup-search{padding:8px 12px;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-search-input{width:100%;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;font-size:13px;outline:none;box-sizing:border-box}::ng-deep .wuic-sf-filter-popup-search-input:focus{border-color:#2563eb;box-shadow:0 0 0 2px #2563eb33}::ng-deep .wuic-sf-filter-popup-list-wrap{display:flex;flex-direction:column;max-height:260px;overflow:hidden}::ng-deep .wuic-sf-filter-popup-selectall{padding:4px 12px;border-bottom:1px solid #e5e7eb;background:#f9fafb;font-weight:500}::ng-deep .wuic-sf-filter-popup-list{flex:1 1 auto;overflow-y:auto;max-height:220px}::ng-deep .wuic-sf-filter-popup-item{display:flex;align-items:center;gap:6px;padding:4px 12px;cursor:pointer}::ng-deep .wuic-sf-filter-popup-item:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-item input[type=checkbox]{margin:0;flex:0 0 auto}::ng-deep .wuic-sf-filter-popup-item span{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-footer{display:flex;justify-content:flex-end;gap:8px;padding:8px 12px;border-top:1px solid #e5e7eb;background:#f9fafb}::ng-deep .wuic-sf-filter-popup-ok,::ng-deep .wuic-sf-filter-popup-cancel{padding:4px 14px;border:1px solid #d1d5db;border-radius:4px;background:#fff;cursor:pointer;font-size:13px}::ng-deep .wuic-sf-filter-popup-ok{background:#2563eb;color:#fff;border-color:#2563eb}::ng-deep .wuic-sf-filter-popup-ok:hover{background:#1d4ed8}::ng-deep .wuic-sf-filter-popup-cancel:hover{background:#f3f4f6}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active{color:#2563eb}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active svg{fill:#2563eb}::ng-deep .wuic-sf-filter-popup.wuic-sf-filter-popup--dark{background:#1f2937;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-header,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-footer,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-selectall{background:#111827;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-clear,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search{border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{color:#f3f4f6;background:transparent;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-item:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel:hover{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search-input{background:#111827;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close{color:#9ca3af}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close:hover{color:#f3f4f6}::ng-deep .wuic-sf-cell-editor{box-sizing:border-box;padding:2px 6px;border:2px solid #2563eb;background:#fff;color:#111827;font-family:inherit;font-size:13px;outline:none;box-shadow:0 2px 8px #00000026;border-radius:2px}::ng-deep .wuic-sf-cell-editor:focus{border-color:#1d4ed8;box-shadow:0 0 0 2px #2563eb40}::ng-deep select.wuic-sf-cell-editor{cursor:pointer}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark{background:#1f2937;color:#f3f4f6;border-color:#2563eb}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark option{background:#1f2937;color:#f3f4f6}\n"], dependencies: [{ kind: "component", type: DataSourceComponent, selector: "wuic-data-source", inputs: ["route", "routeFromRouting", "hardcodedRoute", "autoload", "loading", "changeTracking", "parentRecord", "parentMetaInfo", "parentDatasource", "useComboEndpoint", "comboFormulaLookup", "comboMcId", "comboField", "comboExtraFields", "comboCurrentRecord", "componentRef"] }, { kind: "ngmodule", type: SpreadsheetModule }, { kind: "component", type: i7.SpreadsheetComponent, selector: "ejs-spreadsheet", inputs: ["activeSheetIndex", "allowAutoFill", "allowCellFormatting", "allowChart", "allowConditionalFormat", "allowDataValidation", "allowDelete", "allowEditing", "allowFiltering", "allowFindAndReplace", "allowFreezePane", "allowHyperlink", "allowImage", "allowInsert", "allowMerge", "allowNumberFormatting", "allowOpen", "allowPrint", "allowResizing", "allowSave", "allowScrolling", "allowSorting", "allowUndoRedo", "allowWrap", "author", "autoFillSettings", "calculationMode", "cellStyle", "cssClass", "currencyCode", "definedNames", "enableClipboard", "enableContextMenu", "enableKeyboardNavigation", "enableKeyboardShortcut", "enableNotes", "enablePersistence", "enableRtl", "height", "isProtected", "listSeparator", "locale", "openSettings", "openUrl", "password", "saveUrl", "scrollSettings", "selectionSettings", "sheets", "showAggregate", "showCommentsPane", "showFormulaBar", "showRibbon", "showSheetTabs", "width"], outputs: ["actionBegin", "actionComplete", "afterHyperlinkClick", "afterHyperlinkCreate", "beforeCellFormat", "beforeCellRender", "beforeCellSave", "beforeCellUpdate", "beforeConditionalFormat", "beforeDataBound", "beforeHyperlinkClick", "beforeHyperlinkCreate", "beforeOpen", "beforeSave", "beforeSelect", "beforeSort", "cellEdit", "cellEdited", "cellEditing", "cellSave", "contextMenuBeforeClose", "contextMenuBeforeOpen", "contextMenuItemSelect", "created", "dataBound", "dataSourceChanged", "dialogBeforeOpen", "fileMenuBeforeClose", "fileMenuBeforeOpen", "fileMenuItemSelect", "openComplete", "openFailure", "queryCellInfo", "saveComplete", "select", "sortComplete"] }, { kind: "component", type: ImportExportButtonComponent, selector: "wuic-import-export-button", inputs: ["routeName", "tableMetadata", "filterInfoProvider"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: SyncfusionStylesBootstrapComponent, selector: "wuic-syncfusion-styles-bootstrap" }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
|
|
4270
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SpreadsheetListSfComponent, isStandalone: true, selector: "wuic-spreadsheet-list-sf", inputs: { hardcodedRoute: "hardcodedRoute", parentRecord: "parentRecord", parentMetaInfo: "parentMetaInfo", datasource: "datasource", hardcodedDatasource: "hardcodedDatasource", hideToolbar: "hideToolbar", enableLockAwareness: "enableLockAwareness", lockScope: "lockScope", heartbeatIntervalSec: "heartbeatIntervalSec", showFormulaBar: "showFormulaBar", showRibbon: "showRibbon" }, outputs: { onSpreadsheetDataBound: "onSpreadsheetDataBound", onSpreadsheetBeforePageChange: "onSpreadsheetBeforePageChange", onSpreadsheetPageChange: "onSpreadsheetPageChange", onSpreadsheetRowInserted: "onSpreadsheetRowInserted", onSpreadsheetRowsDeleted: "onSpreadsheetRowsDeleted", onSpreadsheetBatchSaved: "onSpreadsheetBatchSaved", onLockAcquired: "onLockAcquired", onLockConflict: "onLockConflict", onLockReleased: "onLockReleased", onLockExpired: "onLockExpired" }, host: { listeners: { "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "sfSpreadsheet", first: true, predicate: ["sfSpreadsheet"], descendants: true }, { propertyName: "lookupSource", first: true, predicate: ["lookupSource"], descendants: true }], ngImport: i0, template: "<!--\n Layout root wrapper:\n 1. Toolbar WUIC custom (insert / save batch / export / refresh)\n 2. Syncfusion Spreadsheet host\n 3. Pagination custom (Syncfusion non ha pagination built-in, quindi la\n rendiamo sotto il foglio con nav + page-size dropdown)\n 4. Lookup datasource (invisibile, pattern identico al vecchio componente)\n-->\n\n<!-- Bootstrap CSS Syncfusion (~500 KiB): si monta solo quando questo\n componente lazy \u00E8 istanziato \u2192 CSS NON nel bundle iniziale globale,\n risparmia ~500 KiB su tutte le pagine che non aprono spreadsheet. -->\n<wuic-syncfusion-styles-bootstrap></wuic-syncfusion-styles-bootstrap>\n\n<div class=\"wuic-sf-spreadsheet-wrapper\">\n\n @if (!hideToolbar && metaInfo) {\n <!-- Stile allineato a <wuic-list-grid>: stessa caption-bar, stessi p-button\n PrimeNG con icona + label, stesso componente import/export. -->\n <div class=\"grid-caption-bar wuic-sf-caption-bar\" role=\"toolbar\" aria-label=\"Spreadsheet toolbar\">\n <div class=\"grid-caption-left\">\n @if (!metaInfo.tableMetadata.md_hide_refresh) {\n <p-button icon=\"pi pi-refresh\" label=\"{{'refresh_grid' | translate}}\"\n (onClick)=\"onToolbarRefresh()\" />\n }\n @if (canInsertRows()) {\n <p-button icon=\"pi pi-plus\" label=\"{{'add_grid' | translate}}\"\n (onClick)=\"onToolbarInsert()\" />\n }\n @if (!metaInfo.tableMetadata.md_hide_export_xls) {\n <!-- Include dialog con progress bar + bottoni \"Stoppa e salva\n parziale\" / \"Stoppa\" / \"Continua in background\". -->\n <wuic-import-export-button\n [routeName]=\"metaInfo.tableMetadata.md_route_name\"\n [tableMetadata]=\"metaInfo.tableMetadata\"\n [filterInfoProvider]=\"getCurrentFilterInfoForExport\"></wuic-import-export-button>\n }\n @if (isBatchSaveEnabled()) {\n <p-button icon=\"pi pi-save\" label=\"{{'list_grid.save_changes' | translate}}\"\n (onClick)=\"onToolbarSaveBatch()\" />\n }\n </div>\n </div>\n }\n\n <div class=\"wuic-sf-spreadsheet-host\">\n @if (metaInfo && sfSheets.length > 0) {\n <ejs-spreadsheet #sfSpreadsheet\n [sheets]=\"sfSheets\"\n [height]=\"sfHeight\"\n [width]=\"sfWidth\"\n [scrollSettings]=\"sfScrollSettings\"\n [showRibbon]=\"showRibbon\"\n [showFormulaBar]=\"showFormulaBar\"\n [showSheetTabs]=\"false\"\n [allowEditing]=\"true\"\n [allowSorting]=\"true\"\n [allowFiltering]=\"false\"\n [allowResizing]=\"true\"\n [allowInsert]=\"canInsertRows()\"\n [allowDelete]=\"canDeleteRows()\"\n [enableContextMenu]=\"true\"\n [enableKeyboardNavigation]=\"true\"\n [enableClipboard]=\"true\"\n (created)=\"onSyncfusionCreated()\"\n (dataBound)=\"onSyncfusionDataBound()\"\n (cellSave)=\"onSyncfusionCellSave($event)\"\n (beforeCellSave)=\"onSyncfusionBeforeCellSave($event)\"\n (beforeCellRender)=\"onSyncfusionBeforeCellRender($event)\"\n (cellEdit)=\"onSyncfusionCellEdit($event)\"\n (contextMenuBeforeOpen)=\"onSyncfusionContextMenuBeforeOpen($event)\"\n (contextMenuItemSelect)=\"onSyncfusionContextMenuItemSelect($event)\"\n (actionBegin)=\"onSyncfusionActionBegin($event)\"\n (actionComplete)=\"onSyncfusionActionComplete($event)\"\n (dialogBeforeOpen)=\"onSyncfusionDialogBeforeOpen($event)\">\n </ejs-spreadsheet>\n }\n </div>\n\n @if (totalPages > 1 || totalRecords > pageSize) {\n <div class=\"wuic-sf-pagination\" role=\"navigation\" aria-label=\"Paginazione\">\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(1, pageSize) : setClientPage(1)\"\n title=\"Prima pagina\">\n <i class=\"pi pi-angle-double-left\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex - 1, pageSize) : setClientPage(pageIndex - 1)\"\n title=\"Pagina precedente\">\n <i class=\"pi pi-angle-left\"></i>\n </button>\n <span class=\"wuic-sf-page-info\">\n Pagina <strong>{{ pageIndex }}</strong> di <strong>{{ totalPages }}</strong>\n <span class=\"wuic-sf-page-total\">({{ totalRecords }} record)</span>\n </span>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex + 1, pageSize) : setClientPage(pageIndex + 1)\"\n title=\"Pagina successiva\">\n <i class=\"pi pi-angle-right\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(totalPages, pageSize) : setClientPage(totalPages)\"\n title=\"Ultima pagina\">\n <i class=\"pi pi-angle-double-right\"></i>\n </button>\n <select class=\"wuic-sf-page-size\" [value]=\"pageSize\"\n (change)=\"setPageSize($any($event.target).value)\"\n title=\"Record per pagina\">\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n </select>\n </div>\n }\n\n</div>\n\n@if (!hardcodedRoute) {\n <wuic-data-source #lookupSource [autoload]=\"true\" [routeFromRouting]=\"false\"\n [route]=\"currentRoute\" [parentRecord]=\"currentRecord\"\n [parentMetaInfo]=\"metaInfo\"></wuic-data-source>\n}\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}.wuic-sf-spreadsheet-wrapper{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;overflow:hidden}.wuic-sf-caption-bar{flex:0 0 auto;padding:5px}.grid-caption-left{display:flex;align-items:stretch;gap:.5rem;flex-wrap:nowrap;min-height:2.25rem;height:2.25rem}.wuic-sf-spreadsheet-host{flex:1 1 auto;min-height:0;width:100%;position:relative;overflow:visible}::ng-deep .e-dialog.e-popup-open,::ng-deep .e-excelfilter,::ng-deep .e-filter-popup{z-index:10010!important;min-width:240px}::ng-deep .e-excelfilter .e-footer-content,::ng-deep .e-filter-popup .e-footer-content{display:flex!important;justify-content:flex-end;gap:6px;padding:8px 12px!important}.wuic-sf-spreadsheet-host ejs-spreadsheet{display:block;width:100%;height:100%}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header .e-header-cell-div{font-weight:700!important;text-align:left!important;padding-left:6px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wuic-sf-pagination{display:flex;gap:6px;align-items:center;justify-content:flex-end;padding:6px 10px;background-color:var(--wuic-surface-a, #ffffff);border-top:1px solid var(--wuic-surface-border, #e5e7eb);flex:0 0 auto;font-size:13px}.wuic-sf-page-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;cursor:pointer;color:var(--wuic-text-color, #1f2937);transition:background-color .12s ease,border-color .12s ease}.wuic-sf-page-btn:hover:not(:disabled){background-color:var(--wuic-hover-bg, #f3f4f6);border-color:var(--wuic-primary-color, #6366f1)}.wuic-sf-page-btn:disabled{opacity:.35;cursor:not-allowed}.wuic-sf-page-info{margin:0 8px;white-space:nowrap;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-info strong{color:var(--wuic-text-color, #1f2937)}.wuic-sf-page-total{margin-left:6px;font-size:12px;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-size{margin-left:8px;height:30px;padding:0 8px;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;color:var(--wuic-text-color, #1f2937);cursor:pointer}:host-context(.theme-dark) .wuic-sf-pagination,:host-context([data-theme=\"dark\"]) .wuic-sf-pagination{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn,:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn,:host-context(.theme-dark) .wuic-sf-page-size,:host-context([data-theme=\"dark\"]) .wuic-sf-page-size{color:#f3f4f6;border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn:hover:not(:disabled),:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn:hover:not(:disabled){background-color:#374151}:host-context(.theme-dark) .wuic-sf-page-info,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info{color:#9ca3af}:host-context(.theme-dark) .wuic-sf-page-info strong,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info strong{color:#f3f4f6}:host-context(.theme-dark) .wuic-sf-page-total,:host-context([data-theme=\"dark\"]) .wuic-sf-page-total{color:#9ca3af}:host ::ng-deep .e-spreadsheet{font-family:var(--wuic-font-family, inherit)}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .e-header-cell.wuic-sf-colname-header{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep .e-spreadsheet .e-sheet-content .e-filter-btn{opacity:0!important;pointer-events:none!important;width:0!important;height:0!important;min-width:0!important;padding:0!important;margin:0!important;overflow:hidden!important;position:absolute!important;right:0;top:0}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header{position:relative!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn{position:absolute;right:2px;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;background:transparent;border:none;border-radius:3px;cursor:pointer;color:#475569;flex-shrink:0;transition:background-color .12s,color .12s;z-index:2}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#e2e8f0;color:#1f2937}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg{display:block;pointer-events:none}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet svg,:host ::ng-deep .e-spreadsheet svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#2563eb}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-colname-header .e-header-cell-div{padding-right:22px!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn{color:#cbd5e1}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#334155;color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#60a5fa}:host ::ng-deep .e-spreadsheet .e-sheet-panel{background-color:var(--wuic-surface-a, #ffffff)}:host-context(.theme-dark) ::ng-deep .e-spreadsheet,:host-context([data-theme=\"dark\"]) ::ng-deep .e-spreadsheet,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-sheet-panel,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-main-panel{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-cell{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-row .e-header-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-row-header .e-header-cell{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell.row-danger{background-color:#7f1d1d!important;color:#fecaca!important}:host ::ng-deep .e-cell.row-danger{background-color:#fee2e2!important}:host ::ng-deep .e-cell.row-warning{background-color:#fef3c7!important}:host ::ng-deep .e-cell.row-success{background-color:#d1fae5!important}::ng-deep .wuic-sf-filter-popup{position:fixed;z-index:99999;min-width:260px;max-width:340px;background:#fff;color:#111827;border:1px solid #d1d5db;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:inherit;font-size:13px;display:flex;flex-direction:column;overflow:hidden;-webkit-user-select:none;user-select:none}::ng-deep .wuic-sf-filter-popup-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#f3f4f6;border-bottom:1px solid #e5e7eb;font-weight:600}::ng-deep .wuic-sf-filter-popup-title{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-close{background:transparent;border:none;cursor:pointer;font-size:18px;line-height:1;padding:0 4px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-close:hover{color:#111827}::ng-deep .wuic-sf-filter-popup-sort{display:flex;flex-direction:column;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-sort-btn{background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#111827;display:flex;align-items:center;gap:6px}::ng-deep .wuic-sf-filter-popup-sort-btn:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-sort-icon{font-size:10px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-clear{border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-clear-btn{width:100%;background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#2563eb}::ng-deep .wuic-sf-filter-popup-clear-btn:hover:not(:disabled){background:#eff6ff}::ng-deep .wuic-sf-filter-popup-clear-btn:disabled{color:#9ca3af;cursor:not-allowed}::ng-deep .wuic-sf-filter-popup-search{padding:8px 12px;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-search-input{width:100%;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;font-size:13px;outline:none;box-sizing:border-box}::ng-deep .wuic-sf-filter-popup-search-input:focus{border-color:#2563eb;box-shadow:0 0 0 2px #2563eb33}::ng-deep .wuic-sf-filter-popup-list-wrap{display:flex;flex-direction:column;max-height:260px;overflow:hidden}::ng-deep .wuic-sf-filter-popup-selectall{padding:4px 12px;border-bottom:1px solid #e5e7eb;background:#f9fafb;font-weight:500}::ng-deep .wuic-sf-filter-popup-list{flex:1 1 auto;overflow-y:auto;max-height:220px}::ng-deep .wuic-sf-filter-popup-item{display:flex;align-items:center;gap:6px;padding:4px 12px;cursor:pointer}::ng-deep .wuic-sf-filter-popup-item:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-item input[type=checkbox]{margin:0;flex:0 0 auto}::ng-deep .wuic-sf-filter-popup-item span{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-footer{display:flex;justify-content:flex-end;gap:8px;padding:8px 12px;border-top:1px solid #e5e7eb;background:#f9fafb}::ng-deep .wuic-sf-filter-popup-ok,::ng-deep .wuic-sf-filter-popup-cancel{padding:4px 14px;border:1px solid #d1d5db;border-radius:4px;background:#fff;cursor:pointer;font-size:13px}::ng-deep .wuic-sf-filter-popup-ok{background:#2563eb;color:#fff;border-color:#2563eb}::ng-deep .wuic-sf-filter-popup-ok:hover{background:#1d4ed8}::ng-deep .wuic-sf-filter-popup-cancel:hover{background:#f3f4f6}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active{color:#2563eb}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active svg{fill:#2563eb}::ng-deep .wuic-sf-filter-popup.wuic-sf-filter-popup--dark{background:#1f2937;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-header,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-footer,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-selectall{background:#111827;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-clear,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search{border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{color:#f3f4f6;background:transparent;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-item:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel:hover{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search-input{background:#111827;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close{color:#9ca3af}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close:hover{color:#f3f4f6}::ng-deep .wuic-sf-cell-editor{box-sizing:border-box;padding:2px 6px;border:2px solid #2563eb;background:#fff;color:#111827;font-family:inherit;font-size:13px;outline:none;box-shadow:0 2px 8px #00000026;border-radius:2px}::ng-deep .wuic-sf-cell-editor:focus{border-color:#1d4ed8;box-shadow:0 0 0 2px #2563eb40}::ng-deep select.wuic-sf-cell-editor{cursor:pointer}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark{background:#1f2937;color:#f3f4f6;border-color:#2563eb}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark option{background:#1f2937;color:#f3f4f6}\n"], dependencies: [{ kind: "component", type: DataSourceComponent, selector: "wuic-data-source", inputs: ["route", "routeFromRouting", "hardcodedRoute", "autoload", "loading", "changeTracking", "parentRecord", "parentMetaInfo", "parentDatasource", "useComboEndpoint", "comboFormulaLookup", "comboMcId", "comboField", "comboExtraFields", "comboCurrentRecord", "componentRef"] }, { kind: "ngmodule", type: SpreadsheetModule }, { kind: "component", type: i7.SpreadsheetComponent, selector: "ejs-spreadsheet", inputs: ["activeSheetIndex", "allowAutoFill", "allowCellFormatting", "allowChart", "allowConditionalFormat", "allowDataValidation", "allowDelete", "allowEditing", "allowFiltering", "allowFindAndReplace", "allowFreezePane", "allowHyperlink", "allowImage", "allowInsert", "allowMerge", "allowNumberFormatting", "allowOpen", "allowPrint", "allowResizing", "allowSave", "allowScrolling", "allowSorting", "allowUndoRedo", "allowWrap", "author", "autoFillSettings", "calculationMode", "cellStyle", "cssClass", "currencyCode", "definedNames", "enableClipboard", "enableContextMenu", "enableKeyboardNavigation", "enableKeyboardShortcut", "enableNotes", "enablePersistence", "enableRtl", "height", "isProtected", "listSeparator", "locale", "openSettings", "openUrl", "password", "saveUrl", "scrollSettings", "selectionSettings", "sheets", "showAggregate", "showCommentsPane", "showFormulaBar", "showRibbon", "showSheetTabs", "width"], outputs: ["actionBegin", "actionComplete", "afterHyperlinkClick", "afterHyperlinkCreate", "beforeCellFormat", "beforeCellRender", "beforeCellSave", "beforeCellUpdate", "beforeConditionalFormat", "beforeDataBound", "beforeHyperlinkClick", "beforeHyperlinkCreate", "beforeOpen", "beforeSave", "beforeSelect", "beforeSort", "cellEdit", "cellEdited", "cellEditing", "cellSave", "contextMenuBeforeClose", "contextMenuBeforeOpen", "contextMenuItemSelect", "created", "dataBound", "dataSourceChanged", "dialogBeforeOpen", "fileMenuBeforeClose", "fileMenuBeforeOpen", "fileMenuItemSelect", "openComplete", "openFailure", "queryCellInfo", "saveComplete", "select", "sortComplete"] }, { kind: "component", type: ImportExportButtonComponent, selector: "wuic-import-export-button", inputs: ["routeName", "tableMetadata", "filterInfoProvider"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "component", type: SyncfusionStylesBootstrapComponent, selector: "wuic-syncfusion-styles-bootstrap" }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
|
|
3850
4271
|
}
|
|
3851
4272
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SpreadsheetListSfComponent, decorators: [{
|
|
3852
4273
|
type: Component,
|
|
@@ -3857,7 +4278,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3857
4278
|
ButtonModule,
|
|
3858
4279
|
TranslateModule,
|
|
3859
4280
|
SyncfusionStylesBootstrapComponent
|
|
3860
|
-
], template: "<!--\n Layout root wrapper:\n 1. Toolbar WUIC custom (insert / save batch / export / refresh)\n 2. Syncfusion Spreadsheet host\n 3. Pagination custom (Syncfusion non ha pagination built-in, quindi la\n rendiamo sotto il foglio con nav + page-size dropdown)\n 4. Lookup datasource (invisibile, pattern identico al vecchio componente)\n-->\n\n<!-- Bootstrap CSS Syncfusion (~500 KiB): si monta solo quando questo\n componente lazy \u00E8 istanziato \u2192 CSS NON nel bundle iniziale globale,\n risparmia ~500 KiB su tutte le pagine che non aprono spreadsheet. -->\n<wuic-syncfusion-styles-bootstrap></wuic-syncfusion-styles-bootstrap>\n\n<div class=\"wuic-sf-spreadsheet-wrapper\">\n\n @if (!hideToolbar && metaInfo) {\n <!-- Stile allineato a <wuic-list-grid>: stessa caption-bar, stessi p-button\n PrimeNG con icona + label, stesso componente import/export. -->\n <div class=\"grid-caption-bar wuic-sf-caption-bar\" role=\"toolbar\" aria-label=\"Spreadsheet toolbar\">\n <div class=\"grid-caption-left\">\n @if (!metaInfo.tableMetadata.md_hide_refresh) {\n <p-button icon=\"pi pi-refresh\" label=\"{{'refresh_grid' | translate}}\"\n (onClick)=\"onToolbarRefresh()\" />\n }\n @if (canInsertRows()) {\n <p-button icon=\"pi pi-plus\" label=\"{{'add_grid' | translate}}\"\n (onClick)=\"onToolbarInsert()\" />\n }\n @if (!metaInfo.tableMetadata.md_hide_export_xls) {\n <!-- Include dialog con progress bar + bottoni \"Stoppa e salva\n parziale\" / \"Stoppa\" / \"Continua in background\". -->\n <wuic-import-export-button\n [routeName]=\"metaInfo.tableMetadata.md_route_name\"\n [tableMetadata]=\"metaInfo.tableMetadata\"\n [filterInfoProvider]=\"getCurrentFilterInfoForExport\"></wuic-import-export-button>\n }\n @if (isBatchSaveEnabled()) {\n <p-button icon=\"pi pi-save\" label=\"{{'list_grid.save_changes' | translate}}\"\n (onClick)=\"onToolbarSaveBatch()\" />\n }\n </div>\n </div>\n }\n\n <div class=\"wuic-sf-spreadsheet-host\">\n @if (metaInfo && sfSheets.length > 0) {\n <ejs-spreadsheet #sfSpreadsheet\n [sheets]=\"sfSheets\"\n [height]=\"sfHeight\"\n [width]=\"sfWidth\"\n [scrollSettings]=\"sfScrollSettings\"\n [showRibbon]=\"false\"\n [showFormulaBar]=\"false\"\n [showSheetTabs]=\"false\"\n [allowEditing]=\"true\"\n [allowSorting]=\"true\"\n [allowFiltering]=\"false\"\n [allowResizing]=\"true\"\n [allowInsert]=\"canInsertRows()\"\n [allowDelete]=\"canDeleteRows()\"\n [enableContextMenu]=\"true\"\n [enableKeyboardNavigation]=\"true\"\n [enableClipboard]=\"true\"\n (created)=\"onSyncfusionCreated()\"\n (dataBound)=\"onSyncfusionDataBound()\"\n (cellSave)=\"onSyncfusionCellSave($event)\"\n (beforeCellSave)=\"onSyncfusionBeforeCellSave($event)\"\n (beforeCellRender)=\"onSyncfusionBeforeCellRender($event)\"\n (cellEdit)=\"onSyncfusionCellEdit($event)\"\n (contextMenuBeforeOpen)=\"onSyncfusionContextMenuBeforeOpen($event)\"\n (contextMenuItemSelect)=\"onSyncfusionContextMenuItemSelect($event)\"\n (actionBegin)=\"onSyncfusionActionBegin($event)\"\n (actionComplete)=\"onSyncfusionActionComplete($event)\"\n (dialogBeforeOpen)=\"onSyncfusionDialogBeforeOpen($event)\">\n </ejs-spreadsheet>\n }\n </div>\n\n @if (totalPages > 1 || totalRecords > pageSize) {\n <div class=\"wuic-sf-pagination\" role=\"navigation\" aria-label=\"Paginazione\">\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(1, pageSize) : setClientPage(1)\"\n title=\"Prima pagina\">\n <i class=\"pi pi-angle-double-left\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex - 1, pageSize) : setClientPage(pageIndex - 1)\"\n title=\"Pagina precedente\">\n <i class=\"pi pi-angle-left\"></i>\n </button>\n <span class=\"wuic-sf-page-info\">\n Pagina <strong>{{ pageIndex }}</strong> di <strong>{{ totalPages }}</strong>\n <span class=\"wuic-sf-page-total\">({{ totalRecords }} record)</span>\n </span>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex + 1, pageSize) : setClientPage(pageIndex + 1)\"\n title=\"Pagina successiva\">\n <i class=\"pi pi-angle-right\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(totalPages, pageSize) : setClientPage(totalPages)\"\n title=\"Ultima pagina\">\n <i class=\"pi pi-angle-double-right\"></i>\n </button>\n <select class=\"wuic-sf-page-size\" [value]=\"pageSize\"\n (change)=\"setPageSize($any($event.target).value)\"\n title=\"Record per pagina\">\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n </select>\n </div>\n }\n\n</div>\n\n@if (!hardcodedRoute) {\n <wuic-data-source #lookupSource [autoload]=\"true\" [routeFromRouting]=\"false\"\n [route]=\"currentRoute\" [parentRecord]=\"currentRecord\"\n [parentMetaInfo]=\"metaInfo\"></wuic-data-source>\n}\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}.wuic-sf-spreadsheet-wrapper{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;overflow:hidden}.wuic-sf-caption-bar{flex:0 0 auto;padding:5px}.grid-caption-left{display:flex;align-items:stretch;gap:.5rem;flex-wrap:nowrap;min-height:2.25rem;height:2.25rem}.wuic-sf-spreadsheet-host{flex:1 1 auto;min-height:0;width:100%;position:relative;overflow:visible}::ng-deep .e-dialog.e-popup-open,::ng-deep .e-excelfilter,::ng-deep .e-filter-popup{z-index:10010!important;min-width:240px}::ng-deep .e-excelfilter .e-footer-content,::ng-deep .e-filter-popup .e-footer-content{display:flex!important;justify-content:flex-end;gap:6px;padding:8px 12px!important}.wuic-sf-spreadsheet-host ejs-spreadsheet{display:block;width:100%;height:100%}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header .e-header-cell-div{font-weight:700!important;text-align:left!important;padding-left:6px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wuic-sf-pagination{display:flex;gap:6px;align-items:center;justify-content:flex-end;padding:6px 10px;background-color:var(--wuic-surface-a, #ffffff);border-top:1px solid var(--wuic-surface-border, #e5e7eb);flex:0 0 auto;font-size:13px}.wuic-sf-page-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;cursor:pointer;color:var(--wuic-text-color, #1f2937);transition:background-color .12s ease,border-color .12s ease}.wuic-sf-page-btn:hover:not(:disabled){background-color:var(--wuic-hover-bg, #f3f4f6);border-color:var(--wuic-primary-color, #6366f1)}.wuic-sf-page-btn:disabled{opacity:.35;cursor:not-allowed}.wuic-sf-page-info{margin:0 8px;white-space:nowrap;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-info strong{color:var(--wuic-text-color, #1f2937)}.wuic-sf-page-total{margin-left:6px;font-size:12px;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-size{margin-left:8px;height:30px;padding:0 8px;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;color:var(--wuic-text-color, #1f2937);cursor:pointer}:host-context(.theme-dark) .wuic-sf-pagination,:host-context([data-theme=\"dark\"]) .wuic-sf-pagination{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn,:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn,:host-context(.theme-dark) .wuic-sf-page-size,:host-context([data-theme=\"dark\"]) .wuic-sf-page-size{color:#f3f4f6;border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn:hover:not(:disabled),:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn:hover:not(:disabled){background-color:#374151}:host-context(.theme-dark) .wuic-sf-page-info,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info{color:#9ca3af}:host-context(.theme-dark) .wuic-sf-page-info strong,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info strong{color:#f3f4f6}:host-context(.theme-dark) .wuic-sf-page-total,:host-context([data-theme=\"dark\"]) .wuic-sf-page-total{color:#9ca3af}:host ::ng-deep .e-spreadsheet{font-family:var(--wuic-font-family, inherit)}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .e-header-cell.wuic-sf-colname-header{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep .e-spreadsheet .e-sheet-content .e-filter-btn{opacity:0!important;pointer-events:none!important;width:0!important;height:0!important;min-width:0!important;padding:0!important;margin:0!important;overflow:hidden!important;position:absolute!important;right:0;top:0}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header{position:relative!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn{position:absolute;right:2px;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;background:transparent;border:none;border-radius:3px;cursor:pointer;color:#475569;flex-shrink:0;transition:background-color .12s,color .12s;z-index:2}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#e2e8f0;color:#1f2937}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg{display:block;pointer-events:none}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet svg,:host ::ng-deep .e-spreadsheet svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#2563eb}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-colname-header .e-header-cell-div{padding-right:22px!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn{color:#cbd5e1}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#334155;color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#60a5fa}:host ::ng-deep .e-spreadsheet .e-sheet-panel{background-color:var(--wuic-surface-a, #ffffff)}:host-context(.theme-dark) ::ng-deep .e-spreadsheet,:host-context([data-theme=\"dark\"]) ::ng-deep .e-spreadsheet,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-sheet-panel,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-main-panel{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-cell{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-row .e-header-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-row-header .e-header-cell{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell.row-danger{background-color:#7f1d1d!important;color:#fecaca!important}:host ::ng-deep .e-cell.row-danger{background-color:#fee2e2!important}:host ::ng-deep .e-cell.row-warning{background-color:#fef3c7!important}:host ::ng-deep .e-cell.row-success{background-color:#d1fae5!important}::ng-deep .wuic-sf-filter-popup{position:fixed;z-index:99999;min-width:260px;max-width:340px;background:#fff;color:#111827;border:1px solid #d1d5db;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:inherit;font-size:13px;display:flex;flex-direction:column;overflow:hidden;-webkit-user-select:none;user-select:none}::ng-deep .wuic-sf-filter-popup-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#f3f4f6;border-bottom:1px solid #e5e7eb;font-weight:600}::ng-deep .wuic-sf-filter-popup-title{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-close{background:transparent;border:none;cursor:pointer;font-size:18px;line-height:1;padding:0 4px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-close:hover{color:#111827}::ng-deep .wuic-sf-filter-popup-sort{display:flex;flex-direction:column;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-sort-btn{background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#111827;display:flex;align-items:center;gap:6px}::ng-deep .wuic-sf-filter-popup-sort-btn:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-sort-icon{font-size:10px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-clear{border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-clear-btn{width:100%;background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#2563eb}::ng-deep .wuic-sf-filter-popup-clear-btn:hover:not(:disabled){background:#eff6ff}::ng-deep .wuic-sf-filter-popup-clear-btn:disabled{color:#9ca3af;cursor:not-allowed}::ng-deep .wuic-sf-filter-popup-search{padding:8px 12px;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-search-input{width:100%;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;font-size:13px;outline:none;box-sizing:border-box}::ng-deep .wuic-sf-filter-popup-search-input:focus{border-color:#2563eb;box-shadow:0 0 0 2px #2563eb33}::ng-deep .wuic-sf-filter-popup-list-wrap{display:flex;flex-direction:column;max-height:260px;overflow:hidden}::ng-deep .wuic-sf-filter-popup-selectall{padding:4px 12px;border-bottom:1px solid #e5e7eb;background:#f9fafb;font-weight:500}::ng-deep .wuic-sf-filter-popup-list{flex:1 1 auto;overflow-y:auto;max-height:220px}::ng-deep .wuic-sf-filter-popup-item{display:flex;align-items:center;gap:6px;padding:4px 12px;cursor:pointer}::ng-deep .wuic-sf-filter-popup-item:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-item input[type=checkbox]{margin:0;flex:0 0 auto}::ng-deep .wuic-sf-filter-popup-item span{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-footer{display:flex;justify-content:flex-end;gap:8px;padding:8px 12px;border-top:1px solid #e5e7eb;background:#f9fafb}::ng-deep .wuic-sf-filter-popup-ok,::ng-deep .wuic-sf-filter-popup-cancel{padding:4px 14px;border:1px solid #d1d5db;border-radius:4px;background:#fff;cursor:pointer;font-size:13px}::ng-deep .wuic-sf-filter-popup-ok{background:#2563eb;color:#fff;border-color:#2563eb}::ng-deep .wuic-sf-filter-popup-ok:hover{background:#1d4ed8}::ng-deep .wuic-sf-filter-popup-cancel:hover{background:#f3f4f6}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active{color:#2563eb}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active svg{fill:#2563eb}::ng-deep .wuic-sf-filter-popup.wuic-sf-filter-popup--dark{background:#1f2937;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-header,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-footer,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-selectall{background:#111827;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-clear,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search{border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{color:#f3f4f6;background:transparent;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-item:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel:hover{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search-input{background:#111827;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close{color:#9ca3af}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close:hover{color:#f3f4f6}::ng-deep .wuic-sf-cell-editor{box-sizing:border-box;padding:2px 6px;border:2px solid #2563eb;background:#fff;color:#111827;font-family:inherit;font-size:13px;outline:none;box-shadow:0 2px 8px #00000026;border-radius:2px}::ng-deep .wuic-sf-cell-editor:focus{border-color:#1d4ed8;box-shadow:0 0 0 2px #2563eb40}::ng-deep select.wuic-sf-cell-editor{cursor:pointer}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark{background:#1f2937;color:#f3f4f6;border-color:#2563eb}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark option{background:#1f2937;color:#f3f4f6}\n"] }]
|
|
4281
|
+
], template: "<!--\n Layout root wrapper:\n 1. Toolbar WUIC custom (insert / save batch / export / refresh)\n 2. Syncfusion Spreadsheet host\n 3. Pagination custom (Syncfusion non ha pagination built-in, quindi la\n rendiamo sotto il foglio con nav + page-size dropdown)\n 4. Lookup datasource (invisibile, pattern identico al vecchio componente)\n-->\n\n<!-- Bootstrap CSS Syncfusion (~500 KiB): si monta solo quando questo\n componente lazy \u00E8 istanziato \u2192 CSS NON nel bundle iniziale globale,\n risparmia ~500 KiB su tutte le pagine che non aprono spreadsheet. -->\n<wuic-syncfusion-styles-bootstrap></wuic-syncfusion-styles-bootstrap>\n\n<div class=\"wuic-sf-spreadsheet-wrapper\">\n\n @if (!hideToolbar && metaInfo) {\n <!-- Stile allineato a <wuic-list-grid>: stessa caption-bar, stessi p-button\n PrimeNG con icona + label, stesso componente import/export. -->\n <div class=\"grid-caption-bar wuic-sf-caption-bar\" role=\"toolbar\" aria-label=\"Spreadsheet toolbar\">\n <div class=\"grid-caption-left\">\n @if (!metaInfo.tableMetadata.md_hide_refresh) {\n <p-button icon=\"pi pi-refresh\" label=\"{{'refresh_grid' | translate}}\"\n (onClick)=\"onToolbarRefresh()\" />\n }\n @if (canInsertRows()) {\n <p-button icon=\"pi pi-plus\" label=\"{{'add_grid' | translate}}\"\n (onClick)=\"onToolbarInsert()\" />\n }\n @if (!metaInfo.tableMetadata.md_hide_export_xls) {\n <!-- Include dialog con progress bar + bottoni \"Stoppa e salva\n parziale\" / \"Stoppa\" / \"Continua in background\". -->\n <wuic-import-export-button\n [routeName]=\"metaInfo.tableMetadata.md_route_name\"\n [tableMetadata]=\"metaInfo.tableMetadata\"\n [filterInfoProvider]=\"getCurrentFilterInfoForExport\"></wuic-import-export-button>\n }\n @if (isBatchSaveEnabled()) {\n <p-button icon=\"pi pi-save\" label=\"{{'list_grid.save_changes' | translate}}\"\n (onClick)=\"onToolbarSaveBatch()\" />\n }\n </div>\n </div>\n }\n\n <div class=\"wuic-sf-spreadsheet-host\">\n @if (metaInfo && sfSheets.length > 0) {\n <ejs-spreadsheet #sfSpreadsheet\n [sheets]=\"sfSheets\"\n [height]=\"sfHeight\"\n [width]=\"sfWidth\"\n [scrollSettings]=\"sfScrollSettings\"\n [showRibbon]=\"showRibbon\"\n [showFormulaBar]=\"showFormulaBar\"\n [showSheetTabs]=\"false\"\n [allowEditing]=\"true\"\n [allowSorting]=\"true\"\n [allowFiltering]=\"false\"\n [allowResizing]=\"true\"\n [allowInsert]=\"canInsertRows()\"\n [allowDelete]=\"canDeleteRows()\"\n [enableContextMenu]=\"true\"\n [enableKeyboardNavigation]=\"true\"\n [enableClipboard]=\"true\"\n (created)=\"onSyncfusionCreated()\"\n (dataBound)=\"onSyncfusionDataBound()\"\n (cellSave)=\"onSyncfusionCellSave($event)\"\n (beforeCellSave)=\"onSyncfusionBeforeCellSave($event)\"\n (beforeCellRender)=\"onSyncfusionBeforeCellRender($event)\"\n (cellEdit)=\"onSyncfusionCellEdit($event)\"\n (contextMenuBeforeOpen)=\"onSyncfusionContextMenuBeforeOpen($event)\"\n (contextMenuItemSelect)=\"onSyncfusionContextMenuItemSelect($event)\"\n (actionBegin)=\"onSyncfusionActionBegin($event)\"\n (actionComplete)=\"onSyncfusionActionComplete($event)\"\n (dialogBeforeOpen)=\"onSyncfusionDialogBeforeOpen($event)\">\n </ejs-spreadsheet>\n }\n </div>\n\n @if (totalPages > 1 || totalRecords > pageSize) {\n <div class=\"wuic-sf-pagination\" role=\"navigation\" aria-label=\"Paginazione\">\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(1, pageSize) : setClientPage(1)\"\n title=\"Prima pagina\">\n <i class=\"pi pi-angle-double-left\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex <= 1\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex - 1, pageSize) : setClientPage(pageIndex - 1)\"\n title=\"Pagina precedente\">\n <i class=\"pi pi-angle-left\"></i>\n </button>\n <span class=\"wuic-sf-page-info\">\n Pagina <strong>{{ pageIndex }}</strong> di <strong>{{ totalPages }}</strong>\n <span class=\"wuic-sf-page-total\">({{ totalRecords }} record)</span>\n </span>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(pageIndex + 1, pageSize) : setClientPage(pageIndex + 1)\"\n title=\"Pagina successiva\">\n <i class=\"pi pi-angle-right\"></i>\n </button>\n <button type=\"button\" class=\"wuic-sf-page-btn\"\n [disabled]=\"pageIndex >= totalPages\"\n (click)=\"isServerSide ? handleServerPageChange(totalPages, pageSize) : setClientPage(totalPages)\"\n title=\"Ultima pagina\">\n <i class=\"pi pi-angle-double-right\"></i>\n </button>\n <select class=\"wuic-sf-page-size\" [value]=\"pageSize\"\n (change)=\"setPageSize($any($event.target).value)\"\n title=\"Record per pagina\">\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n </select>\n </div>\n }\n\n</div>\n\n@if (!hardcodedRoute) {\n <wuic-data-source #lookupSource [autoload]=\"true\" [routeFromRouting]=\"false\"\n [route]=\"currentRoute\" [parentRecord]=\"currentRecord\"\n [parentMetaInfo]=\"metaInfo\"></wuic-data-source>\n}\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}.wuic-sf-spreadsheet-wrapper{display:flex;flex-direction:column;width:100%;height:100%;min-height:0;overflow:hidden}.wuic-sf-caption-bar{flex:0 0 auto;padding:5px}.grid-caption-left{display:flex;align-items:stretch;gap:.5rem;flex-wrap:nowrap;min-height:2.25rem;height:2.25rem}.wuic-sf-spreadsheet-host{flex:1 1 auto;min-height:0;width:100%;position:relative;overflow:visible}::ng-deep .e-dialog.e-popup-open,::ng-deep .e-excelfilter,::ng-deep .e-filter-popup{z-index:10010!important;min-width:240px}::ng-deep .e-excelfilter .e-footer-content,::ng-deep .e-filter-popup .e-footer-content{display:flex!important;justify-content:flex-end;gap:6px;padding:8px 12px!important}.wuic-sf-spreadsheet-host ejs-spreadsheet{display:block;width:100%;height:100%}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header .e-header-cell-div{font-weight:700!important;text-align:left!important;padding-left:6px!important;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.wuic-sf-pagination{display:flex;gap:6px;align-items:center;justify-content:flex-end;padding:6px 10px;background-color:var(--wuic-surface-a, #ffffff);border-top:1px solid var(--wuic-surface-border, #e5e7eb);flex:0 0 auto;font-size:13px}.wuic-sf-page-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;cursor:pointer;color:var(--wuic-text-color, #1f2937);transition:background-color .12s ease,border-color .12s ease}.wuic-sf-page-btn:hover:not(:disabled){background-color:var(--wuic-hover-bg, #f3f4f6);border-color:var(--wuic-primary-color, #6366f1)}.wuic-sf-page-btn:disabled{opacity:.35;cursor:not-allowed}.wuic-sf-page-info{margin:0 8px;white-space:nowrap;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-info strong{color:var(--wuic-text-color, #1f2937)}.wuic-sf-page-total{margin-left:6px;font-size:12px;color:var(--wuic-text-muted, #6b7280)}.wuic-sf-page-size{margin-left:8px;height:30px;padding:0 8px;border:1px solid var(--wuic-surface-border, #e5e7eb);border-radius:4px;background:transparent;color:var(--wuic-text-color, #1f2937);cursor:pointer}:host-context(.theme-dark) .wuic-sf-pagination,:host-context([data-theme=\"dark\"]) .wuic-sf-pagination{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn,:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn,:host-context(.theme-dark) .wuic-sf-page-size,:host-context([data-theme=\"dark\"]) .wuic-sf-page-size{color:#f3f4f6;border-color:var(--wuic-surface-border-dark, #374151)}:host-context(.theme-dark) .wuic-sf-page-btn:hover:not(:disabled),:host-context([data-theme=\"dark\"]) .wuic-sf-page-btn:hover:not(:disabled){background-color:#374151}:host-context(.theme-dark) .wuic-sf-page-info,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info{color:#9ca3af}:host-context(.theme-dark) .wuic-sf-page-info strong,:host-context([data-theme=\"dark\"]) .wuic-sf-page-info strong{color:#f3f4f6}:host-context(.theme-dark) .wuic-sf-page-total,:host-context([data-theme=\"dark\"]) .wuic-sf-page-total{color:#9ca3af}:host ::ng-deep .e-spreadsheet{font-family:var(--wuic-font-family, inherit)}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .e-header-cell.wuic-sf-colname-header{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep .e-spreadsheet .e-sheet-content .e-filter-btn{opacity:0!important;pointer-events:none!important;width:0!important;height:0!important;min-width:0!important;padding:0!important;margin:0!important;overflow:hidden!important;position:absolute!important;right:0;top:0}:host ::ng-deep .e-spreadsheet .e-column-header .e-header-cell.wuic-sf-colname-header{position:relative!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn{position:absolute;right:2px;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;padding:0;background:transparent;border:none;border-radius:3px;cursor:pointer;color:#475569;flex-shrink:0;transition:background-color .12s,color .12s;z-index:2}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#e2e8f0;color:#1f2937}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg{display:block;pointer-events:none}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet svg,:host ::ng-deep .e-spreadsheet svg *{pointer-events:none!important}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#2563eb}:host ::ng-deep .e-spreadsheet .e-column-header .wuic-sf-colname-header .e-header-cell-div{padding-right:22px!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn{color:#cbd5e1}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn:hover{background-color:#334155;color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-column-header .wuic-sf-header-filter-btn.wuic-filtered{color:#60a5fa}:host ::ng-deep .e-spreadsheet .e-sheet-panel{background-color:var(--wuic-surface-a, #ffffff)}:host-context(.theme-dark) ::ng-deep .e-spreadsheet,:host-context([data-theme=\"dark\"]) ::ng-deep .e-spreadsheet,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-sheet-panel,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-main-panel{background-color:var(--wuic-surface-a-dark, #1f2937);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-cell{background-color:var(--wuic-surface-a-dark, #1f2937);border-color:var(--wuic-surface-border-dark, #374151);color:#f3f4f6}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-header-row .e-header-cell,:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-row-header .e-header-cell{background-color:#111827!important;color:#e5e7eb!important}:host ::ng-deep ejs-spreadsheet.wuic-sf-dark .e-cell.row-danger{background-color:#7f1d1d!important;color:#fecaca!important}:host ::ng-deep .e-cell.row-danger{background-color:#fee2e2!important}:host ::ng-deep .e-cell.row-warning{background-color:#fef3c7!important}:host ::ng-deep .e-cell.row-success{background-color:#d1fae5!important}::ng-deep .wuic-sf-filter-popup{position:fixed;z-index:99999;min-width:260px;max-width:340px;background:#fff;color:#111827;border:1px solid #d1d5db;border-radius:6px;box-shadow:0 8px 24px #0000002e;font-family:inherit;font-size:13px;display:flex;flex-direction:column;overflow:hidden;-webkit-user-select:none;user-select:none}::ng-deep .wuic-sf-filter-popup-header{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:#f3f4f6;border-bottom:1px solid #e5e7eb;font-weight:600}::ng-deep .wuic-sf-filter-popup-title{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-close{background:transparent;border:none;cursor:pointer;font-size:18px;line-height:1;padding:0 4px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-close:hover{color:#111827}::ng-deep .wuic-sf-filter-popup-sort{display:flex;flex-direction:column;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-sort-btn{background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#111827;display:flex;align-items:center;gap:6px}::ng-deep .wuic-sf-filter-popup-sort-btn:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-sort-icon{font-size:10px;color:#6b7280}::ng-deep .wuic-sf-filter-popup-clear{border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-clear-btn{width:100%;background:transparent;border:none;text-align:left;padding:6px 12px;cursor:pointer;font-size:13px;color:#2563eb}::ng-deep .wuic-sf-filter-popup-clear-btn:hover:not(:disabled){background:#eff6ff}::ng-deep .wuic-sf-filter-popup-clear-btn:disabled{color:#9ca3af;cursor:not-allowed}::ng-deep .wuic-sf-filter-popup-search{padding:8px 12px;border-bottom:1px solid #e5e7eb}::ng-deep .wuic-sf-filter-popup-search-input{width:100%;padding:4px 8px;border:1px solid #d1d5db;border-radius:4px;font-size:13px;outline:none;box-sizing:border-box}::ng-deep .wuic-sf-filter-popup-search-input:focus{border-color:#2563eb;box-shadow:0 0 0 2px #2563eb33}::ng-deep .wuic-sf-filter-popup-list-wrap{display:flex;flex-direction:column;max-height:260px;overflow:hidden}::ng-deep .wuic-sf-filter-popup-selectall{padding:4px 12px;border-bottom:1px solid #e5e7eb;background:#f9fafb;font-weight:500}::ng-deep .wuic-sf-filter-popup-list{flex:1 1 auto;overflow-y:auto;max-height:220px}::ng-deep .wuic-sf-filter-popup-item{display:flex;align-items:center;gap:6px;padding:4px 12px;cursor:pointer}::ng-deep .wuic-sf-filter-popup-item:hover{background:#f3f4f6}::ng-deep .wuic-sf-filter-popup-item input[type=checkbox]{margin:0;flex:0 0 auto}::ng-deep .wuic-sf-filter-popup-item span{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::ng-deep .wuic-sf-filter-popup-footer{display:flex;justify-content:flex-end;gap:8px;padding:8px 12px;border-top:1px solid #e5e7eb;background:#f9fafb}::ng-deep .wuic-sf-filter-popup-ok,::ng-deep .wuic-sf-filter-popup-cancel{padding:4px 14px;border:1px solid #d1d5db;border-radius:4px;background:#fff;cursor:pointer;font-size:13px}::ng-deep .wuic-sf-filter-popup-ok{background:#2563eb;color:#fff;border-color:#2563eb}::ng-deep .wuic-sf-filter-popup-ok:hover{background:#1d4ed8}::ng-deep .wuic-sf-filter-popup-cancel:hover{background:#f3f4f6}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active{color:#2563eb}:host ::ng-deep .wuic-sf-header-filter-btn.wuic-sf-header-filter-btn--active svg{fill:#2563eb}::ng-deep .wuic-sf-filter-popup.wuic-sf-filter-popup--dark{background:#1f2937;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-header,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-footer,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-selectall{background:#111827;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-clear,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search{border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{color:#f3f4f6;background:transparent;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-sort-btn:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-item:hover,::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-cancel:hover{background:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-search-input{background:#111827;color:#f3f4f6;border-color:#374151}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close{color:#9ca3af}::ng-deep .wuic-sf-filter-popup--dark .wuic-sf-filter-popup-close:hover{color:#f3f4f6}::ng-deep .wuic-sf-cell-editor{box-sizing:border-box;padding:2px 6px;border:2px solid #2563eb;background:#fff;color:#111827;font-family:inherit;font-size:13px;outline:none;box-shadow:0 2px 8px #00000026;border-radius:2px}::ng-deep .wuic-sf-cell-editor:focus{border-color:#1d4ed8;box-shadow:0 0 0 2px #2563eb40}::ng-deep select.wuic-sf-cell-editor{cursor:pointer}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark{background:#1f2937;color:#f3f4f6;border-color:#2563eb}::ng-deep .wuic-sf-cell-editor.wuic-sf-cell-editor--dark option{background:#1f2937;color:#f3f4f6}\n"] }]
|
|
3861
4282
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.Title }, { type: i1$1.ActivatedRoute }, { type: i1$2.HttpClient }, { type: WtoolboxService }, { type: MetadataProviderService }, { type: UserInfoService }], propDecorators: { sfSpreadsheet: [{
|
|
3862
4283
|
type: ViewChild,
|
|
3863
4284
|
args: ['sfSpreadsheet']
|
|
@@ -3876,6 +4297,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3876
4297
|
type: Input
|
|
3877
4298
|
}], hideToolbar: [{
|
|
3878
4299
|
type: Input
|
|
4300
|
+
}], enableLockAwareness: [{
|
|
4301
|
+
type: Input
|
|
4302
|
+
}], lockScope: [{
|
|
4303
|
+
type: Input
|
|
4304
|
+
}], heartbeatIntervalSec: [{
|
|
4305
|
+
type: Input
|
|
4306
|
+
}], showFormulaBar: [{
|
|
4307
|
+
type: Input
|
|
4308
|
+
}], showRibbon: [{
|
|
4309
|
+
type: Input
|
|
3879
4310
|
}], onSpreadsheetDataBound: [{
|
|
3880
4311
|
type: Output
|
|
3881
4312
|
}], onSpreadsheetBeforePageChange: [{
|
|
@@ -3888,10 +4319,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
3888
4319
|
type: Output
|
|
3889
4320
|
}], onSpreadsheetBatchSaved: [{
|
|
3890
4321
|
type: Output
|
|
4322
|
+
}], onLockAcquired: [{
|
|
4323
|
+
type: Output
|
|
4324
|
+
}], onLockConflict: [{
|
|
4325
|
+
type: Output
|
|
4326
|
+
}], onLockReleased: [{
|
|
4327
|
+
type: Output
|
|
4328
|
+
}], onLockExpired: [{
|
|
4329
|
+
type: Output
|
|
3891
4330
|
}], onWindowResize: [{
|
|
3892
4331
|
type: HostListener,
|
|
3893
4332
|
args: ['window:resize']
|
|
3894
4333
|
}] } });
|
|
3895
4334
|
|
|
3896
4335
|
export { SpreadsheetListSfComponent };
|
|
3897
|
-
//# sourceMappingURL=wuic-framework-lib-spreadsheet-list-sf.component-
|
|
4336
|
+
//# sourceMappingURL=wuic-framework-lib-spreadsheet-list-sf.component-C9sWgq61.mjs.map
|