@fuentis/phoenix-ui 0.0.9-alpha.367 → 0.0.9-alpha.369
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.
|
@@ -2567,8 +2567,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
2567
2567
|
}] });
|
|
2568
2568
|
|
|
2569
2569
|
/**
|
|
2570
|
-
*
|
|
2571
|
-
* This controls where buttons will appear (toolbar, row menu, etc.).
|
|
2570
|
+
* Split actions by context (controls placement in toolbar/rows).
|
|
2572
2571
|
*/
|
|
2573
2572
|
function resolveActions(value) {
|
|
2574
2573
|
const transformed = {
|
|
@@ -2602,7 +2601,7 @@ function resolveActions(value) {
|
|
|
2602
2601
|
}
|
|
2603
2602
|
/* ----------------------------- Helpers ----------------------------- */
|
|
2604
2603
|
/**
|
|
2605
|
-
*
|
|
2604
|
+
* Safe nested property access via dot notation.
|
|
2606
2605
|
* Example: "user.address.city" → row.user.address.city
|
|
2607
2606
|
*/
|
|
2608
2607
|
function getNestedValue(obj, path) {
|
|
@@ -2627,10 +2626,10 @@ function getNestedValue(obj, path) {
|
|
|
2627
2626
|
}
|
|
2628
2627
|
}
|
|
2629
2628
|
/**
|
|
2630
|
-
*
|
|
2631
|
-
* -
|
|
2632
|
-
* -
|
|
2633
|
-
* -
|
|
2629
|
+
* Normalize text for export:
|
|
2630
|
+
* - Strip HTML
|
|
2631
|
+
* - Replace NBSPs
|
|
2632
|
+
* - Normalize Unicode (keeps diacritics/umlauts)
|
|
2634
2633
|
*/
|
|
2635
2634
|
function sanitizeText(v) {
|
|
2636
2635
|
const s = (v ?? '').toString();
|
|
@@ -2642,14 +2641,14 @@ function sanitizeText(v) {
|
|
|
2642
2641
|
.trim();
|
|
2643
2642
|
}
|
|
2644
2643
|
/**
|
|
2645
|
-
*
|
|
2644
|
+
* Quote CSV values when needed (delimiter, quotes, newlines).
|
|
2646
2645
|
*/
|
|
2647
2646
|
function needsQuotesCSV(value, delimiter) {
|
|
2648
2647
|
const pattern = new RegExp(`[\"\\n${delimiter === ',' ? ',' : ';'}]`);
|
|
2649
2648
|
return pattern.test(value);
|
|
2650
2649
|
}
|
|
2651
2650
|
/**
|
|
2652
|
-
*
|
|
2651
|
+
* Locale-aware date formatting using Angular DatePipe.
|
|
2653
2652
|
*/
|
|
2654
2653
|
function formatDateValue(val, pattern, locale) {
|
|
2655
2654
|
try {
|
|
@@ -2664,10 +2663,10 @@ function formatDateValue(val, pattern, locale) {
|
|
|
2664
2663
|
}
|
|
2665
2664
|
/* ------------------------- Display resolver ------------------------ */
|
|
2666
2665
|
/**
|
|
2667
|
-
*
|
|
2668
|
-
*
|
|
2666
|
+
* Convert raw row values into exportable strings.
|
|
2667
|
+
* Supports DATE/LIST/BOOLEAN/etc. and CSV/PDF specific rendering.
|
|
2669
2668
|
*/
|
|
2670
|
-
function getDisplayValue(row, col, columnTypeMap, columnTypeEnum, t, locale = 'en-US') {
|
|
2669
|
+
function getDisplayValue(row, col, columnTypeMap, columnTypeEnum, t, locale = 'en-US', forCsv = false, forPdf = false) {
|
|
2671
2670
|
const field = col.field;
|
|
2672
2671
|
const type = columnTypeMap[field] || col.columnType;
|
|
2673
2672
|
const val = getNestedValue(row, field);
|
|
@@ -2680,15 +2679,20 @@ function getDisplayValue(row, col, columnTypeMap, columnTypeEnum, t, locale = 'e
|
|
|
2680
2679
|
return formatDateValue(val, 'dd.MM.yyyy', locale);
|
|
2681
2680
|
case columnTypeEnum.TAG:
|
|
2682
2681
|
return (val?.name ?? val)?.toString();
|
|
2683
|
-
case columnTypeEnum.LIST_TAG:
|
|
2684
2682
|
case columnTypeEnum.LIST:
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2683
|
+
case columnTypeEnum.LIST_TAG: {
|
|
2684
|
+
if (!Array.isArray(val))
|
|
2685
|
+
return String(val);
|
|
2686
|
+
const items = val.map((x) => (x?.name ?? x));
|
|
2687
|
+
if (forCsv)
|
|
2688
|
+
return items.join('\n'); // multi-line cell in CSV
|
|
2689
|
+
if (forPdf)
|
|
2690
|
+
return '• ' + items.join('\n• '); // bullet list in PDF
|
|
2691
|
+
return items.join(', '); // UI default
|
|
2692
|
+
}
|
|
2688
2693
|
case columnTypeEnum.OBJ_TAG:
|
|
2689
2694
|
return (val?.value ?? val)?.toString();
|
|
2690
2695
|
case columnTypeEnum.BOOLEAN: {
|
|
2691
|
-
// Translate YES/NO if translation function is provided
|
|
2692
2696
|
const yes = t ? t('ACTION.YES') : 'Yes';
|
|
2693
2697
|
const no = t ? t('ACTION.NO') : 'No';
|
|
2694
2698
|
return (val === true || val === 'true') ? yes : no;
|
|
@@ -2704,40 +2708,64 @@ function getDisplayValue(row, col, columnTypeMap, columnTypeEnum, t, locale = 'e
|
|
|
2704
2708
|
return String(val);
|
|
2705
2709
|
}
|
|
2706
2710
|
}
|
|
2707
|
-
|
|
2711
|
+
/**
|
|
2712
|
+
* Clean multi-line content for CSV while preserving line breaks:
|
|
2713
|
+
* - Normalize all separators to '\n'
|
|
2714
|
+
* - Remove leading/trailing blank lines and indentation
|
|
2715
|
+
* - Collapse multiple blank lines
|
|
2716
|
+
*/
|
|
2717
|
+
function cleanMultilineForCsv(s) {
|
|
2718
|
+
if (!s)
|
|
2719
|
+
return '';
|
|
2708
2720
|
return s
|
|
2709
|
-
.replace(
|
|
2710
|
-
.replace(
|
|
2711
|
-
.replace(/
|
|
2721
|
+
.replace(/\u2028|\u2029|\r\n|\r/g, '\n')
|
|
2722
|
+
.replace(/^[\s\u00A0]+/g, '')
|
|
2723
|
+
.replace(/[\s\u00A0]+$/g, '')
|
|
2724
|
+
.replace(/^(?:\s*\n)+/g, '')
|
|
2725
|
+
.replace(/(?:\n\s*)+$/g, '')
|
|
2726
|
+
.split('\n')
|
|
2727
|
+
.map(line => line.replace(/^[\s\u00A0]+/, ''))
|
|
2728
|
+
.join('\n')
|
|
2729
|
+
.replace(/(\n\s*){2,}/g, '\n');
|
|
2712
2730
|
}
|
|
2713
2731
|
/**
|
|
2714
|
-
*
|
|
2715
|
-
* - Uses
|
|
2716
|
-
* -
|
|
2717
|
-
* -
|
|
2732
|
+
* Export rows to PDF (jsPDF + autoTable).
|
|
2733
|
+
* - Uses visible columns only
|
|
2734
|
+
* - Translates headers via provided translator
|
|
2735
|
+
* - Wraps the “Scope” column content for long lists
|
|
2718
2736
|
*/
|
|
2719
2737
|
function exportRowsToPdf(columns, rows, columnTypeMap, columnTypeEnum, t, fileName = 'table.pdf', options = {}) {
|
|
2720
2738
|
if (!columns?.length)
|
|
2721
2739
|
return;
|
|
2722
2740
|
const locale = options.locale || 'en-US';
|
|
2741
|
+
const scopeIdx = columns.findIndex(c => (c.header || '').toLowerCase().includes('scope'));
|
|
2723
2742
|
const head = [columns.map(c => sanitizeText(t(c.header)))];
|
|
2724
|
-
const body = (rows ?? []).map(row => columns.map(col =>
|
|
2725
|
-
|
|
2743
|
+
const body = (rows ?? []).map(row => columns.map(col => {
|
|
2744
|
+
const forPdf = true;
|
|
2745
|
+
const raw = getDisplayValue(row, col, columnTypeMap, columnTypeEnum, t, locale, false, forPdf);
|
|
2746
|
+
return sanitizeText(raw);
|
|
2747
|
+
}));
|
|
2726
2748
|
const doc = new jsPDF({ orientation: 'landscape', unit: 'pt', format: 'A4' });
|
|
2727
2749
|
autoTable(doc, {
|
|
2728
2750
|
head,
|
|
2729
2751
|
body,
|
|
2730
|
-
styles: {
|
|
2731
|
-
|
|
2752
|
+
styles: {
|
|
2753
|
+
fontSize: 9,
|
|
2754
|
+
cellPadding: 5,
|
|
2755
|
+
overflow: 'linebreak', // this breaks long/multi-line text
|
|
2756
|
+
valign: 'top' // align multi-line cells nicely
|
|
2757
|
+
},
|
|
2758
|
+
margin: { top: 36, right: 24, bottom: 36, left: 24 }
|
|
2732
2759
|
});
|
|
2733
2760
|
doc.save(fileName);
|
|
2734
2761
|
}
|
|
2735
2762
|
/* -------------------------- Export: CSV ---------------------------- */
|
|
2736
2763
|
/**
|
|
2737
|
-
*
|
|
2738
|
-
* -
|
|
2739
|
-
* - Translates headers
|
|
2740
|
-
* -
|
|
2764
|
+
* Export rows to CSV.
|
|
2765
|
+
* - Uses visible columns only
|
|
2766
|
+
* - Translates headers
|
|
2767
|
+
* - Adds UTF-8 BOM so Excel renders diacritics/umlauts correctly
|
|
2768
|
+
* - Preserves multi-line cells (LIST → each item on a new line)
|
|
2741
2769
|
*/
|
|
2742
2770
|
function exportRowsToCsv(columns, rows, columnTypeMap, columnTypeEnum, t, fileName = 'table.csv', options = {}) {
|
|
2743
2771
|
if (!columns?.length)
|
|
@@ -2746,14 +2774,13 @@ function exportRowsToCsv(columns, rows, columnTypeMap, columnTypeEnum, t, fileNa
|
|
|
2746
2774
|
const delimiter = options.delimiter || ',';
|
|
2747
2775
|
const headers = columns.map(c => sanitizeText(t(c.header)));
|
|
2748
2776
|
const lines = (rows ?? []).map(row => columns.map(col => {
|
|
2749
|
-
const raw = getDisplayValue(row, col, columnTypeMap, columnTypeEnum, t, locale);
|
|
2750
|
-
|
|
2751
|
-
const v = trimExcelLineBreaks(sanitizeText(raw));
|
|
2777
|
+
const raw = getDisplayValue(row, col, columnTypeMap, columnTypeEnum, t, locale, true /* forCsv */);
|
|
2778
|
+
const v = cleanMultilineForCsv(sanitizeText(raw));
|
|
2752
2779
|
const safe = v.replace(/"/g, '""'); // escape double quotes
|
|
2753
2780
|
return needsQuotesCSV(v, delimiter) ? `"${safe}"` : safe;
|
|
2754
2781
|
}).join(delimiter));
|
|
2755
2782
|
const csv = [headers.join(delimiter), ...lines].join('\n');
|
|
2756
|
-
//
|
|
2783
|
+
// Prepend BOM so Excel opens as UTF-8 (č, ć, š, đ, ž, ä, ö, ü, ß, …)
|
|
2757
2784
|
const BOM = '\uFEFF';
|
|
2758
2785
|
const blob = new Blob([BOM + csv], { type: 'text/csv;charset=utf-8;' });
|
|
2759
2786
|
const a = document.createElement('a');
|
|
@@ -2767,7 +2794,7 @@ function exportRowsToCsv(columns, rows, columnTypeMap, columnTypeEnum, t, fileNa
|
|
|
2767
2794
|
}
|
|
2768
2795
|
/* --------------------------- File name ----------------------------- */
|
|
2769
2796
|
/**
|
|
2770
|
-
*
|
|
2797
|
+
* Build file name as: tableKey_YYYY-MM-DD_HH-mm.ext
|
|
2771
2798
|
* Example: risks_2025-09-10_14-32.csv
|
|
2772
2799
|
*/
|
|
2773
2800
|
function buildFileName(baseKey, ext) {
|