@elite.framework/ng.ui.core 1.0.81 → 1.0.82
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/base-crud/index.d.ts +1 -0
- package/fesm2022/elite.framework-ng.ui.core-base-crud.mjs +16 -2
- package/fesm2022/elite.framework-ng.ui.core-base-crud.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.ui.core-generic-crud-table.mjs +29 -29
- package/fesm2022/elite.framework-ng.ui.core-generic-crud-table.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.ui.core-generic-report.mjs +354 -286
- package/fesm2022/elite.framework-ng.ui.core-generic-report.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.ui.core-generic-search-advanced.mjs +1307 -123
- package/fesm2022/elite.framework-ng.ui.core-generic-search-advanced.mjs.map +1 -1
- package/generic-crud-table/index.d.ts +2 -6
- package/generic-report/index.d.ts +50 -26
- package/generic-search-advanced/index.d.ts +127 -25
- package/package.json +13 -13
|
@@ -1,33 +1,31 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { NgModule, inject, Input, ViewChild
|
|
3
|
-
import * as i2 from '@angular/common';
|
|
2
|
+
import { NgModule, inject, Component, Input, ViewChild } from '@angular/core';
|
|
3
|
+
import * as i2$1 from '@angular/common';
|
|
4
4
|
import { CommonModule } from '@angular/common';
|
|
5
|
-
import * as
|
|
6
|
-
import { FormGroup, ReactiveFormsModule
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import * as i11 from '@ngx-translate/core';
|
|
5
|
+
import * as i1 from '@angular/forms';
|
|
6
|
+
import { FormsModule, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
|
7
|
+
import { FormlyForm } from '@ngx-formly/core';
|
|
8
|
+
import * as i4 from '@ngx-translate/core';
|
|
10
9
|
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
11
|
-
import * as
|
|
10
|
+
import * as i2 from 'primeng/button';
|
|
12
11
|
import { ButtonModule } from 'primeng/button';
|
|
13
12
|
import { DialogModule } from 'primeng/dialog';
|
|
14
|
-
import
|
|
13
|
+
import * as i3 from 'primeng/inputtext';
|
|
15
14
|
import { InputTextModule } from 'primeng/inputtext';
|
|
16
|
-
import * as i6 from 'primeng/radiobutton';
|
|
17
15
|
import { RadioButtonModule } from 'primeng/radiobutton';
|
|
18
|
-
import * as i7 from 'primeng/checkbox';
|
|
19
16
|
import { CheckboxModule } from 'primeng/checkbox';
|
|
20
|
-
import
|
|
21
|
-
import {
|
|
22
|
-
import * as i8 from 'primeng/tabs';
|
|
23
|
-
import { TabsModule } from 'primeng/tabs';
|
|
24
|
-
import * as i1 from 'primeng/dynamicdialog';
|
|
25
|
-
import { DynamicDialogModule, DialogService } from 'primeng/dynamicdialog';
|
|
26
|
-
import { SelectModule } from 'primeng/select';
|
|
17
|
+
import * as i1$1 from 'primeng/dynamicdialog';
|
|
18
|
+
import { DynamicDialogRef, DynamicDialogConfig, DialogService } from 'primeng/dynamicdialog';
|
|
27
19
|
import { RestService } from '@elite.framework/ng.core/services';
|
|
28
20
|
import { Subject, takeUntil } from 'rxjs';
|
|
29
|
-
import * as
|
|
21
|
+
import * as i6 from 'primeng/drawer';
|
|
30
22
|
import { DrawerModule } from 'primeng/drawer';
|
|
23
|
+
import { TableModule } from 'primeng/table';
|
|
24
|
+
import * as i7 from 'primeng/splitbutton';
|
|
25
|
+
import { SplitButtonModule } from 'primeng/splitbutton';
|
|
26
|
+
import * as i8 from 'primeng/tooltip';
|
|
27
|
+
import { TooltipModule } from 'primeng/tooltip';
|
|
28
|
+
import { DomSanitizer } from '@angular/platform-browser';
|
|
31
29
|
import { QueryBuilderService } from '@elite.framework/ng.ui.core/generic-search-advanced';
|
|
32
30
|
import * as i5 from 'primeng/api';
|
|
33
31
|
|
|
@@ -43,6 +41,103 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
|
|
|
43
41
|
}]
|
|
44
42
|
}] });
|
|
45
43
|
|
|
44
|
+
// report-name-dialog.component.ts
|
|
45
|
+
class ReportNameDialogComponent {
|
|
46
|
+
fileName = '';
|
|
47
|
+
ref = inject(DynamicDialogRef);
|
|
48
|
+
config = inject(DynamicDialogConfig);
|
|
49
|
+
translate = inject(TranslateService);
|
|
50
|
+
ngOnInit() {
|
|
51
|
+
this.fileName = this.config.data?.fileName || '';
|
|
52
|
+
}
|
|
53
|
+
save() {
|
|
54
|
+
if (this.fileName?.trim()) {
|
|
55
|
+
this.ref.close(this.fileName.trim());
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ReportNameDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
59
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: ReportNameDialogComponent, isStandalone: true, selector: "app-report-name-dialog", ngImport: i0, template: `
|
|
60
|
+
<div class="p-fluid">
|
|
61
|
+
<div class="field">
|
|
62
|
+
<label for="fileName" class="block text-sm font-medium mb-2">
|
|
63
|
+
{{ 'REPORT_NAME' | translate }}
|
|
64
|
+
</label>
|
|
65
|
+
<input
|
|
66
|
+
id="fileName"
|
|
67
|
+
type="text"
|
|
68
|
+
[(ngModel)]="fileName"
|
|
69
|
+
pInputText
|
|
70
|
+
class="w-full"
|
|
71
|
+
[placeholder]="'ENTER_REPORT_NAME' | translate"
|
|
72
|
+
autofocus>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="flex justify-end gap-2 mt-4">
|
|
77
|
+
<button
|
|
78
|
+
type="button"
|
|
79
|
+
pButton
|
|
80
|
+
class="p-button-text"
|
|
81
|
+
(click)="ref.close()"
|
|
82
|
+
[label]="'CANCEL' | translate">
|
|
83
|
+
</button>
|
|
84
|
+
<button
|
|
85
|
+
type="button"
|
|
86
|
+
pButton
|
|
87
|
+
(click)="save()"
|
|
88
|
+
[label]="'SAVE' | translate">
|
|
89
|
+
</button>
|
|
90
|
+
</div>
|
|
91
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["pSize", "variant", "fluid", "invalid"] }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }] });
|
|
92
|
+
}
|
|
93
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ReportNameDialogComponent, decorators: [{
|
|
94
|
+
type: Component,
|
|
95
|
+
args: [{
|
|
96
|
+
selector: 'app-report-name-dialog',
|
|
97
|
+
standalone: true,
|
|
98
|
+
imports: [
|
|
99
|
+
CommonModule,
|
|
100
|
+
FormsModule,
|
|
101
|
+
TranslateModule,
|
|
102
|
+
ButtonModule,
|
|
103
|
+
InputTextModule
|
|
104
|
+
],
|
|
105
|
+
template: `
|
|
106
|
+
<div class="p-fluid">
|
|
107
|
+
<div class="field">
|
|
108
|
+
<label for="fileName" class="block text-sm font-medium mb-2">
|
|
109
|
+
{{ 'REPORT_NAME' | translate }}
|
|
110
|
+
</label>
|
|
111
|
+
<input
|
|
112
|
+
id="fileName"
|
|
113
|
+
type="text"
|
|
114
|
+
[(ngModel)]="fileName"
|
|
115
|
+
pInputText
|
|
116
|
+
class="w-full"
|
|
117
|
+
[placeholder]="'ENTER_REPORT_NAME' | translate"
|
|
118
|
+
autofocus>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div class="flex justify-end gap-2 mt-4">
|
|
123
|
+
<button
|
|
124
|
+
type="button"
|
|
125
|
+
pButton
|
|
126
|
+
class="p-button-text"
|
|
127
|
+
(click)="ref.close()"
|
|
128
|
+
[label]="'CANCEL' | translate">
|
|
129
|
+
</button>
|
|
130
|
+
<button
|
|
131
|
+
type="button"
|
|
132
|
+
pButton
|
|
133
|
+
(click)="save()"
|
|
134
|
+
[label]="'SAVE' | translate">
|
|
135
|
+
</button>
|
|
136
|
+
</div>
|
|
137
|
+
`
|
|
138
|
+
}]
|
|
139
|
+
}] });
|
|
140
|
+
|
|
46
141
|
var ExportType;
|
|
47
142
|
(function (ExportType) {
|
|
48
143
|
ExportType[ExportType["LIST"] = 0] = "LIST";
|
|
@@ -57,14 +152,15 @@ class GenericReportComponent {
|
|
|
57
152
|
previewContainer;
|
|
58
153
|
filterFields = [];
|
|
59
154
|
fields_ = [];
|
|
60
|
-
|
|
61
|
-
exportType = ExportType.EXCEL;
|
|
155
|
+
exportType = ExportType.PDF;
|
|
62
156
|
fileName = '';
|
|
63
157
|
showFilters = false;
|
|
64
158
|
loading = false;
|
|
65
|
-
activeTabIndex = 0;
|
|
66
159
|
currentDate = new Date();
|
|
67
160
|
previewData = [];
|
|
161
|
+
htmlExportContent = '';
|
|
162
|
+
showHtmlInIframe = false;
|
|
163
|
+
previewColumns = [];
|
|
68
164
|
options = {};
|
|
69
165
|
enableQueryBuilder = true;
|
|
70
166
|
localExport = false;
|
|
@@ -72,40 +168,49 @@ class GenericReportComponent {
|
|
|
72
168
|
apiName = '';
|
|
73
169
|
model = {};
|
|
74
170
|
form = new FormGroup({});
|
|
75
|
-
exportConfig
|
|
76
|
-
columns: {},
|
|
77
|
-
filters: this.model,
|
|
78
|
-
exportType: this.exportType,
|
|
79
|
-
fileName: this.fileName
|
|
80
|
-
};
|
|
171
|
+
exportConfig;
|
|
81
172
|
exportTypes = [
|
|
82
173
|
{ value: ExportType.EXCEL, label: 'EXCEL', icon: 'pi pi-file-excel' },
|
|
83
174
|
{ value: ExportType.PDF, label: 'PDF', icon: 'pi pi-file-pdf' },
|
|
84
175
|
{ value: ExportType.HTML, label: 'HTML', icon: 'pi pi-code' },
|
|
85
176
|
{ value: ExportType.PRINT, label: 'PRINT', icon: 'pi pi-print' }
|
|
86
177
|
];
|
|
178
|
+
exportMenuItems = [];
|
|
87
179
|
destroy$ = new Subject();
|
|
180
|
+
dialogService = inject(DialogService);
|
|
88
181
|
translate = inject(TranslateService);
|
|
89
182
|
restService = inject(RestService);
|
|
90
183
|
queryBuilder = inject(QueryBuilderService);
|
|
184
|
+
sanitizer = inject(DomSanitizer);
|
|
91
185
|
constructor(ref, config) {
|
|
92
186
|
this.ref = ref;
|
|
93
187
|
this.config = config;
|
|
94
188
|
}
|
|
189
|
+
ngOnDestroy() {
|
|
190
|
+
this.destroy$.next();
|
|
191
|
+
this.destroy$.complete();
|
|
192
|
+
if (this.ref) {
|
|
193
|
+
try {
|
|
194
|
+
this.ref.close();
|
|
195
|
+
}
|
|
196
|
+
catch (e) {
|
|
197
|
+
// Ignore errors during cleanup
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
95
201
|
ngOnInit() {
|
|
96
202
|
this.filterFields = this.config.data?.filterFields || [];
|
|
97
|
-
this.initializeComponent();
|
|
98
203
|
this.buildQueryUIFields();
|
|
204
|
+
this.initializeComponent();
|
|
205
|
+
this.initializeExportConfig();
|
|
206
|
+
this.initializeExportMenu();
|
|
99
207
|
}
|
|
100
208
|
get filterCount() {
|
|
101
|
-
|
|
102
|
-
((this.model?.sorting ?? [])?.length || 0) +
|
|
103
|
-
(this.model?.pagination && this.model?.pagination?.top ? 1 : 0);
|
|
104
|
-
return filters;
|
|
209
|
+
return this.queryBuilder.getAppliedFiltersCount(this.model).total;
|
|
105
210
|
}
|
|
106
211
|
buildQueryUIFields() {
|
|
107
212
|
if (this.enableQueryBuilder) {
|
|
108
|
-
this.fields_ = this.queryBuilder.buildQueryUIFields(this.filterFields);
|
|
213
|
+
this.fields_ = this.queryBuilder.buildQueryUIFields(this.filterFields, true, true);
|
|
109
214
|
}
|
|
110
215
|
else {
|
|
111
216
|
this.fields_ = this.filterFields;
|
|
@@ -113,32 +218,52 @@ class GenericReportComponent {
|
|
|
113
218
|
}
|
|
114
219
|
initializeComponent() {
|
|
115
220
|
this.apiName = this.config.data?.apiName || '';
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
displayName: String(columnDefinitions[key]),
|
|
121
|
-
selected: true,
|
|
122
|
-
customName: String(columnDefinitions[key])
|
|
123
|
-
}));
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
this.availableColumns = (this.filterFields || []).map(f => {
|
|
127
|
-
const key = String(f.key ?? '');
|
|
128
|
-
const label = String(f.props?.label ?? key);
|
|
129
|
-
return {
|
|
130
|
-
key,
|
|
131
|
-
displayName: this.translate.instant(label),
|
|
132
|
-
selected: true,
|
|
133
|
-
customName: label
|
|
134
|
-
};
|
|
135
|
-
});
|
|
136
|
-
}
|
|
221
|
+
this.initializeFilterFields();
|
|
222
|
+
this.onExport();
|
|
223
|
+
}
|
|
224
|
+
initializeFilterFields() {
|
|
137
225
|
this.filterFields = this.config.data?.filterFields || this.getDefaultFilterFields();
|
|
138
226
|
this.model = this.config.data?.model || {};
|
|
139
227
|
this.fileName = this.config.data?.defaultFileName || `export_${new Date().toISOString().split('T')[0]}`;
|
|
140
|
-
|
|
141
|
-
|
|
228
|
+
}
|
|
229
|
+
initializeExportConfig() {
|
|
230
|
+
this.exportConfig = {
|
|
231
|
+
filters: this.model,
|
|
232
|
+
exportType: this.exportType,
|
|
233
|
+
fileName: this.fileName
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
initializeExportMenu() {
|
|
237
|
+
this.exportMenuItems = [
|
|
238
|
+
// Edit Report Name menu item
|
|
239
|
+
{
|
|
240
|
+
label: this.translate.instant('EDIT_REPORT_NAME'),
|
|
241
|
+
icon: 'pi pi-pencil',
|
|
242
|
+
command: () => this.openReportNameDialog()
|
|
243
|
+
},
|
|
244
|
+
// Separator
|
|
245
|
+
{ separator: true },
|
|
246
|
+
// Export type menu items
|
|
247
|
+
...this.exportTypes.map(type => ({
|
|
248
|
+
label: this.translate.instant(type.label),
|
|
249
|
+
icon: type.icon,
|
|
250
|
+
command: () => this.onExportTypeChange(type.value)
|
|
251
|
+
}))
|
|
252
|
+
];
|
|
253
|
+
}
|
|
254
|
+
openReportNameDialog() {
|
|
255
|
+
const ref = this.dialogService.open(ReportNameDialogComponent, {
|
|
256
|
+
header: this.translate.instant('EDIT_REPORT_NAME'),
|
|
257
|
+
width: '500px',
|
|
258
|
+
data: {
|
|
259
|
+
fileName: this.fileName
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
ref.onClose.subscribe((result) => {
|
|
263
|
+
if (result) {
|
|
264
|
+
this.fileName = result;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
142
267
|
}
|
|
143
268
|
getDefaultFilterFields() {
|
|
144
269
|
return [
|
|
@@ -152,173 +277,44 @@ class GenericReportComponent {
|
|
|
152
277
|
}
|
|
153
278
|
];
|
|
154
279
|
}
|
|
155
|
-
|
|
156
|
-
return this.availableColumns.filter(col => col.selected);
|
|
157
|
-
}
|
|
158
|
-
onExportTypeChange(type) {
|
|
159
|
-
this.exportType = type;
|
|
160
|
-
// Auto-switch to preview tab for HTML/Print
|
|
161
|
-
if ((type === ExportType.HTML || type === ExportType.PRINT) && this.selectedColumns.length > 0) {
|
|
162
|
-
this.activeTabIndex = 1;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
onColumnToggle(column) {
|
|
166
|
-
if (!column.selected) {
|
|
167
|
-
column.customName = column.displayName;
|
|
168
|
-
}
|
|
169
|
-
// Refresh preview when columns change
|
|
170
|
-
if (this.activeTabIndex === 1) {
|
|
171
|
-
this.generatePreview();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
onCustomNameChange(column) {
|
|
175
|
-
if (!column.customName?.trim()) {
|
|
176
|
-
column.customName = column.displayName;
|
|
177
|
-
}
|
|
178
|
-
// Refresh preview when column names change
|
|
179
|
-
if (this.activeTabIndex === 1) {
|
|
180
|
-
this.generatePreview();
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
selectAllColumns() {
|
|
184
|
-
this.availableColumns.forEach(col => {
|
|
185
|
-
col.selected = true;
|
|
186
|
-
col.customName = col.displayName;
|
|
187
|
-
});
|
|
188
|
-
this.generatePreview();
|
|
189
|
-
}
|
|
190
|
-
deselectAllColumns() {
|
|
191
|
-
this.availableColumns.forEach(col => {
|
|
192
|
-
col.selected = false;
|
|
193
|
-
});
|
|
194
|
-
this.previewData = [];
|
|
195
|
-
}
|
|
280
|
+
// Query and Preview Methods
|
|
196
281
|
generatePreview() {
|
|
197
|
-
|
|
198
|
-
this.previewData = [];
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
// In a real application, you would call your API here
|
|
202
|
-
// For demo purposes, we're using the sample data
|
|
203
|
-
this.loadPreviewData();
|
|
204
|
-
}
|
|
205
|
-
getPreviewValue(row, columnKey) {
|
|
206
|
-
// Handle nested properties with dot notation
|
|
207
|
-
return columnKey.split('.').reduce((obj, key) => obj?.[key], row) || '-';
|
|
208
|
-
}
|
|
209
|
-
getExportButtonText() {
|
|
210
|
-
switch (this.exportType) {
|
|
211
|
-
case ExportType.PRINT:
|
|
212
|
-
return this.translate.instant('PRINT');
|
|
213
|
-
case ExportType.HTML:
|
|
214
|
-
return this.translate.instant('GENERATE_REPORT');
|
|
215
|
-
default:
|
|
216
|
-
return this.translate.instant('EXPORT');
|
|
217
|
-
}
|
|
282
|
+
this.onExport();
|
|
218
283
|
}
|
|
219
284
|
onSubmit() {
|
|
220
|
-
// Use the new QueryBuilderService methods
|
|
221
285
|
const odataParams = this.queryBuilder.buildODataFromQueryModel(this.model, this.filterFields);
|
|
222
|
-
// this.odataSearch.emit(odataParams);
|
|
223
|
-
// Generate query string using the unified method
|
|
224
286
|
this.queryString = this.queryBuilder.toODataQueryString(odataParams);
|
|
225
|
-
|
|
226
|
-
if (this.model?.pagination && this.model?.pagination?.top) {
|
|
227
|
-
// this.paginationChange.emit({
|
|
228
|
-
// top:this.model?.pagination?.top,
|
|
229
|
-
// // skip:,
|
|
230
|
-
// });
|
|
231
|
-
}
|
|
232
|
-
// this.search.emit(
|
|
233
|
-
// {
|
|
234
|
-
// filter:this.model['filter'],
|
|
235
|
-
// query:this.queryString,
|
|
236
|
-
// // sorting:,
|
|
237
|
-
// // top:,
|
|
238
|
-
// // skip:,
|
|
239
|
-
// }
|
|
240
|
-
// );
|
|
241
|
-
this.loadPreviewData();
|
|
287
|
+
this.onExport();
|
|
242
288
|
}
|
|
243
289
|
onReset() {
|
|
244
|
-
this.
|
|
245
|
-
col.selected = true;
|
|
246
|
-
col.customName = col.displayName;
|
|
247
|
-
});
|
|
248
|
-
this.exportType = ExportType.EXCEL;
|
|
290
|
+
this.exportType = ExportType.PDF;
|
|
249
291
|
this.fileName = `export_${new Date().toISOString().split('T')[0]}`;
|
|
250
292
|
this.form.reset();
|
|
251
293
|
this.model = {};
|
|
252
|
-
this.activeTabIndex = 0;
|
|
253
294
|
this.generatePreview();
|
|
254
295
|
}
|
|
296
|
+
// Export Methods
|
|
255
297
|
onExport() {
|
|
256
|
-
if (this.selectedColumns.length === 0)
|
|
257
|
-
return;
|
|
258
298
|
this.loading = true;
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const exportConfig = {
|
|
265
|
-
columns: columnsMapping,
|
|
299
|
+
const exportConfig = this.createExportConfig();
|
|
300
|
+
this.handleApiExport(exportConfig);
|
|
301
|
+
}
|
|
302
|
+
createExportConfig() {
|
|
303
|
+
return {
|
|
266
304
|
filters: this.model,
|
|
267
305
|
exportType: this.exportType,
|
|
268
306
|
fileName: this.fileName
|
|
269
307
|
};
|
|
270
|
-
// Handle export based on type
|
|
271
|
-
switch (this.exportType) {
|
|
272
|
-
case ExportType.PRINT:
|
|
273
|
-
this.printPreview();
|
|
274
|
-
this.loading = false;
|
|
275
|
-
break;
|
|
276
|
-
case ExportType.HTML:
|
|
277
|
-
this.generateHtmlReport(exportConfig);
|
|
278
|
-
this.loading = false;
|
|
279
|
-
break;
|
|
280
|
-
default:
|
|
281
|
-
this.handleApiExport(exportConfig);
|
|
282
|
-
break;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
generateHtmlReport(config) {
|
|
286
|
-
const htmlContent = this.previewContainer.nativeElement.innerHTML;
|
|
287
|
-
const blob = new Blob([htmlContent], { type: 'text/html' });
|
|
288
|
-
this.downloadFile(blob, `${config.fileName}.html`);
|
|
289
308
|
}
|
|
290
309
|
handleApiExport(config) {
|
|
291
310
|
if (this.form.invalid)
|
|
292
311
|
return;
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
fileName: config.fileName || '',
|
|
296
|
-
query: this.queryString,
|
|
297
|
-
exportType: config.exportType,
|
|
298
|
-
columns: JSON.stringify(config.columns),
|
|
299
|
-
// ...this.currentFilters,
|
|
300
|
-
// ...this.pageFilters,
|
|
301
|
-
// ...(this.searchGlobal ? { filter: this.searchGlobal } : {}),
|
|
302
|
-
};
|
|
303
|
-
const params = Object.keys(filters).reduce((acc, key) => {
|
|
304
|
-
acc[key] = filters[key];
|
|
305
|
-
return acc;
|
|
306
|
-
}, {});
|
|
307
|
-
this.restService.request({
|
|
308
|
-
method: 'GET',
|
|
309
|
-
url: `/${this.apiName}/export`,
|
|
310
|
-
// body: { ...config.filters, ...this.model },
|
|
311
|
-
params: params
|
|
312
|
-
}, { apiName: this.apiName })
|
|
312
|
+
const requestOptions = this.createRequestOptions(config);
|
|
313
|
+
this.restService.request(requestOptions, { apiName: this.apiName })
|
|
313
314
|
.pipe(takeUntil(this.destroy$))
|
|
314
315
|
.subscribe({
|
|
315
316
|
next: (response) => {
|
|
316
|
-
this.
|
|
317
|
-
if (config.exportType == ExportType.EXCEL) {
|
|
318
|
-
const blob = this.base64ToBlob(response, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
319
|
-
this.downloadFile(blob, `${config.fileName}.${this.getFileExtension(config.exportType)}`);
|
|
320
|
-
}
|
|
321
|
-
this.loading = false;
|
|
317
|
+
this.handleExportResponse(response, config);
|
|
322
318
|
},
|
|
323
319
|
error: (error) => {
|
|
324
320
|
console.error('Export failed:', error);
|
|
@@ -326,45 +322,149 @@ class GenericReportComponent {
|
|
|
326
322
|
}
|
|
327
323
|
});
|
|
328
324
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
325
|
+
createRequestOptions(config) {
|
|
326
|
+
// Default query
|
|
327
|
+
if (!this.queryString || this.queryString == '') {
|
|
328
|
+
// Use the new QueryBuilderService methods
|
|
329
|
+
const odataParams = this.queryBuilder.buildODataFromQueryModel(this.model, this.filterFields);
|
|
330
|
+
// this.odataSearch.emit(odataParams);
|
|
331
|
+
// Generate query string using the unified method
|
|
332
|
+
this.queryString = this.queryBuilder.toODataQueryString(odataParams);
|
|
333
|
+
// console.log('OData Query String:', queryString);
|
|
334
|
+
}
|
|
333
335
|
const filters = {
|
|
336
|
+
fileName: config.fileName || '',
|
|
334
337
|
query: this.queryString,
|
|
335
|
-
exportType:
|
|
336
|
-
columns: JSON.stringify(this.getPreviewColumns()),
|
|
337
|
-
// ...this.currentFilters,
|
|
338
|
-
// ...this.pageFilters,
|
|
339
|
-
// ...(this.searchGlobal ? { filter: this.searchGlobal } : {}),
|
|
338
|
+
exportType: config.exportType,
|
|
340
339
|
};
|
|
341
340
|
const params = Object.keys(filters).reduce((acc, key) => {
|
|
342
341
|
acc[key] = filters[key];
|
|
343
342
|
return acc;
|
|
344
343
|
}, {});
|
|
345
|
-
|
|
344
|
+
const requestOptions = {
|
|
346
345
|
method: 'GET',
|
|
347
346
|
url: `/${this.apiName}/export`,
|
|
348
347
|
params: params
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
this.loading = false;
|
|
355
|
-
},
|
|
356
|
-
error: (error) => {
|
|
357
|
-
console.error('Preview load failed:', error);
|
|
358
|
-
this.loading = false;
|
|
359
|
-
}
|
|
360
|
-
});
|
|
348
|
+
};
|
|
349
|
+
if (config.exportType === ExportType.HTML) {
|
|
350
|
+
requestOptions.responseType = 'text';
|
|
351
|
+
}
|
|
352
|
+
return requestOptions;
|
|
361
353
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
354
|
+
// private handleExportResponse(response: any, config: any) {
|
|
355
|
+
// this.loading = false;
|
|
356
|
+
// if (config.exportType === ExportType.HTML) {
|
|
357
|
+
// this.showHtmlExport(response);
|
|
358
|
+
// } else {
|
|
359
|
+
// this.downloadBinaryExport(response, config);
|
|
360
|
+
// }
|
|
361
|
+
// }
|
|
362
|
+
handleExportResponse(response, config) {
|
|
363
|
+
this.loading = false;
|
|
364
|
+
if (config.exportType === ExportType.HTML) {
|
|
365
|
+
this.showHtmlExport(response);
|
|
366
|
+
// } else if (config.exportType === ExportType.PDF && this.isMobileDevice()) {
|
|
367
|
+
}
|
|
368
|
+
else if (config.exportType === ExportType.PDF) {
|
|
369
|
+
this.showPdfInMobile(response, config);
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
this.downloadBinaryExport(response, config);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// Platform detection methods
|
|
376
|
+
isMobileDevice() {
|
|
377
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
378
|
+
}
|
|
379
|
+
isIOS() {
|
|
380
|
+
return /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
381
|
+
}
|
|
382
|
+
isAndroid() {
|
|
383
|
+
return /Android/.test(navigator.userAgent);
|
|
384
|
+
}
|
|
385
|
+
showPdfModal = false;
|
|
386
|
+
currentPdfUrl;
|
|
387
|
+
currentFileName = '';
|
|
388
|
+
showPdfInMobile(base64Data, config) {
|
|
389
|
+
try {
|
|
390
|
+
const blob = this.base64ToBlob(base64Data, this.getMimeType(ExportType.PDF));
|
|
391
|
+
this.currentPdfUrl = this.sanitizeUrl(URL.createObjectURL(blob));
|
|
392
|
+
this.currentFileName = `${config.fileName}.pdf`;
|
|
393
|
+
this.showPdfModal = true;
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
var error = 'PDF is too large for mobile viewing. Please download instead.';
|
|
397
|
+
}
|
|
398
|
+
finally {
|
|
399
|
+
// this.loading = false;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
sanitizeUrl(url) {
|
|
403
|
+
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
|
|
404
|
+
}
|
|
405
|
+
// onPdfModalClose(): void {
|
|
406
|
+
// this.showPdfModal = false;
|
|
407
|
+
// if (this.currentPdfUrl) {
|
|
408
|
+
// URL.revokeObjectURL(this.currentPdfUrl);
|
|
409
|
+
// this.currentPdfUrl = '';
|
|
410
|
+
// }
|
|
411
|
+
// }
|
|
412
|
+
onPdfDownload() {
|
|
413
|
+
// Trigger download
|
|
414
|
+
// const blob = this.base64ToBlob(this.getCurrentBase64(), this.getMimeType(ExportType.PDF));
|
|
415
|
+
// this.downloadFile(blob, this.currentFileName);
|
|
416
|
+
}
|
|
417
|
+
downloadBinaryExport(response, config) {
|
|
418
|
+
const blob = this.base64ToBlob(response, this.getMimeType(config.exportType));
|
|
419
|
+
this.downloadFile(blob, `${config.fileName}.${this.getFileExtension(config.exportType)}`);
|
|
420
|
+
}
|
|
421
|
+
// HTML Export Methods
|
|
422
|
+
showHtmlExport(htmlContent) {
|
|
423
|
+
const cleanHtml = this.cleanHtmlContent(htmlContent);
|
|
424
|
+
this.htmlExportContent = cleanHtml;
|
|
425
|
+
this.showHtmlInIframe = true;
|
|
426
|
+
setTimeout(() => {
|
|
427
|
+
this.setIframeContent(cleanHtml);
|
|
428
|
+
}, 100);
|
|
429
|
+
}
|
|
430
|
+
setIframeContent(htmlContent) {
|
|
431
|
+
const iframe = document.getElementById('reportIframe');
|
|
432
|
+
if (!iframe) {
|
|
433
|
+
console.error('Iframe not found');
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
437
|
+
if (iframeDoc) {
|
|
438
|
+
iframeDoc.open();
|
|
439
|
+
iframeDoc.write(htmlContent);
|
|
440
|
+
iframeDoc.close();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
print() {
|
|
444
|
+
// const iframe = document.getElementById('reportIframe') as HTMLIFrameElement | null;
|
|
445
|
+
// if (!iframe || !iframe.contentWindow) return;
|
|
446
|
+
// const iframeWindow = iframe.contentWindow;
|
|
447
|
+
// iframeWindow.focus();
|
|
448
|
+
// iframeWindow.print();
|
|
449
|
+
document.getElementById('reportIframe').contentWindow.print();
|
|
450
|
+
}
|
|
451
|
+
// Utility Methods
|
|
452
|
+
getExportButtonText() {
|
|
453
|
+
switch (this.exportType) {
|
|
454
|
+
case ExportType.PRINT:
|
|
455
|
+
return this.translate.instant('PRINT');
|
|
456
|
+
case ExportType.HTML:
|
|
457
|
+
return this.translate.instant('EXPORT');
|
|
458
|
+
default:
|
|
459
|
+
return this.translate.instant('EXPORT');
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
onExportTypeChange(type) {
|
|
463
|
+
this.exportType = type;
|
|
464
|
+
}
|
|
465
|
+
getCurrentExportTypeIcon() {
|
|
466
|
+
const currentType = this.exportTypes.find(type => type.value === this.exportType);
|
|
467
|
+
return currentType?.icon || 'pi pi-download';
|
|
368
468
|
}
|
|
369
469
|
base64ToBlob(base64, mime) {
|
|
370
470
|
const byteChars = atob(base64);
|
|
@@ -390,80 +490,48 @@ class GenericReportComponent {
|
|
|
390
490
|
case ExportType.HTML:
|
|
391
491
|
return 'html';
|
|
392
492
|
default:
|
|
393
|
-
return '
|
|
493
|
+
return 'pdf';
|
|
394
494
|
}
|
|
395
495
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
<html>
|
|
405
|
-
<head>
|
|
406
|
-
<title>${this.fileName}</title>
|
|
407
|
-
<style>
|
|
408
|
-
body { font-family: Arial, sans-serif; margin: 20px; }
|
|
409
|
-
table { width: 100%; border-collapse: collapse; }
|
|
410
|
-
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
|
|
411
|
-
th { background-color: #f5f5f5; font-weight: bold; }
|
|
412
|
-
.header { text-align: center; margin-bottom: 20px; }
|
|
413
|
-
.footer { text-align: center; margin-top: 20px; font-size: 12px; color: #666; }
|
|
414
|
-
@media print {
|
|
415
|
-
body { margin: 0; }
|
|
416
|
-
.no-print { display: none; }
|
|
417
|
-
}
|
|
418
|
-
</style>
|
|
419
|
-
</head>
|
|
420
|
-
<body>
|
|
421
|
-
${printContent}
|
|
422
|
-
<div class="footer no-print">
|
|
423
|
-
<button onclick="window.print()" style="padding: 10px 20px; margin: 10px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">
|
|
424
|
-
Print Report
|
|
425
|
-
</button>
|
|
426
|
-
<button onclick="window.close()" style="padding: 10px 20px; margin: 10px; background: #6c757d; color: white; border: none; border-radius: 4px; cursor: pointer;">
|
|
427
|
-
Close
|
|
428
|
-
</button>
|
|
429
|
-
</div>
|
|
430
|
-
</body>
|
|
431
|
-
</html>
|
|
432
|
-
`);
|
|
433
|
-
printWindow.document.close();
|
|
434
|
-
// Auto-print when window loads
|
|
435
|
-
printWindow.onload = () => {
|
|
436
|
-
printWindow.focus();
|
|
437
|
-
// Uncomment the line below for auto-print
|
|
438
|
-
// printWindow.print();
|
|
439
|
-
};
|
|
496
|
+
getMimeType(exportType) {
|
|
497
|
+
switch (exportType) {
|
|
498
|
+
case ExportType.EXCEL:
|
|
499
|
+
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
|
500
|
+
case ExportType.PDF:
|
|
501
|
+
return 'application/pdf';
|
|
502
|
+
default:
|
|
503
|
+
return 'application/octet-stream';
|
|
440
504
|
}
|
|
441
505
|
}
|
|
442
|
-
|
|
443
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: GenericReportComponent, isStandalone: true, selector: "app-generic-report", inputs: { filterFields: "filterFields", enableQueryBuilder: "enableQueryBuilder", localExport: "localExport", queryString: "queryString", apiName: "apiName", model: "model" }, providers: [DialogService], viewQueries: [{ propertyName: "previewContainer", first: true, predicate: ["previewContainer"], descendants: true }], ngImport: i0, template: "\r\n <div class=\"flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg max-w-6xl mx-auto\">\r\n <!-- Header -->\r\n <!-- <div class=\"flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700\">\r\n <h2 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'EXPORT_DATA' | translate }}\r\n </h2>\r\n <button\r\n (click)=\"ref?.close()\"\r\n class=\"p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\r\n aria-label=\"Close\">\r\n <i class=\"pi pi-times text-gray-500 dark:text-gray-400\"></i>\r\n </button>\r\n </div> -->\r\n\r\n <!-- Content -->\r\n <div class=\"flex-1 overflow-hidden\">\r\n <p-tabs [value]=\"activeTabIndex\">\r\n <!-- Configuration Tab -->\r\n <p-tablist>\r\n <p-tab value=\"0\">{{'CONFIGURATION' | translate}}</p-tab>\r\n <p-tab value=\"1\">{{'PREVIEW' | translate}}</p-tab>\r\n </p-tablist>\r\n <p-tabpanels>\r\n <p-tabpanel value=\"0\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Left Column - Export Settings -->\r\n <div class=\"space-y-6\">\r\n <!-- File Name -->\r\n <div class=\"space-y-2\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'FILE_NAME' | translate }}\r\n </label>\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"fileName\"\r\n class=\"w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\r\n [placeholder]=\"'ENTER_FILE_NAME' | translate\">\r\n </div>\r\n\r\n <!-- Export Type -->\r\n <div class=\"space-y-3\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'EXPORT_FORMAT' | translate }}\r\n </label>\r\n <div class=\"grid grid-cols-2 gap-3\">\r\n <div *ngFor=\"let type of exportTypes\" class=\"flex items-center\">\r\n <p-radioButton\r\n [name]=\"'exportType'\"\r\n [value]=\"type.value\"\r\n [(ngModel)]=\"exportType\"\r\n [inputId]=\"`${type.value}`\"\r\n (onClick)=\"onExportTypeChange(type.value)\"\r\n class=\"mr-3\">\r\n </p-radioButton>\r\n <label [for]=\"type.value\" class=\"flex items-center cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n <i [class]=\"type.icon + ' mr-2'\"></i>\r\n {{ type.label | translate }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Section -->\r\n <div class=\"space-y-3\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SEARCH_FILTERS' | translate }}\r\n </label>\r\n <button\r\n type=\"button\"\r\n (click)=\"showFilters = !showFilters\"\r\n class=\"text-sm text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ showFilters ? ('HIDE_FILTERS' | translate) : ('SHOW_FILTERS' | translate) }}\r\n </button>\r\n </div>\r\n\r\n <!-- <div *ngIf=\"showFilters\" class=\"space-y-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\">\r\n </formly-form>\r\n </div> -->\r\n </div>\r\n </div>\r\n\r\n <!-- Right Column - Column Selection -->\r\n <div class=\"space-y-4\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SELECT_COLUMNS' | translate }}\r\n </label>\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"selectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'SELECT_ALL' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"deselectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'DESELECT_ALL' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"max-h-80 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-lg\">\r\n <div *ngFor=\"let column of availableColumns\" class=\"flex items-center p-3 border-b border-gray-100 dark:border-gray-600 last:border-b-0 hover:bg-gray-50 dark:hover:bg-gray-700\">\r\n <p-checkbox\r\n [binary]=\"true\"\r\n [(ngModel)]=\"column.selected\"\r\n [inputId]=\"column.key\"\r\n (onChange)=\"onColumnToggle(column)\"\r\n class=\"mr-3\">\r\n </p-checkbox>\r\n <label [for]=\"column.key\" class=\"flex-1 cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n {{ column.displayName }}\r\n </label>\r\n <div *ngIf=\"column.selected\" class=\"flex items-center gap-2\">\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"column.customName\"\r\n (blur)=\"onCustomNameChange(column)\"\r\n [placeholder]=\"column.displayName\"\r\n class=\"text-xs p-1 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-white w-32\"\r\n [title]=\"'CUSTOM_COLUMN_NAME' | translate\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Selected Columns Summary -->\r\n <div *ngIf=\"selectedColumns.length > 0\" class=\"p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg\">\r\n <p class=\"text-sm text-blue-700 dark:text-blue-300\">\r\n {{ 'SELECTED_COLUMNS_COUNT' | translate: { count: selectedColumns.length } }}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n <!-- Preview Tab -->\r\n <!-- [disabled]=\"selectedColumns.length === 0\" -->\r\n <p-tabpanel value=\"1\" >\r\n <div class=\"p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Preview Actions -->\r\n <div class=\"flex justify-between items-center mb-4\">\r\n <h3 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'REPORT_PREVIEW' | translate }}\r\n </h3>\r\n <div class=\"flex gap-2\">\r\n <button\r\n *ngIf=\"exportType === 1 || exportType === 4\"\r\n (click)=\"printPreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\r\n <i class=\"pi pi-print mr-2\"></i>\r\n {{ 'PRINT' | translate }}\r\n </button>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors\">\r\n <i class=\"pi pi-refresh mr-2\"></i>\r\n {{ 'REFRESH_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div #previewContainer class=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6\">\r\n <!-- Report Header -->\r\n <div class=\"text-center mb-6 border-b border-gray-200 dark:border-gray-700 pb-4\">\r\n <h1 class=\"text-2xl font-bold text-gray-900 dark:text-white\">{{ fileName }}</h1>\r\n <p class=\"text-gray-600 dark:text-gray-400 mt-2\">\r\n {{ 'GENERATED_ON' | translate }}: {{ currentDate | date:'medium' }}\r\n </p>\r\n </div>\r\n\r\n <!-- Report Table -->\r\n <div class=\"overflow-x-auto\">\r\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\r\n <thead class=\"bg-gray-50 dark:bg-gray-700\">\r\n <tr>\r\n <th\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider border border-gray-200 dark:border-gray-600\">\r\n {{ column.customName || column.displayName }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\r\n <tr *ngFor=\"let row of previewData; let i = index\"\r\n [class.bg-gray-50]=\"i % 2 === 0\"\r\n [class.dark:bg-gray-900]=\"i % 2 === 0\">\r\n <td\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white border border-gray-200 dark:border-gray-600\">\r\n {{ getPreviewValue(row, column.key) }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Empty State -->\r\n <div *ngIf=\"previewData.length === 0\" class=\"text-center py-8\">\r\n <i class=\"pi pi-inbox text-4xl text-gray-400 dark:text-gray-500 mb-4\"></i>\r\n <p class=\"text-gray-500 dark:text-gray-400\">{{ 'NO_PREVIEW_DATA' | translate }}</p>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"mt-4 px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'GENERATE_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n\r\n <!-- Report Footer -->\r\n <div class=\"text-center mt-6 border-t border-gray-200 dark:border-gray-700 pt-4\">\r\n <p class=\"text-sm text-gray-500 dark:text-gray-400\">\r\n {{ 'PAGE' | translate }} 1 of 1\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Info -->\r\n <div class=\"mt-4 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\">\r\n <p class=\"text-sm text-green-700 dark:text-green-300\">\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n {{ 'PREVIEW_INFO' | translate }}\r\n </p>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n </p-tabpanels>\r\n </p-tabs>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"border-t border-gray-200 dark:border-gray-700 px-6 py-4 bg-gray-50 dark:bg-gray-800\">\r\n <div class=\"flex justify-between items-center\">\r\n <button\r\n type=\"button\"\r\n (click)=\"onReset()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors\"\r\n [disabled]=\"loading\">\r\n <i class=\"pi pi-refresh ml-2\"></i>\r\n {{ 'RESET' | translate }}\r\n </button>\r\n\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"ref?.close()\"\r\n class=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [disabled]=\"loading\">\r\n {{ 'CANCEL' | translate }}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"loading || selectedColumns.length === 0\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors\">\r\n <i class=\"pi pi-download ml-2\" [class.animate-spin]=\"loading\"></i>\r\n {{ getExportButtonText() }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n @if(showFilters){\r\n<p-drawer\r\n [(visible)]=\"showFilters\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\"\r\n>\r\n <!-- Entire form wrapper -->\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); showFilters=false\" class=\"flex flex-col flex-1\">\r\n <!-- Scrollable Form -->\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\"\r\n >\r\n </formly-form>\r\n </div>\r\n\r\n </form>\r\n <!-- Action Buttons -->\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); showFilters=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); showFilters=false\"\r\n >\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n</p-drawer>\r\n\r\n }\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i4.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "directive", type: i5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: SelectModule }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "component", type: i6.RadioButton, selector: "p-radioButton, p-radiobutton, p-radio-button", inputs: ["value", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "styleClass", "autofocus", "binary", "variant", "size"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i7.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "ngmodule", type: DividerModule }, { kind: "ngmodule", type: TabsModule }, { kind: "component", type: i8.Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: i8.TabPanels, selector: "p-tabpanels" }, { kind: "component", type: i8.TabPanel, selector: "p-tabpanel", inputs: ["value"], outputs: ["valueChange"] }, { kind: "component", type: i8.TabList, selector: "p-tablist" }, { kind: "component", type: i8.Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: i9.LegacyFormlyForm, selector: "formly-form" }, { kind: "ngmodule", type: DynamicDialogModule }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i10.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "pipe", type: i11.TranslatePipe, name: "translate" }] });
|
|
506
|
+
cleanHtmlContent(html) {
|
|
507
|
+
return html
|
|
508
|
+
.replace(/\\r\\n/g, '\n')
|
|
509
|
+
.replace(/\\"/g, '"')
|
|
510
|
+
.replace(/\\t/g, ' ')
|
|
511
|
+
.trim();
|
|
512
|
+
}
|
|
513
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GenericReportComponent, deps: [{ token: i1$1.DynamicDialogRef }, { token: i1$1.DynamicDialogConfig }], target: i0.ɵɵFactoryTarget.Component });
|
|
514
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.8", type: GenericReportComponent, isStandalone: true, selector: "app-generic-report", inputs: { filterFields: "filterFields", enableQueryBuilder: "enableQueryBuilder", localExport: "localExport", queryString: "queryString", apiName: "apiName", model: "model" }, providers: [DialogService, RestService], viewQueries: [{ propertyName: "previewContainer", first: true, predicate: ["previewContainer"], descendants: true }], ngImport: i0, template: "<!-- class=\"flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg max-w-6xl mx-auto\" -->\r\n<div >\r\n <!-- Content -->\r\n <div class=\"flex-1 overflow-hidden p-2\">\r\n\r\n <!-- Preview Actions -->\r\n <div class=\"flex justify-between items-center mb-6 p-2 bg-white rounded-lg\">\r\n <h3 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'REPORT' | translate }}\r\n </h3>\r\n <div class=\"flex gap-2\">\r\n <!-- Filters Button -->\r\n <button\r\n type=\"button\"\r\n (click)=\"showFilters = !showFilters\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [pTooltip]=\"'SEARCH_FILTERS' | translate\">\r\n <i class=\"pi pi-filter\"></i>\r\n <span *ngIf=\"filterCount > 0\" class=\"ml-2 bg-blue-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center\">\r\n {{ filterCount }}\r\n </span>\r\n </button>\r\n\r\n <!-- Refresh Preview -->\r\n <button\r\n (click)=\"generatePreview()\"\r\n [disabled]=\"loading\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors\"\r\n [pTooltip]=\"'REFRESH' | translate\">\r\n <i class=\"pi pi-refresh mr-2 ml-2\" [class.animate-spin]=\"loading\"></i>\r\n {{ 'REFRESH' | translate }}\r\n </button>\r\n\r\n <!-- Print Button -->\r\n <button\r\n *ngIf=\"exportType === 4 || exportType === 1 || exportType === 2\"\r\n (click)=\"print()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [pTooltip]=\"'PRINT' | translate\">\r\n <i class=\"pi pi-print mr-2 ml-2\"></i>\r\n {{ 'PRINT' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div #previewContainer class=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg\">\r\n <!-- HTML Export Preview (Iframe) -->\r\n <div *ngIf=\"showHtmlInIframe && htmlExportContent || showPdfModal\" class=\"html-export-preview\">\r\n <iframe\r\n id=\"reportIframe\"\r\n class=\"w-full border border-gray-300 dark:border-gray-600 rounded-b-lg\"\r\n [style.height]=\"'600px'\"\r\n title=\"HTML Export Preview\"\r\n [src]=\"currentPdfUrl\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n frameborder=\"0\"\r\n allowfullscreen\r\n\r\n >\r\n <!-- allowfullscreen -->\r\n </iframe>\r\n </div>\r\n <!-- <app-pdf-modal\r\n *ngIf=\"showPdfModal\"\r\n [pdfUrl]=\"currentPdfUrl\"\r\n [fileName]=\"currentFileName\"\r\n (closed)=\"onPdfModalClose()\"\r\n (downloadRequested)=\"onPdfDownload()\">\r\n</app-pdf-modal> -->\r\n\r\n <!-- Regular Preview Table -->\r\n <!-- <div *ngIf=\"!showHtmlInIframe\" class=\"p-4\">\r\n <p-table\r\n [value]=\"previewData\"\r\n [columns]=\"previewColumns\"\r\n [paginator]=\"true\"\r\n [rows]=\"10\"\r\n [showCurrentPageReport]=\"true\"\r\n currentPageReportTemplate=\"Showing {first} to {last} of {totalRecords} entries\"\r\n styleClass=\"p-datatable-sm\">\r\n <ng-template pTemplate=\"header\">\r\n <tr>\r\n <th *ngFor=\"let col of previewColumns\" class=\"text-left\">\r\n {{ col.header }}\r\n </th>\r\n </tr>\r\n </ng-template>\r\n <ng-template pTemplate=\"body\" let-rowData>\r\n <tr>\r\n <td *ngFor=\"let col of previewColumns\" class=\"text-left\">\r\n {{ rowData[col.field] }}\r\n </td>\r\n </tr>\r\n </ng-template>\r\n <ng-template pTemplate=\"emptymessage\">\r\n <tr>\r\n <td [attr.colspan]=\"previewColumns.length\" class=\"text-center py-4\">\r\n <div class=\"text-center py-8\">\r\n <i class=\"pi pi-inbox text-4xl text-gray-400 dark:text-gray-500 mb-4\"></i>\r\n <p class=\"text-gray-500 dark:text-gray-400\">{{ 'NO_PREVIEW_DATA' | translate }}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n </div> -->\r\n </div>\r\n\r\n <!-- <div class=\"mt-4 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\">\r\n <p class=\"text-sm text-green-700 dark:text-green-300\">\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n {{ 'PREVIEW_INFO' | translate }}\r\n </p>\r\n </div> -->\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"border-t border-gray-200 dark:border-gray-700 px-2 py-2 bg-gray-50 dark:bg-gray-800\">\r\n <div class=\"flex justify-between items-center\">\r\n <button\r\n type=\"button\"\r\n (click)=\"onReset()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors\"\r\n [disabled]=\"loading\">\r\n <i class=\"pi pi-refresh mr-2\"></i>\r\n {{ 'RESET' | translate }}\r\n </button>\r\n\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"ref?.close()\"\r\n class=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [disabled]=\"loading\">\r\n {{ 'CANCEL' | translate }}\r\n </button>\r\n\r\n <!-- SplitButton for Export -->\r\n <!-- || previewData.length === 0 -->\r\n <p-splitButton\r\n [label]=\"getExportButtonText()\"\r\n [icon]=\"getCurrentExportTypeIcon()\"\r\n [model]=\"exportMenuItems\"\r\n (onClick)=\"onExport()\"\r\n [disabled]=\"loading\"\r\n styleClass=\"p-button-primary\">\r\n </p-splitButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Drawer -->\r\n @if(showFilters){\r\n <p-drawer\r\n [(visible)]=\"showFilters\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\">\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); showFilters=false\" class=\"flex flex-col flex-1\">\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\">\r\n </formly-form>\r\n </div>\r\n </form>\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); showFilters=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); showFilters=false\">\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </p-drawer>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i2.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "directive", type: i5.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: RadioButtonModule }, { kind: "ngmodule", type: CheckboxModule }, { kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i6.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "ngmodule", type: TableModule }, { kind: "ngmodule", type: SplitButtonModule }, { kind: "component", type: i7.SplitButton, selector: "p-splitbutton, p-splitButton, p-split-button", inputs: ["model", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "icon", "iconPos", "label", "tooltip", "tooltipOptions", "styleClass", "menuStyle", "menuStyleClass", "dropdownIcon", "appendTo", "dir", "expandAriaLabel", "showTransitionOptions", "hideTransitionOptions", "buttonProps", "menuButtonProps", "autofocus", "disabled", "tabindex", "menuButtonDisabled", "buttonDisabled"], outputs: ["onClick", "onMenuHide", "onMenuShow", "onDropdownClick"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i8.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo"] }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }] });
|
|
444
515
|
}
|
|
445
516
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: GenericReportComponent, decorators: [{
|
|
446
517
|
type: Component,
|
|
447
|
-
args: [{ selector: 'app-generic-report',
|
|
518
|
+
args: [{ selector: 'app-generic-report', imports: [
|
|
448
519
|
CommonModule,
|
|
449
520
|
ReactiveFormsModule,
|
|
450
521
|
FormsModule,
|
|
451
522
|
TranslateModule,
|
|
452
523
|
ButtonModule,
|
|
453
524
|
DialogModule,
|
|
454
|
-
SelectModule,
|
|
455
|
-
MultiSelectModule,
|
|
456
525
|
InputTextModule,
|
|
457
526
|
RadioButtonModule,
|
|
458
527
|
CheckboxModule,
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
], template: "\r\n <div class=\"flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg max-w-6xl mx-auto\">\r\n <!-- Header -->\r\n <!-- <div class=\"flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700\">\r\n <h2 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'EXPORT_DATA' | translate }}\r\n </h2>\r\n <button\r\n (click)=\"ref?.close()\"\r\n class=\"p-1 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\r\n aria-label=\"Close\">\r\n <i class=\"pi pi-times text-gray-500 dark:text-gray-400\"></i>\r\n </button>\r\n </div> -->\r\n\r\n <!-- Content -->\r\n <div class=\"flex-1 overflow-hidden\">\r\n <p-tabs [value]=\"activeTabIndex\">\r\n <!-- Configuration Tab -->\r\n <p-tablist>\r\n <p-tab value=\"0\">{{'CONFIGURATION' | translate}}</p-tab>\r\n <p-tab value=\"1\">{{'PREVIEW' | translate}}</p-tab>\r\n </p-tablist>\r\n <p-tabpanels>\r\n <p-tabpanel value=\"0\">\r\n <div class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Left Column - Export Settings -->\r\n <div class=\"space-y-6\">\r\n <!-- File Name -->\r\n <div class=\"space-y-2\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'FILE_NAME' | translate }}\r\n </label>\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"fileName\"\r\n class=\"w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500\"\r\n [placeholder]=\"'ENTER_FILE_NAME' | translate\">\r\n </div>\r\n\r\n <!-- Export Type -->\r\n <div class=\"space-y-3\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'EXPORT_FORMAT' | translate }}\r\n </label>\r\n <div class=\"grid grid-cols-2 gap-3\">\r\n <div *ngFor=\"let type of exportTypes\" class=\"flex items-center\">\r\n <p-radioButton\r\n [name]=\"'exportType'\"\r\n [value]=\"type.value\"\r\n [(ngModel)]=\"exportType\"\r\n [inputId]=\"`${type.value}`\"\r\n (onClick)=\"onExportTypeChange(type.value)\"\r\n class=\"mr-3\">\r\n </p-radioButton>\r\n <label [for]=\"type.value\" class=\"flex items-center cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n <i [class]=\"type.icon + ' mr-2'\"></i>\r\n {{ type.label | translate }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Section -->\r\n <div class=\"space-y-3\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SEARCH_FILTERS' | translate }}\r\n </label>\r\n <button\r\n type=\"button\"\r\n (click)=\"showFilters = !showFilters\"\r\n class=\"text-sm text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ showFilters ? ('HIDE_FILTERS' | translate) : ('SHOW_FILTERS' | translate) }}\r\n </button>\r\n </div>\r\n\r\n <!-- <div *ngIf=\"showFilters\" class=\"space-y-4 p-4 border border-gray-200 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\">\r\n </formly-form>\r\n </div> -->\r\n </div>\r\n </div>\r\n\r\n <!-- Right Column - Column Selection -->\r\n <div class=\"space-y-4\">\r\n <div class=\"flex items-center justify-between\">\r\n <label class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\">\r\n {{ 'SELECT_COLUMNS' | translate }}\r\n </label>\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"selectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'SELECT_ALL' | translate }}\r\n </button>\r\n <button\r\n type=\"button\"\r\n (click)=\"deselectAllColumns()\"\r\n class=\"text-xs text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'DESELECT_ALL' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"max-h-80 overflow-y-auto border border-gray-200 dark:border-gray-700 rounded-lg\">\r\n <div *ngFor=\"let column of availableColumns\" class=\"flex items-center p-3 border-b border-gray-100 dark:border-gray-600 last:border-b-0 hover:bg-gray-50 dark:hover:bg-gray-700\">\r\n <p-checkbox\r\n [binary]=\"true\"\r\n [(ngModel)]=\"column.selected\"\r\n [inputId]=\"column.key\"\r\n (onChange)=\"onColumnToggle(column)\"\r\n class=\"mr-3\">\r\n </p-checkbox>\r\n <label [for]=\"column.key\" class=\"flex-1 cursor-pointer text-sm text-gray-700 dark:text-gray-300\">\r\n {{ column.displayName }}\r\n </label>\r\n <div *ngIf=\"column.selected\" class=\"flex items-center gap-2\">\r\n <input\r\n type=\"text\"\r\n [(ngModel)]=\"column.customName\"\r\n (blur)=\"onCustomNameChange(column)\"\r\n [placeholder]=\"column.displayName\"\r\n class=\"text-xs p-1 border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-800 text-gray-900 dark:text-white w-32\"\r\n [title]=\"'CUSTOM_COLUMN_NAME' | translate\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Selected Columns Summary -->\r\n <div *ngIf=\"selectedColumns.length > 0\" class=\"p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg\">\r\n <p class=\"text-sm text-blue-700 dark:text-blue-300\">\r\n {{ 'SELECTED_COLUMNS_COUNT' | translate: { count: selectedColumns.length } }}\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n <!-- Preview Tab -->\r\n <!-- [disabled]=\"selectedColumns.length === 0\" -->\r\n <p-tabpanel value=\"1\" >\r\n <div class=\"p-4 max-h-[60vh] overflow-y-auto\">\r\n <!-- Preview Actions -->\r\n <div class=\"flex justify-between items-center mb-4\">\r\n <h3 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'REPORT_PREVIEW' | translate }}\r\n </h3>\r\n <div class=\"flex gap-2\">\r\n <button\r\n *ngIf=\"exportType === 1 || exportType === 4\"\r\n (click)=\"printPreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\">\r\n <i class=\"pi pi-print mr-2\"></i>\r\n {{ 'PRINT' | translate }}\r\n </button>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 transition-colors\">\r\n <i class=\"pi pi-refresh mr-2\"></i>\r\n {{ 'REFRESH_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div #previewContainer class=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-6\">\r\n <!-- Report Header -->\r\n <div class=\"text-center mb-6 border-b border-gray-200 dark:border-gray-700 pb-4\">\r\n <h1 class=\"text-2xl font-bold text-gray-900 dark:text-white\">{{ fileName }}</h1>\r\n <p class=\"text-gray-600 dark:text-gray-400 mt-2\">\r\n {{ 'GENERATED_ON' | translate }}: {{ currentDate | date:'medium' }}\r\n </p>\r\n </div>\r\n\r\n <!-- Report Table -->\r\n <div class=\"overflow-x-auto\">\r\n <table class=\"min-w-full divide-y divide-gray-200 dark:divide-gray-700\">\r\n <thead class=\"bg-gray-50 dark:bg-gray-700\">\r\n <tr>\r\n <th\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider border border-gray-200 dark:border-gray-600\">\r\n {{ column.customName || column.displayName }}\r\n </th>\r\n </tr>\r\n </thead>\r\n <tbody class=\"bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700\">\r\n <tr *ngFor=\"let row of previewData; let i = index\"\r\n [class.bg-gray-50]=\"i % 2 === 0\"\r\n [class.dark:bg-gray-900]=\"i % 2 === 0\">\r\n <td\r\n *ngFor=\"let column of selectedColumns\"\r\n class=\"px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-white border border-gray-200 dark:border-gray-600\">\r\n {{ getPreviewValue(row, column.key) }}\r\n </td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <!-- Empty State -->\r\n <div *ngIf=\"previewData.length === 0\" class=\"text-center py-8\">\r\n <i class=\"pi pi-inbox text-4xl text-gray-400 dark:text-gray-500 mb-4\"></i>\r\n <p class=\"text-gray-500 dark:text-gray-400\">{{ 'NO_PREVIEW_DATA' | translate }}</p>\r\n <button\r\n (click)=\"generatePreview()\"\r\n class=\"mt-4 px-4 py-2 text-sm font-medium text-blue-600 dark:text-blue-400 hover:underline\">\r\n {{ 'GENERATE_PREVIEW' | translate }}\r\n </button>\r\n </div>\r\n\r\n <!-- Report Footer -->\r\n <div class=\"text-center mt-6 border-t border-gray-200 dark:border-gray-700 pt-4\">\r\n <p class=\"text-sm text-gray-500 dark:text-gray-400\">\r\n {{ 'PAGE' | translate }} 1 of 1\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Info -->\r\n <div class=\"mt-4 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\">\r\n <p class=\"text-sm text-green-700 dark:text-green-300\">\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n {{ 'PREVIEW_INFO' | translate }}\r\n </p>\r\n </div>\r\n </div>\r\n </p-tabpanel>\r\n\r\n </p-tabpanels>\r\n </p-tabs>\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"border-t border-gray-200 dark:border-gray-700 px-6 py-4 bg-gray-50 dark:bg-gray-800\">\r\n <div class=\"flex justify-between items-center\">\r\n <button\r\n type=\"button\"\r\n (click)=\"onReset()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors\"\r\n [disabled]=\"loading\">\r\n <i class=\"pi pi-refresh ml-2\"></i>\r\n {{ 'RESET' | translate }}\r\n </button>\r\n\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"ref?.close()\"\r\n class=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [disabled]=\"loading\">\r\n {{ 'CANCEL' | translate }}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"onExport()\"\r\n [disabled]=\"loading || selectedColumns.length === 0\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors\">\r\n <i class=\"pi pi-download ml-2\" [class.animate-spin]=\"loading\"></i>\r\n {{ getExportButtonText() }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n @if(showFilters){\r\n<p-drawer\r\n [(visible)]=\"showFilters\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\"\r\n>\r\n <!-- Entire form wrapper -->\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); showFilters=false\" class=\"flex flex-col flex-1\">\r\n <!-- Scrollable Form -->\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\"\r\n >\r\n </formly-form>\r\n </div>\r\n\r\n </form>\r\n <!-- Action Buttons -->\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); showFilters=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); showFilters=false\"\r\n >\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n</p-drawer>\r\n\r\n }\r\n" }]
|
|
466
|
-
}], ctorParameters: () => [{ type: i1.DynamicDialogRef }, { type: i1.DynamicDialogConfig }], propDecorators: { previewContainer: [{
|
|
528
|
+
DrawerModule,
|
|
529
|
+
FormlyForm,
|
|
530
|
+
TableModule,
|
|
531
|
+
SplitButtonModule,
|
|
532
|
+
TooltipModule,
|
|
533
|
+
], providers: [DialogService, RestService], template: "<!-- class=\"flex flex-col h-full bg-white dark:bg-gray-900 rounded-lg max-w-6xl mx-auto\" -->\r\n<div >\r\n <!-- Content -->\r\n <div class=\"flex-1 overflow-hidden p-2\">\r\n\r\n <!-- Preview Actions -->\r\n <div class=\"flex justify-between items-center mb-6 p-2 bg-white rounded-lg\">\r\n <h3 class=\"text-lg font-semibold text-gray-900 dark:text-white\">\r\n {{ 'REPORT' | translate }}\r\n </h3>\r\n <div class=\"flex gap-2\">\r\n <!-- Filters Button -->\r\n <button\r\n type=\"button\"\r\n (click)=\"showFilters = !showFilters\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [pTooltip]=\"'SEARCH_FILTERS' | translate\">\r\n <i class=\"pi pi-filter\"></i>\r\n <span *ngIf=\"filterCount > 0\" class=\"ml-2 bg-blue-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center\">\r\n {{ filterCount }}\r\n </span>\r\n </button>\r\n\r\n <!-- Refresh Preview -->\r\n <button\r\n (click)=\"generatePreview()\"\r\n [disabled]=\"loading\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors\"\r\n [pTooltip]=\"'REFRESH' | translate\">\r\n <i class=\"pi pi-refresh mr-2 ml-2\" [class.animate-spin]=\"loading\"></i>\r\n {{ 'REFRESH' | translate }}\r\n </button>\r\n\r\n <!-- Print Button -->\r\n <button\r\n *ngIf=\"exportType === 4 || exportType === 1 || exportType === 2\"\r\n (click)=\"print()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [pTooltip]=\"'PRINT' | translate\">\r\n <i class=\"pi pi-print mr-2 ml-2\"></i>\r\n {{ 'PRINT' | translate }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Preview Content -->\r\n <div #previewContainer class=\"bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg\">\r\n <!-- HTML Export Preview (Iframe) -->\r\n <div *ngIf=\"showHtmlInIframe && htmlExportContent || showPdfModal\" class=\"html-export-preview\">\r\n <iframe\r\n id=\"reportIframe\"\r\n class=\"w-full border border-gray-300 dark:border-gray-600 rounded-b-lg\"\r\n [style.height]=\"'600px'\"\r\n title=\"HTML Export Preview\"\r\n [src]=\"currentPdfUrl\"\r\n width=\"100%\"\r\n height=\"100%\"\r\n frameborder=\"0\"\r\n allowfullscreen\r\n\r\n >\r\n <!-- allowfullscreen -->\r\n </iframe>\r\n </div>\r\n <!-- <app-pdf-modal\r\n *ngIf=\"showPdfModal\"\r\n [pdfUrl]=\"currentPdfUrl\"\r\n [fileName]=\"currentFileName\"\r\n (closed)=\"onPdfModalClose()\"\r\n (downloadRequested)=\"onPdfDownload()\">\r\n</app-pdf-modal> -->\r\n\r\n <!-- Regular Preview Table -->\r\n <!-- <div *ngIf=\"!showHtmlInIframe\" class=\"p-4\">\r\n <p-table\r\n [value]=\"previewData\"\r\n [columns]=\"previewColumns\"\r\n [paginator]=\"true\"\r\n [rows]=\"10\"\r\n [showCurrentPageReport]=\"true\"\r\n currentPageReportTemplate=\"Showing {first} to {last} of {totalRecords} entries\"\r\n styleClass=\"p-datatable-sm\">\r\n <ng-template pTemplate=\"header\">\r\n <tr>\r\n <th *ngFor=\"let col of previewColumns\" class=\"text-left\">\r\n {{ col.header }}\r\n </th>\r\n </tr>\r\n </ng-template>\r\n <ng-template pTemplate=\"body\" let-rowData>\r\n <tr>\r\n <td *ngFor=\"let col of previewColumns\" class=\"text-left\">\r\n {{ rowData[col.field] }}\r\n </td>\r\n </tr>\r\n </ng-template>\r\n <ng-template pTemplate=\"emptymessage\">\r\n <tr>\r\n <td [attr.colspan]=\"previewColumns.length\" class=\"text-center py-4\">\r\n <div class=\"text-center py-8\">\r\n <i class=\"pi pi-inbox text-4xl text-gray-400 dark:text-gray-500 mb-4\"></i>\r\n <p class=\"text-gray-500 dark:text-gray-400\">{{ 'NO_PREVIEW_DATA' | translate }}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n </div> -->\r\n </div>\r\n\r\n <!-- <div class=\"mt-4 p-3 bg-green-50 dark:bg-green-900/20 rounded-lg\">\r\n <p class=\"text-sm text-green-700 dark:text-green-300\">\r\n <i class=\"pi pi-info-circle mr-2\"></i>\r\n {{ 'PREVIEW_INFO' | translate }}\r\n </p>\r\n </div> -->\r\n </div>\r\n\r\n <!-- Footer -->\r\n <div class=\"border-t border-gray-200 dark:border-gray-700 px-2 py-2 bg-gray-50 dark:bg-gray-800\">\r\n <div class=\"flex justify-between items-center\">\r\n <button\r\n type=\"button\"\r\n (click)=\"onReset()\"\r\n class=\"flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors\"\r\n [disabled]=\"loading\">\r\n <i class=\"pi pi-refresh mr-2\"></i>\r\n {{ 'RESET' | translate }}\r\n </button>\r\n\r\n <div class=\"flex gap-2\">\r\n <button\r\n type=\"button\"\r\n (click)=\"ref?.close()\"\r\n class=\"px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors\"\r\n [disabled]=\"loading\">\r\n {{ 'CANCEL' | translate }}\r\n </button>\r\n\r\n <!-- SplitButton for Export -->\r\n <!-- || previewData.length === 0 -->\r\n <p-splitButton\r\n [label]=\"getExportButtonText()\"\r\n [icon]=\"getCurrentExportTypeIcon()\"\r\n [model]=\"exportMenuItems\"\r\n (onClick)=\"onExport()\"\r\n [disabled]=\"loading\"\r\n styleClass=\"p-button-primary\">\r\n </p-splitButton>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Filters Drawer -->\r\n @if(showFilters){\r\n <p-drawer\r\n [(visible)]=\"showFilters\"\r\n position=\"right\"\r\n [styleClass]=\"'!w-full md:!w-80 lg:!w-[40rem] !h-full' \"\r\n [modal]=\"true\"\r\n [dismissible]=\"true\"\r\n styleClass=\"p-4 w-full max-w-md max-h-[90vh] flex flex-col\">\r\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit(); showFilters=false\" class=\"flex flex-col flex-1\">\r\n <div class=\"flex-1 overflow-auto\">\r\n <formly-form\r\n [form]=\"form\"\r\n [fields]=\"fields_\"\r\n [model]=\"model\"\r\n [options]=\"options\">\r\n </formly-form>\r\n </div>\r\n </form>\r\n <ng-template pTemplate=\"footer\">\r\n <div class=\"flex justify-end mt-2 space-x-2 flex-none\">\r\n <button\r\n type=\"submit\"\r\n pButton size=\"small\"\r\n (click)=\" onSubmit(); showFilters=false\"\r\n label=\"{{ 'SEARCH' | translate }}\">\r\n </button>\r\n <button\r\n type=\"button\"\r\n pButton\r\n size=\"small\"\r\n class=\"p-button-text\"\r\n (click)=\"onReset(); showFilters=false\">\r\n {{ 'CLEAR' | translate }}\r\n </button>\r\n </div>\r\n </ng-template>\r\n </p-drawer>\r\n }\r\n</div>\r\n" }]
|
|
534
|
+
}], ctorParameters: () => [{ type: i1$1.DynamicDialogRef }, { type: i1$1.DynamicDialogConfig }], propDecorators: { previewContainer: [{
|
|
467
535
|
type: ViewChild,
|
|
468
536
|
args: ['previewContainer']
|
|
469
537
|
}], filterFields: [{
|
|
@@ -484,5 +552,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImpor
|
|
|
484
552
|
* Generated bundle index. Do not edit.
|
|
485
553
|
*/
|
|
486
554
|
|
|
487
|
-
export { ExportType, GenericReportComponent, GenericReportModule };
|
|
555
|
+
export { ExportType, GenericReportComponent, GenericReportModule, ReportNameDialogComponent };
|
|
488
556
|
//# sourceMappingURL=elite.framework-ng.ui.core-generic-report.mjs.map
|