Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,63 @@ function basePage() {
formatNumber(value, pattern) {
return window.HarmoniaFormat.number(value, pattern);
},

/**
* Translate a column header: columns carry an optional i18next key (tkey) next to the
* design-time label, exactly like the table headers render them.
*/
columnHeader(col) {
return (window.T && col.tkey) ? window.T(col.tkey, col.label) : col.label;
},

/**
* Download rows as a CSV file. Values come from cellText(row, col) - the SAME resolver the
* table cells use, so FK columns carry their referenced labels and dates their formatted
* form, never raw ids or serialized arrays. The BOM makes Excel decode UTF-8 (Cyrillic
* included) without an import wizard.
*/
exportRowsCsv(rows, columns, cellText, filename) {
const esc = (v) => {
const s = String(v == null ? '' : v);
return /[",\n\r]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
};
const head = columns.map((c) => esc(this.columnHeader(c))).join(',');
const lines = rows.map((r) => columns.map((c) => esc(cellText(r, c))).join(','));
const blob = new Blob(['\ufeff' + [head].concat(lines).join('\r\n')], { type: 'text/csv;charset=utf-8' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = filename;
a.click();
URL.revokeObjectURL(a.href);
},

/**
* Print rows as a minimal table document in a new window (the browser dialog covers paper and
* Save as PDF). Same data path as the CSV export: the full filtered set through cellText.
*/
printRows(rows, columns, cellText, title) {
const esc = (v) => String(v == null ? '' : v)
.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
const th = columns.map((c) =>
'<th class="' + (c.number ? 'text-right' : '') + '">' + esc(this.columnHeader(c)) + '</th>').join('');
const body = rows.map((r) => '<tr>' + columns.map((c) =>
'<td class="' + (c.number ? 'text-right' : '') + '">' + esc(cellText(r, c)) + '</td>').join('') + '</tr>').join('');
const html = '<!doctype html><html><head><title>' + esc(title) + '</title><style>'
+ 'body{font-family:system-ui,-apple-system,sans-serif;margin:24px;color:#111}'
+ 'h1{font-size:18px;margin:0 0 4px}'
+ '.meta{font-size:11px;color:#555;margin:0 0 16px}'
+ 'table{border-collapse:collapse;width:100%;font-size:12px}'
+ 'th,td{border:1px solid #999;padding:4px 8px;text-align:left}'
+ 'th{background:#eee}.text-right{text-align:right}'
+ '</style></head><body><h1>' + esc(title) + '</h1>'
+ '<p class="meta">' + rows.length + ' rows - ' + esc(new Date().toLocaleString()) + '</p>'
+ '<table><thead><tr>' + th + '</tr></thead><tbody>' + body + '</tbody></table></body></html>';
const w = window.open('', '_blank');
if (!w) return;
w.document.write(html);
w.document.close();
w.focus();
w.print();
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,20 @@ document.addEventListener('alpine:init', () => {
#end
],

// ----- Export / print of the own rows: same columns and cell resolution as the table
// (FK labels, status text, formatted dates) via the shared basePage helpers.
exportCell(row, col) {
if (row[col.name] == null || row[col.name] === '') return '';
return col.status ? this.statusText(row) : this.display(row, col);
},
exportCsv() {
this.exportRowsCsv(this.items, this.columns, (r, c) => this.exportCell(r, c), '${name}.csv');
},
printList() {
this.printRows(this.items, this.columns, (r, c) => this.exportCell(r, c),
'My ' + (window.T ? window.T('$projectName:${tprefix}.t.${dataName}_plural', '${menuLabel}') : '${menuLabel}'));
},

newEntity() { this.navigate('/my/${name}/create'); },
openEntity(row) { this.navigate('/my/${name}/' + row.#foreach($property in $properties)#if($property.dataPrimaryKey)${property.name}#end#end + '/edit'); },
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
<i role="img" x-h-lucide data-lucide="plus"></i>
<span x-text="T('$projectName:${tprefix}.defaults.new', 'New')"></span>
</button>
<!-- Export the own rows as CSV / print them (Save as PDF via the browser dialog). -->
<button x-h-button data-variant="outline" data-size="sm" :disabled="items.length === 0" @click="exportCsv()">
<i role="img" x-h-lucide data-lucide="download"></i><span x-text="T('$projectName:${tprefix}.defaults.export', 'Export')"></span>
</button>
<button x-h-button data-variant="outline" data-size="sm" :disabled="items.length === 0" @click="printList()">
<i role="img" x-h-lucide data-lucide="printer"></i><span x-text="T('$projectName:${tprefix}.defaults.print', 'Print')"></span>
</button>
</div>

<div x-show="state === 'loading'" class="p-4"><div x-h-spinner></div></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ document.addEventListener('alpine:init', () => {
#end
],

// ----- Export / print of the partner's own rows: same columns and cell resolution as the
// table (status text, formatted dates) via the shared basePage helpers.
exportCell(row, col) {
if (row[col.name] == null || row[col.name] === '') return '';
return col.status ? this.statusText(row) : this.display(row, col);
},
exportCsv() {
this.exportRowsCsv(this.items, this.columns, (r, c) => this.exportCell(r, c), '${name}.csv');
},
printList() {
this.printRows(this.items, this.columns, (r, c) => this.exportCell(r, c),
window.T ? window.T('$projectName:${tprefix}.t.${dataName}_plural', '${menuLabel}') : '${menuLabel}');
},

newEntity() { this.navigate('/partner/${name}/create'); },
openEntity(row) { this.navigate('/partner/${name}/' + row.#foreach($property in $properties)#if($property.dataPrimaryKey)${property.name}#end#end + '/edit'); },
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
<i role="img" x-h-lucide data-lucide="plus"></i>
<span x-text="T('$projectName:${tprefix}.defaults.new', 'New')"></span>
</button>
<!-- Export the own rows as CSV / print them (Save as PDF via the browser dialog). -->
<button x-h-button data-variant="outline" data-size="sm" :disabled="items.length === 0" @click="exportCsv()">
<i role="img" x-h-lucide data-lucide="download"></i><span x-text="T('$projectName:${tprefix}.defaults.export', 'Export')"></span>
</button>
<button x-h-button data-variant="outline" data-size="sm" :disabled="items.length === 0" @click="printList()">
<i role="img" x-h-lucide data-lucide="printer"></i><span x-text="T('$projectName:${tprefix}.defaults.print', 'Print')"></span>
</button>
</div>

<div x-show="state === 'loading'" class="p-4"><div x-h-spinner></div></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,27 @@ document.addEventListener('alpine:init', () => {
this.currentPage = Math.max(1, Math.min(n, this.totalPages));
this.refreshIcons();
},

// ----- Export / print: the FULL filtered+sorted set (not the current page), cells resolved
// exactly like the table (FK labels, formatted dates) via the shared basePage helpers.
exportColumns: [
#foreach($property in $properties)
#if(!$property.dataAutoIncrement && $property.widgetIsMajor)
{ name: '${property.name}', label: '#if($property.widgetLabel)${property.widgetLabel}#else${property.name}#end', tkey: '$projectName:${tprefix}.t.${property.dataName}'#if($property.widgetType == "DROPDOWN" || $property.widgetType == "DOCUMENT_STATUS"), fk: true#elseif($property.isNumberType), number: true#end#if($property.isDateType), date: true#end },
#end
#end
],
exportCell(row, col) {
const v = row[col.name];
if (v == null || v === '') return '';
return col.fk ? this.lookupText(col.name, v) : this.displayValue(v, !!col.date);
},
exportCsv() {
this.exportRowsCsv(this.sortedItems, this.exportColumns, (r, c) => this.exportCell(r, c), '${name}.csv');
},
printList() {
this.printRows(this.sortedItems, this.exportColumns, (r, c) => this.exportCell(r, c),
window.T ? window.T('$projectName:${tprefix}.t.${dataName}_plural', '${menuLabel}') : '${menuLabel}');
},
}));
}, { once: true });
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
<svg x-h-icon data-icon="search" class="size-4" role="img" aria-label="search"></svg>
</div>
</div>
<!-- Export the filtered rows as CSV / print them (Save as PDF via the browser dialog). -->
<button x-h-button data-variant="outline" data-size="sm" :disabled="filteredItems.length === 0" @click="exportCsv()">
<i role="img" x-h-lucide data-lucide="download"></i><span x-text="T('$projectName:${tprefix}.defaults.export', 'Export')"></span>
</button>
<button x-h-button data-variant="outline" data-size="sm" :disabled="filteredItems.length === 0" @click="printList()">
<i role="img" x-h-lucide data-lucide="printer"></i><span x-text="T('$projectName:${tprefix}.defaults.print', 'Print')"></span>
</button>
<!-- Developer-contributed page actions for this view (customActions extension point). -->
<template x-for="action in $store.customActions.getActions(caView, 'page')" :key="action.id">
<button x-h-button data-variant="outline" data-size="sm" @click="$store.customActions.trigger(action)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,28 @@ document.addEventListener('alpine:init', () => {

goPage(n) { this.currentPage = Math.max(1, Math.min(n, this.totalPages)); this.refreshIcons(); },

// ----- Export / print: the FULL filtered+sorted set (not the current page), cells resolved
// exactly like the table (FK labels, formatted dates) via the shared basePage helpers.
exportColumns: [
#foreach($property in $properties)
#if(!$property.dataAutoIncrement && $property.widgetIsMajor)
{ name: '${property.name}', label: '#if($property.widgetLabel)${property.widgetLabel}#else${property.name}#end', tkey: '$projectName:${tprefix}.t.${property.dataName}'#if($property.widgetType == "DROPDOWN" || $property.widgetType == "DOCUMENT_STATUS"), fk: true#elseif($property.isNumberType), number: true#end#if($property.isDateType), date: true#end },
#end
#end
],
exportCell(row, col) {
const v = row[col.name];
if (v == null || v === '') return '';
return col.fk ? this.lookupText(col.name, v) : this.displayValue(v, !!col.date);
},
exportCsv() {
this.exportRowsCsv(this.sortedItems, this.exportColumns, (r, c) => this.exportCell(r, c), '${name}.csv');
},
printList() {
this.printRows(this.sortedItems, this.exportColumns, (r, c) => this.exportCell(r, c),
window.T ? window.T('$projectName:${tprefix}.t.${dataName}_plural', '${menuLabel}') : '${menuLabel}');
},

newEntity() { window.PineconeRouter.navigate('/${name}/create'); },
editEntity(row) { window.PineconeRouter.navigate('/${name}/' + encodeURIComponent(row.${primaryKeysString}) + '/edit'); },
previewEntity(row) { window.PineconeRouter.navigate('/${name}/' + encodeURIComponent(row.${primaryKeysString}) + '/preview'); },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
<i role="img" x-h-lucide data-lucide="plus"></i>
<span x-text="T('$projectName:${tprefix}.defaults.new', 'New')"></span>
</button>
<!-- Export the filtered rows as CSV / print them (Save as PDF via the browser dialog). -->
<button x-h-button data-variant="outline" data-size="sm" :disabled="sortedItems.length === 0" @click="exportCsv()">
<i role="img" x-h-lucide data-lucide="download"></i><span x-text="T('$projectName:${tprefix}.defaults.export', 'Export')"></span>
</button>
<button x-h-button data-variant="outline" data-size="sm" :disabled="sortedItems.length === 0" @click="printList()">
<i role="img" x-h-lucide data-lucide="printer"></i><span x-text="T('$projectName:${tprefix}.defaults.print', 'Print')"></span>
</button>
<!-- Developer-contributed page actions for this view (customActions extension point). -->
<template x-for="action in $store.customActions.getActions(caView, 'page')" :key="action.id">
<button x-h-button data-variant="outline" data-size="sm" @click="$store.customActions.trigger(action)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,28 @@ document.addEventListener('alpine:init', () => {
return 'default';
},

// ----- Export / print: the FULL filtered set (not the current page), cells resolved exactly
// like the table (FK labels, formatted dates) via the shared basePage helpers.
exportColumns: [
#foreach($property in $properties)
#if(!$property.dataAutoIncrement && $property.widgetIsMajor)
{ name: '${property.name}', label: '#if($property.widgetLabel)${property.widgetLabel}#else${property.name}#end', tkey: '$projectName:${tprefix}.t.${property.dataName}'#if($property.widgetType == "DROPDOWN" || $property.widgetType == "DOCUMENT_STATUS"), fk: true#elseif($property.isNumberType), number: true#end#if($property.isDateType), date: true#end },
#end
#end
],
exportCell(row, col) {
const v = row[col.name];
if (v == null || v === '') return '';
return col.fk ? this.lookupText(col.name, v) : this.displayValue(v, !!col.date);
},
exportCsv() {
this.exportRowsCsv(this.filteredMasters, this.exportColumns, (r, c) => this.exportCell(r, c), '${name}.csv');
},
printList() {
this.printRows(this.filteredMasters, this.exportColumns, (r, c) => this.exportCell(r, c),
window.T ? window.T('$projectName:${tprefix}.t.${dataName}_plural', '${menuLabel}') : '${menuLabel}');
},

newMaster() { window.PineconeRouter.navigate('/${name}/create'); },
editMaster(row) { window.PineconeRouter.navigate('/${name}/' + encodeURIComponent(row.${primaryKeysString}) + '/edit'); },
previewMaster(row) { window.PineconeRouter.navigate('/${name}/' + encodeURIComponent(row.${primaryKeysString}) + '/preview'); },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
<div x-h-input-group-addon data-align="inline-start"><svg x-h-icon data-icon="search" class="size-4" role="img" aria-label="search"></svg></div>
</div>
<button x-h-button data-variant="primary" @click="newMaster()"><i role="img" x-h-lucide data-lucide="plus"></i><span x-text="T('$projectName:${tprefix}.defaults.new', 'New')"></span></button>
<!-- Export the filtered rows as CSV / print them (Save as PDF via the browser dialog). -->
<button x-h-button data-variant="outline" data-size="sm" :disabled="filteredMasters.length === 0" @click="exportCsv()">
<i role="img" x-h-lucide data-lucide="download"></i><span x-text="T('$projectName:${tprefix}.defaults.export', 'Export')"></span>
</button>
<button x-h-button data-variant="outline" data-size="sm" :disabled="filteredMasters.length === 0" @click="printList()">
<i role="img" x-h-lucide data-lucide="printer"></i><span x-text="T('$projectName:${tprefix}.defaults.print', 'Print')"></span>
</button>
<!-- Developer-contributed page actions for this view (customActions extension point). -->
<template x-for="action in $store.customActions.getActions(caView, 'page')" :key="action.id">
<button x-h-button data-variant="outline" data-size="sm" @click="$store.customActions.trigger(action)">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<div x-h-toolbar data-variant="transparent">
<span x-h-toolbar-title>${name}</span>
<div x-h-toolbar-spacer></div>
<button x-h-button data-variant="outline" data-size="sm" @click="load()"><i role="img" x-h-lucide data-lucide="refresh-cw"></i><span>Refresh</span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="printChart()"><i role="img" x-h-lucide data-lucide="printer"></i><span>Print</span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="load()"><i role="img" x-h-lucide data-lucide="refresh-cw"></i><span x-text="T('$projectName:${tprefix}.defaults.refresh', 'Refresh')"></span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="printChart()"><i role="img" x-h-lucide data-lucide="printer"></i><span x-text="T('$projectName:${tprefix}.defaults.print', 'Print')"></span></button>
</div>
<div x-show="state === 'loading'" class="p-4"><div x-h-spinner></div></div>
<div x-show="state === 'error'" x-h-alert data-variant="negative" role="alert" class="m-4"><div x-h-alert-description x-text="error"></div></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
<div x-h-toolbar data-variant="transparent">
<span x-h-toolbar-title>${name}</span>
<div x-h-toolbar-spacer></div>
<button x-h-button data-variant="outline" data-size="sm" @click="load()"><i role="img" x-h-lucide data-lucide="refresh-cw"></i><span>Refresh</span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="exportCsv()"><i role="img" x-h-lucide data-lucide="download"></i><span>Export</span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="printReport()"><i role="img" x-h-lucide data-lucide="printer"></i><span>Print</span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="load()"><i role="img" x-h-lucide data-lucide="refresh-cw"></i><span x-text="T('$projectName:${tprefix}.defaults.refresh', 'Refresh')"></span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="exportCsv()"><i role="img" x-h-lucide data-lucide="download"></i><span x-text="T('$projectName:${tprefix}.defaults.export', 'Export')"></span></button>
<button x-h-button data-variant="outline" data-size="sm" @click="printReport()"><i role="img" x-h-lucide data-lucide="printer"></i><span x-text="T('$projectName:${tprefix}.defaults.print', 'Print')"></span></button>
</div>
<div x-show="state === 'loading'" class="p-4"><div x-h-spinner></div></div>
<div x-show="state === 'error'" x-h-alert data-variant="negative" role="alert" class="m-4"><div x-h-alert-description x-text="error"></div></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"from": "From {{text}}",
"filter": "Filter",
"print": "Print",
"export": "Export",
"reset": "Reset",
"create": "Create",
"edit": "Edit",
Expand Down
Loading
Loading