@elite.framework/ng.ui.core 1.0.3 → 1.0.5
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/excel-import/README.md +3 -0
- package/excel-import/index.d.ts +69 -0
- package/fesm2022/elite.framework-ng.ui.core-excel-import.mjs +568 -0
- package/fesm2022/elite.framework-ng.ui.core-excel-import.mjs.map +1 -0
- package/fesm2022/elite.framework-ng.ui.core-generic-crud-table.mjs +5 -2
- package/fesm2022/elite.framework-ng.ui.core-generic-crud-table.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.ui.core-generic-table.mjs +5 -2
- package/fesm2022/elite.framework-ng.ui.core-generic-table.mjs.map +1 -1
- package/fesm2022/elite.framework-ng.ui.core-label-type.mjs +7 -3
- package/fesm2022/elite.framework-ng.ui.core-label-type.mjs.map +1 -1
- package/generic-crud-table/index.d.ts +2 -1
- package/generic-table/index.d.ts +2 -1
- package/package.json +25 -21
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { OnDestroy, EventEmitter } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/common';
|
|
4
|
+
import * as _elite_framework_ng_core_tokens from '@elite.framework/ng.core/tokens';
|
|
5
|
+
import { FormGroup } from '@angular/forms';
|
|
6
|
+
import { FormlyFieldConfig } from '@ngx-formly/core';
|
|
7
|
+
import { DynamicDialogRef, DynamicDialogConfig } from 'primeng/dynamicdialog';
|
|
8
|
+
|
|
9
|
+
declare class ExcelImportModule {
|
|
10
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ExcelImportModule, never>;
|
|
11
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<ExcelImportModule, never, [typeof i1.CommonModule], never>;
|
|
12
|
+
static ɵinj: i0.ɵɵInjectorDeclaration<ExcelImportModule>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ExcelImportConfig {
|
|
16
|
+
templateUrl: string;
|
|
17
|
+
apiUrl: string;
|
|
18
|
+
apiName: string;
|
|
19
|
+
mappingFields: FormlyFieldConfig[];
|
|
20
|
+
acceptedFileTypes?: string;
|
|
21
|
+
maxFileSize?: number;
|
|
22
|
+
steps?: {
|
|
23
|
+
label: string;
|
|
24
|
+
}[];
|
|
25
|
+
}
|
|
26
|
+
declare class ExcelImportComponent implements OnDestroy {
|
|
27
|
+
ref: DynamicDialogRef;
|
|
28
|
+
dialogConfig: DynamicDialogConfig;
|
|
29
|
+
config: ExcelImportConfig;
|
|
30
|
+
importComplete: EventEmitter<any>;
|
|
31
|
+
importError: EventEmitter<Error>;
|
|
32
|
+
form: FormGroup;
|
|
33
|
+
model: any;
|
|
34
|
+
loading: boolean;
|
|
35
|
+
uploadedFileName: string | null;
|
|
36
|
+
uploadError: string | null;
|
|
37
|
+
excelHeaders: string[];
|
|
38
|
+
private destroy$;
|
|
39
|
+
private restService;
|
|
40
|
+
private messageService;
|
|
41
|
+
private translateService;
|
|
42
|
+
private fb;
|
|
43
|
+
env: _elite_framework_ng_core_tokens.EnvironmentConfig;
|
|
44
|
+
steps: {
|
|
45
|
+
label: any;
|
|
46
|
+
}[];
|
|
47
|
+
activeStep: number;
|
|
48
|
+
mappingFields: FormlyFieldConfig[];
|
|
49
|
+
constructor(ref: DynamicDialogRef, dialogConfig: DynamicDialogConfig);
|
|
50
|
+
ngOnInit(): void;
|
|
51
|
+
nextStep(): void;
|
|
52
|
+
prevStep(): void;
|
|
53
|
+
canProceed(): boolean;
|
|
54
|
+
getModelValue(field: FormlyFieldConfig, model: any): any;
|
|
55
|
+
private fileContent;
|
|
56
|
+
onFileUpload(event: any): void;
|
|
57
|
+
private arrayBufferToBase64;
|
|
58
|
+
private getFileExtension;
|
|
59
|
+
onSubmit(): void;
|
|
60
|
+
private clearFileUpload;
|
|
61
|
+
private initializeForm;
|
|
62
|
+
onCancel(): void;
|
|
63
|
+
ngOnDestroy(): void;
|
|
64
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ExcelImportComponent, never>;
|
|
65
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ExcelImportComponent, "app-excel-import", never, { "config": { "alias": "config"; "required": false; }; }, { "importComplete": "importComplete"; "importError": "importError"; }, never, never, true, never>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { ExcelImportComponent, ExcelImportModule };
|
|
69
|
+
export type { ExcelImportConfig };
|
|
@@ -0,0 +1,568 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { NgModule, EventEmitter, inject, Output, Input, Component } from '@angular/core';
|
|
3
|
+
import * as i2 from '@angular/common';
|
|
4
|
+
import { CommonModule } from '@angular/common';
|
|
5
|
+
import * as i3 from '@angular/forms';
|
|
6
|
+
import { FormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
7
|
+
import { RestService } from '@elite.framework/ng.core/services';
|
|
8
|
+
import { FormlyForm } from '@ngx-formly/core';
|
|
9
|
+
import * as i8 from '@ngx-translate/core';
|
|
10
|
+
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
11
|
+
import * as i4 from 'primeng/button';
|
|
12
|
+
import { ButtonModule } from 'primeng/button';
|
|
13
|
+
import * as i1 from 'primeng/dynamicdialog';
|
|
14
|
+
import { Subject, takeUntil } from 'rxjs';
|
|
15
|
+
import * as i5 from 'primeng/fileupload';
|
|
16
|
+
import { FileUploadModule } from 'primeng/fileupload';
|
|
17
|
+
import * as i6 from 'primeng/steps';
|
|
18
|
+
import { StepsModule } from 'primeng/steps';
|
|
19
|
+
import { MessageService } from 'primeng/api';
|
|
20
|
+
import * as i7 from 'primeng/toast';
|
|
21
|
+
import { ToastModule } from 'primeng/toast';
|
|
22
|
+
import { read, utils } from 'xlsx';
|
|
23
|
+
import { ENVIRONMENT } from '@elite.framework/ng.core/tokens';
|
|
24
|
+
|
|
25
|
+
class ExcelImportModule {
|
|
26
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExcelImportModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
27
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.8", ngImport: i0, type: ExcelImportModule, imports: [CommonModule] });
|
|
28
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExcelImportModule, imports: [CommonModule] });
|
|
29
|
+
}
|
|
30
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExcelImportModule, decorators: [{
|
|
31
|
+
type: NgModule,
|
|
32
|
+
args: [{
|
|
33
|
+
imports: [CommonModule],
|
|
34
|
+
}]
|
|
35
|
+
}] });
|
|
36
|
+
|
|
37
|
+
class ExcelImportComponent {
|
|
38
|
+
ref;
|
|
39
|
+
dialogConfig;
|
|
40
|
+
config;
|
|
41
|
+
importComplete = new EventEmitter();
|
|
42
|
+
importError = new EventEmitter();
|
|
43
|
+
form;
|
|
44
|
+
model = {};
|
|
45
|
+
loading = false;
|
|
46
|
+
uploadedFileName = null;
|
|
47
|
+
uploadError = null;
|
|
48
|
+
excelHeaders = [];
|
|
49
|
+
destroy$ = new Subject();
|
|
50
|
+
restService = inject(RestService);
|
|
51
|
+
messageService = inject(MessageService);
|
|
52
|
+
translateService = inject(TranslateService);
|
|
53
|
+
fb = inject(FormBuilder);
|
|
54
|
+
env = inject(ENVIRONMENT);
|
|
55
|
+
steps = [
|
|
56
|
+
{ label: this.translateService.instant('uploadFile') },
|
|
57
|
+
{ label: this.translateService.instant('columnMapping') },
|
|
58
|
+
{ label: this.translateService.instant('review') },
|
|
59
|
+
];
|
|
60
|
+
activeStep = 0;
|
|
61
|
+
mappingFields = [];
|
|
62
|
+
constructor(ref, dialogConfig) {
|
|
63
|
+
this.ref = ref;
|
|
64
|
+
this.dialogConfig = dialogConfig;
|
|
65
|
+
this.form = this.fb.group({});
|
|
66
|
+
// Initialize from dialog config if provided
|
|
67
|
+
if (this.dialogConfig?.data?.config) {
|
|
68
|
+
this.config = this.dialogConfig.data.config;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
ngOnInit() {
|
|
72
|
+
if (!this.config) {
|
|
73
|
+
throw new Error('ExcelImportConfig is required');
|
|
74
|
+
}
|
|
75
|
+
this.mappingFields = this.config.mappingFields.map(field => ({
|
|
76
|
+
...field,
|
|
77
|
+
props: {
|
|
78
|
+
...field.props,
|
|
79
|
+
options: []
|
|
80
|
+
}
|
|
81
|
+
}));
|
|
82
|
+
this.steps = this.config.steps || this.steps;
|
|
83
|
+
}
|
|
84
|
+
nextStep() {
|
|
85
|
+
if (this.activeStep < 2)
|
|
86
|
+
this.activeStep++;
|
|
87
|
+
}
|
|
88
|
+
prevStep() {
|
|
89
|
+
if (this.activeStep > 0)
|
|
90
|
+
this.activeStep--;
|
|
91
|
+
}
|
|
92
|
+
canProceed() {
|
|
93
|
+
switch (this.activeStep) {
|
|
94
|
+
case 0:
|
|
95
|
+
return !!this.uploadedFileName;
|
|
96
|
+
case 1:
|
|
97
|
+
return this.form.valid;
|
|
98
|
+
case 2:
|
|
99
|
+
return true;
|
|
100
|
+
default:
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
getModelValue(field, model) {
|
|
105
|
+
if (!field.key)
|
|
106
|
+
return null;
|
|
107
|
+
if (Array.isArray(field.key)) {
|
|
108
|
+
// Walk through nested keys like ['address', 'street']
|
|
109
|
+
return field.key.reduce((acc, k) => (acc ? acc[k] : undefined), model);
|
|
110
|
+
}
|
|
111
|
+
return model[field.key];
|
|
112
|
+
}
|
|
113
|
+
// Add this property to store the file content
|
|
114
|
+
fileContent = null;
|
|
115
|
+
// Update the onFileUpload method to store the file content
|
|
116
|
+
onFileUpload(event) {
|
|
117
|
+
this.uploadError = null;
|
|
118
|
+
const file = event.files[0];
|
|
119
|
+
if (!file) {
|
|
120
|
+
this.uploadError = 'noFileSelected';
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
// Validate file type
|
|
124
|
+
const validExtensions = ['.xlsx', '.xls', '.csv'];
|
|
125
|
+
const fileExtension = file.name.toLowerCase().substring(file.name.lastIndexOf('.'));
|
|
126
|
+
if (!validExtensions.includes(fileExtension)) {
|
|
127
|
+
this.uploadError = 'invalidFileType';
|
|
128
|
+
this.clearFileUpload(event);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
this.uploadedFileName = file.name;
|
|
132
|
+
const reader = new FileReader();
|
|
133
|
+
reader.onload = (e) => {
|
|
134
|
+
try {
|
|
135
|
+
const arrayBuffer = e.target?.result;
|
|
136
|
+
this.fileContent = arrayBuffer; // Store the file content
|
|
137
|
+
const data = new Uint8Array(arrayBuffer);
|
|
138
|
+
const workbook = read(data, { type: 'array' });
|
|
139
|
+
if (workbook.SheetNames.length === 0) {
|
|
140
|
+
this.uploadError = 'noSheetsFound';
|
|
141
|
+
this.clearFileUpload(event);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const sheetName = workbook.SheetNames[0];
|
|
145
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
146
|
+
const rows = utils.sheet_to_json(worksheet, { header: 1 });
|
|
147
|
+
if (rows.length === 0) {
|
|
148
|
+
this.uploadError = 'noDataFound';
|
|
149
|
+
this.clearFileUpload(event);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
this.excelHeaders = rows[0];
|
|
153
|
+
// Update mapping fields with header options
|
|
154
|
+
this.mappingFields.forEach(field => {
|
|
155
|
+
if (field.props) {
|
|
156
|
+
field.props.options = this.excelHeaders.map(h => ({
|
|
157
|
+
value: h,
|
|
158
|
+
label: h,
|
|
159
|
+
}));
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
// Initialize form with default values if not set
|
|
163
|
+
this.initializeForm();
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
console.error('Error processing Excel file:', error);
|
|
167
|
+
this.uploadError = 'fileProcessingError';
|
|
168
|
+
this.clearFileUpload(event);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
reader.onerror = (error) => {
|
|
172
|
+
console.error('File reading error:', error);
|
|
173
|
+
this.uploadError = 'fileReadError';
|
|
174
|
+
this.clearFileUpload(event);
|
|
175
|
+
};
|
|
176
|
+
reader.readAsArrayBuffer(file);
|
|
177
|
+
}
|
|
178
|
+
// Add this method to convert ArrayBuffer to base64
|
|
179
|
+
arrayBufferToBase64(buffer) {
|
|
180
|
+
const bytes = new Uint8Array(buffer);
|
|
181
|
+
let binary = '';
|
|
182
|
+
const len = bytes.byteLength;
|
|
183
|
+
for (let i = 0; i < len; i++) {
|
|
184
|
+
binary += String.fromCharCode(bytes[i]);
|
|
185
|
+
}
|
|
186
|
+
return window.btoa(binary);
|
|
187
|
+
}
|
|
188
|
+
// Add this method to get file extension
|
|
189
|
+
getFileExtension(filename) {
|
|
190
|
+
const index = filename.lastIndexOf('.');
|
|
191
|
+
return index !== -1 ? filename.slice(index) : '';
|
|
192
|
+
}
|
|
193
|
+
// Updated onSubmit method
|
|
194
|
+
onSubmit() {
|
|
195
|
+
if (this.form.invalid || !this.uploadedFileName || !this.fileContent) {
|
|
196
|
+
this.form.markAllAsTouched();
|
|
197
|
+
if (!this.fileContent) {
|
|
198
|
+
this.messageService.add({
|
|
199
|
+
severity: 'error',
|
|
200
|
+
summary: 'Error',
|
|
201
|
+
detail: 'File content is missing. Please upload the file again.'
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
this.loading = true;
|
|
207
|
+
// Convert file content to base64
|
|
208
|
+
let fileBase64;
|
|
209
|
+
try {
|
|
210
|
+
if (this.fileContent instanceof ArrayBuffer) {
|
|
211
|
+
fileBase64 = this.arrayBufferToBase64(this.fileContent);
|
|
212
|
+
}
|
|
213
|
+
else if (typeof this.fileContent === 'string') {
|
|
214
|
+
// If it's already a string (base64), use it directly
|
|
215
|
+
fileBase64 = this.fileContent;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
throw new Error('Unsupported file content type');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
this.loading = false;
|
|
223
|
+
console.error('Error converting file to base64:', error);
|
|
224
|
+
this.messageService.add({
|
|
225
|
+
severity: 'error',
|
|
226
|
+
summary: 'Error',
|
|
227
|
+
detail: 'Failed to process file content'
|
|
228
|
+
});
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const requestBody = {
|
|
232
|
+
fileName: this.uploadedFileName,
|
|
233
|
+
fileExtension: this.getFileExtension(this.uploadedFileName),
|
|
234
|
+
fileContent: fileBase64,
|
|
235
|
+
mappings: this.form.value,
|
|
236
|
+
headers: this.excelHeaders,
|
|
237
|
+
fileSize: this.fileContent instanceof ArrayBuffer ? this.fileContent.byteLength : 0
|
|
238
|
+
};
|
|
239
|
+
this.restService
|
|
240
|
+
.request({
|
|
241
|
+
method: 'POST',
|
|
242
|
+
url: this.config.apiUrl,
|
|
243
|
+
body: requestBody,
|
|
244
|
+
headers: {
|
|
245
|
+
'Content-Type': 'application/json'
|
|
246
|
+
}
|
|
247
|
+
}, { apiName: this.config.apiName })
|
|
248
|
+
.pipe(takeUntil(this.destroy$))
|
|
249
|
+
.subscribe({
|
|
250
|
+
next: (response) => {
|
|
251
|
+
this.loading = false;
|
|
252
|
+
this.messageService.add({
|
|
253
|
+
severity: 'success',
|
|
254
|
+
summary: 'Success',
|
|
255
|
+
detail: 'File imported successfully'
|
|
256
|
+
});
|
|
257
|
+
this.importComplete.emit(response);
|
|
258
|
+
this.ref.close(response);
|
|
259
|
+
},
|
|
260
|
+
error: (err) => {
|
|
261
|
+
this.loading = false;
|
|
262
|
+
console.error('Import error:', err);
|
|
263
|
+
this.messageService.add({
|
|
264
|
+
severity: 'error',
|
|
265
|
+
summary: 'Error',
|
|
266
|
+
detail: 'Failed to import file'
|
|
267
|
+
});
|
|
268
|
+
this.importError.emit(err);
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
// Update clearFileUpload to also clear file content
|
|
273
|
+
clearFileUpload(event) {
|
|
274
|
+
if (event.options && typeof event.options.clear === 'function') {
|
|
275
|
+
event.options.clear();
|
|
276
|
+
}
|
|
277
|
+
this.uploadedFileName = null;
|
|
278
|
+
this.fileContent = null;
|
|
279
|
+
}
|
|
280
|
+
initializeForm() {
|
|
281
|
+
const formConfig = {};
|
|
282
|
+
this.mappingFields.forEach(field => {
|
|
283
|
+
if (field.key) {
|
|
284
|
+
// Set default value to first header if available
|
|
285
|
+
formConfig[field.key] = [this.excelHeaders[0] || '', Validators.required];
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
this.form = this.fb.group(formConfig);
|
|
289
|
+
}
|
|
290
|
+
onCancel() {
|
|
291
|
+
if (!this.loading) {
|
|
292
|
+
this.ref.close(false);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
ngOnDestroy() {
|
|
296
|
+
this.destroy$.next();
|
|
297
|
+
this.destroy$.complete();
|
|
298
|
+
}
|
|
299
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExcelImportComponent, deps: [{ token: i1.DynamicDialogRef }, { token: i1.DynamicDialogConfig }], target: i0.ɵɵFactoryTarget.Component });
|
|
300
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.8", type: ExcelImportComponent, isStandalone: true, selector: "app-excel-import", inputs: { config: "config" }, outputs: { importComplete: "importComplete", importError: "importError" }, providers: [MessageService], ngImport: i0, template: `
|
|
301
|
+
<p-toast></p-toast>
|
|
302
|
+
<div class="p-4 space-y-4">
|
|
303
|
+
<p-steps [model]="steps" [(activeIndex)]="activeStep" class="mb-4"></p-steps>
|
|
304
|
+
|
|
305
|
+
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
306
|
+
<ng-container [ngSwitch]="activeStep">
|
|
307
|
+
<!-- Step 1: Upload File -->
|
|
308
|
+
<div *ngSwitchCase="0" class="p-4">
|
|
309
|
+
<!-- Download template link -->
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
<!-- File upload -->
|
|
313
|
+
<p-fileUpload
|
|
314
|
+
name="excelFile"
|
|
315
|
+
mode="basic"
|
|
316
|
+
chooseIcon="pi pi-upload"
|
|
317
|
+
chooseLabel="{{ 'chooseFile' | translate }}"
|
|
318
|
+
(onSelect)="onFileUpload($event)"
|
|
319
|
+
[accept]="config.acceptedFileTypes || '.xls,.xlsx,.csv'"
|
|
320
|
+
[maxFileSize]="config.maxFileSize || 10000000"
|
|
321
|
+
[showUploadButton]="false"
|
|
322
|
+
[showCancelButton]="false"
|
|
323
|
+
>
|
|
324
|
+
</p-fileUpload>
|
|
325
|
+
|
|
326
|
+
<!-- Upload status -->
|
|
327
|
+
<p *ngIf="uploadedFileName" class="mt-2 text-green-600">
|
|
328
|
+
{{ uploadedFileName }}
|
|
329
|
+
</p>
|
|
330
|
+
<p *ngIf="uploadError" class="mt-2 text-red-600">
|
|
331
|
+
{{ uploadError }}
|
|
332
|
+
</p>
|
|
333
|
+
</div>
|
|
334
|
+
<p>
|
|
335
|
+
<a
|
|
336
|
+
[href]="env.apiUrl+config.templateUrl"
|
|
337
|
+
download
|
|
338
|
+
class="text-blue-600 hover:underline flex items-center gap-1"
|
|
339
|
+
>
|
|
340
|
+
<i class="pi pi-download"></i>
|
|
341
|
+
{{ 'downloadTemplate' | translate }}
|
|
342
|
+
</a>
|
|
343
|
+
</p>
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
<!-- Step 2: Column Mapping -->
|
|
347
|
+
<div *ngSwitchCase="1" class="p-4">
|
|
348
|
+
<formly-form [form]="form" [fields]="mappingFields" [model]="model"></formly-form>
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
<!-- Step 3: Review -->
|
|
352
|
+
<div *ngSwitchCase="2" class="p-4">
|
|
353
|
+
<p class="text-gray-700 mb-4">
|
|
354
|
+
{{ 'importReviewMessage' | translate }}
|
|
355
|
+
</p>
|
|
356
|
+
<div class="bg-gray-100 p-3 rounded">
|
|
357
|
+
<p><strong>{{ 'fileName' | translate }}:</strong> {{ uploadedFileName }}</p>
|
|
358
|
+
<p><strong>{{ 'selectedMappings' | translate }}:</strong></p>
|
|
359
|
+
<ul class="list-disc list-inside ml-4">
|
|
360
|
+
<li *ngFor="let field of mappingFields">
|
|
361
|
+
{{ field.props?.label }}: {{ getModelValue(field, model) }}
|
|
362
|
+
</li>
|
|
363
|
+
</ul>
|
|
364
|
+
</div>
|
|
365
|
+
</div>
|
|
366
|
+
</ng-container>
|
|
367
|
+
|
|
368
|
+
<!-- Footer Buttons -->
|
|
369
|
+
<div class="flex justify-between mt-6 pt-4 border-t">
|
|
370
|
+
<div>
|
|
371
|
+
<button
|
|
372
|
+
pButton
|
|
373
|
+
type="button"
|
|
374
|
+
[label]="'back' | translate"
|
|
375
|
+
icon="pi pi-arrow-left"
|
|
376
|
+
(click)="prevStep()"
|
|
377
|
+
[disabled]="activeStep === 0 || loading"
|
|
378
|
+
class="p-button-text"
|
|
379
|
+
></button>
|
|
380
|
+
</div>
|
|
381
|
+
|
|
382
|
+
<div class="flex gap-2">
|
|
383
|
+
<button
|
|
384
|
+
pButton
|
|
385
|
+
type="button"
|
|
386
|
+
[label]="'next' | translate"
|
|
387
|
+
icon="pi pi-arrow-right"
|
|
388
|
+
iconPos="right"
|
|
389
|
+
(click)="nextStep()"
|
|
390
|
+
*ngIf="activeStep < 2"
|
|
391
|
+
[disabled]="!canProceed() || loading"
|
|
392
|
+
></button>
|
|
393
|
+
|
|
394
|
+
<button
|
|
395
|
+
pButton
|
|
396
|
+
type="submit"
|
|
397
|
+
[label]="loading ? ('uploading' | translate) : ('save' | translate)"
|
|
398
|
+
icon="pi pi-check"
|
|
399
|
+
*ngIf="activeStep === 2"
|
|
400
|
+
[disabled]="loading"
|
|
401
|
+
[loading]="loading"
|
|
402
|
+
class="p-button-primary"
|
|
403
|
+
></button>
|
|
404
|
+
|
|
405
|
+
<button
|
|
406
|
+
pButton
|
|
407
|
+
type="button"
|
|
408
|
+
[label]="'cancel' | translate"
|
|
409
|
+
severity="secondary"
|
|
410
|
+
(click)="onCancel()"
|
|
411
|
+
[disabled]="loading"
|
|
412
|
+
></button>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
</form>
|
|
416
|
+
</div>
|
|
417
|
+
`, isInline: true, 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: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { 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: "ngmodule", type: FileUploadModule }, { kind: "component", type: i5.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "ngmodule", type: StepsModule }, { kind: "component", type: i6.Steps, selector: "p-steps", inputs: ["activeIndex", "model", "readonly", "style", "styleClass", "exact"], outputs: ["activeIndexChange"] }, { kind: "ngmodule", type: ToastModule }, { kind: "component", type: i7.Toast, selector: "p-toast", inputs: ["key", "autoZIndex", "baseZIndex", "life", "styleClass", "position", "preventOpenDuplicates", "preventDuplicates", "showTransformOptions", "hideTransformOptions", "showTransitionOptions", "hideTransitionOptions", "breakpoints"], outputs: ["onClose"] }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }] });
|
|
418
|
+
}
|
|
419
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.8", ngImport: i0, type: ExcelImportComponent, decorators: [{
|
|
420
|
+
type: Component,
|
|
421
|
+
args: [{
|
|
422
|
+
selector: 'app-excel-import',
|
|
423
|
+
standalone: true,
|
|
424
|
+
providers: [MessageService],
|
|
425
|
+
template: `
|
|
426
|
+
<p-toast></p-toast>
|
|
427
|
+
<div class="p-4 space-y-4">
|
|
428
|
+
<p-steps [model]="steps" [(activeIndex)]="activeStep" class="mb-4"></p-steps>
|
|
429
|
+
|
|
430
|
+
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
431
|
+
<ng-container [ngSwitch]="activeStep">
|
|
432
|
+
<!-- Step 1: Upload File -->
|
|
433
|
+
<div *ngSwitchCase="0" class="p-4">
|
|
434
|
+
<!-- Download template link -->
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
<!-- File upload -->
|
|
438
|
+
<p-fileUpload
|
|
439
|
+
name="excelFile"
|
|
440
|
+
mode="basic"
|
|
441
|
+
chooseIcon="pi pi-upload"
|
|
442
|
+
chooseLabel="{{ 'chooseFile' | translate }}"
|
|
443
|
+
(onSelect)="onFileUpload($event)"
|
|
444
|
+
[accept]="config.acceptedFileTypes || '.xls,.xlsx,.csv'"
|
|
445
|
+
[maxFileSize]="config.maxFileSize || 10000000"
|
|
446
|
+
[showUploadButton]="false"
|
|
447
|
+
[showCancelButton]="false"
|
|
448
|
+
>
|
|
449
|
+
</p-fileUpload>
|
|
450
|
+
|
|
451
|
+
<!-- Upload status -->
|
|
452
|
+
<p *ngIf="uploadedFileName" class="mt-2 text-green-600">
|
|
453
|
+
{{ uploadedFileName }}
|
|
454
|
+
</p>
|
|
455
|
+
<p *ngIf="uploadError" class="mt-2 text-red-600">
|
|
456
|
+
{{ uploadError }}
|
|
457
|
+
</p>
|
|
458
|
+
</div>
|
|
459
|
+
<p>
|
|
460
|
+
<a
|
|
461
|
+
[href]="env.apiUrl+config.templateUrl"
|
|
462
|
+
download
|
|
463
|
+
class="text-blue-600 hover:underline flex items-center gap-1"
|
|
464
|
+
>
|
|
465
|
+
<i class="pi pi-download"></i>
|
|
466
|
+
{{ 'downloadTemplate' | translate }}
|
|
467
|
+
</a>
|
|
468
|
+
</p>
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
<!-- Step 2: Column Mapping -->
|
|
472
|
+
<div *ngSwitchCase="1" class="p-4">
|
|
473
|
+
<formly-form [form]="form" [fields]="mappingFields" [model]="model"></formly-form>
|
|
474
|
+
</div>
|
|
475
|
+
|
|
476
|
+
<!-- Step 3: Review -->
|
|
477
|
+
<div *ngSwitchCase="2" class="p-4">
|
|
478
|
+
<p class="text-gray-700 mb-4">
|
|
479
|
+
{{ 'importReviewMessage' | translate }}
|
|
480
|
+
</p>
|
|
481
|
+
<div class="bg-gray-100 p-3 rounded">
|
|
482
|
+
<p><strong>{{ 'fileName' | translate }}:</strong> {{ uploadedFileName }}</p>
|
|
483
|
+
<p><strong>{{ 'selectedMappings' | translate }}:</strong></p>
|
|
484
|
+
<ul class="list-disc list-inside ml-4">
|
|
485
|
+
<li *ngFor="let field of mappingFields">
|
|
486
|
+
{{ field.props?.label }}: {{ getModelValue(field, model) }}
|
|
487
|
+
</li>
|
|
488
|
+
</ul>
|
|
489
|
+
</div>
|
|
490
|
+
</div>
|
|
491
|
+
</ng-container>
|
|
492
|
+
|
|
493
|
+
<!-- Footer Buttons -->
|
|
494
|
+
<div class="flex justify-between mt-6 pt-4 border-t">
|
|
495
|
+
<div>
|
|
496
|
+
<button
|
|
497
|
+
pButton
|
|
498
|
+
type="button"
|
|
499
|
+
[label]="'back' | translate"
|
|
500
|
+
icon="pi pi-arrow-left"
|
|
501
|
+
(click)="prevStep()"
|
|
502
|
+
[disabled]="activeStep === 0 || loading"
|
|
503
|
+
class="p-button-text"
|
|
504
|
+
></button>
|
|
505
|
+
</div>
|
|
506
|
+
|
|
507
|
+
<div class="flex gap-2">
|
|
508
|
+
<button
|
|
509
|
+
pButton
|
|
510
|
+
type="button"
|
|
511
|
+
[label]="'next' | translate"
|
|
512
|
+
icon="pi pi-arrow-right"
|
|
513
|
+
iconPos="right"
|
|
514
|
+
(click)="nextStep()"
|
|
515
|
+
*ngIf="activeStep < 2"
|
|
516
|
+
[disabled]="!canProceed() || loading"
|
|
517
|
+
></button>
|
|
518
|
+
|
|
519
|
+
<button
|
|
520
|
+
pButton
|
|
521
|
+
type="submit"
|
|
522
|
+
[label]="loading ? ('uploading' | translate) : ('save' | translate)"
|
|
523
|
+
icon="pi pi-check"
|
|
524
|
+
*ngIf="activeStep === 2"
|
|
525
|
+
[disabled]="loading"
|
|
526
|
+
[loading]="loading"
|
|
527
|
+
class="p-button-primary"
|
|
528
|
+
></button>
|
|
529
|
+
|
|
530
|
+
<button
|
|
531
|
+
pButton
|
|
532
|
+
type="button"
|
|
533
|
+
[label]="'cancel' | translate"
|
|
534
|
+
severity="secondary"
|
|
535
|
+
(click)="onCancel()"
|
|
536
|
+
[disabled]="loading"
|
|
537
|
+
></button>
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
</form>
|
|
541
|
+
</div>
|
|
542
|
+
`,
|
|
543
|
+
imports: [
|
|
544
|
+
CommonModule,
|
|
545
|
+
ReactiveFormsModule,
|
|
546
|
+
FormsModule,
|
|
547
|
+
FormlyForm,
|
|
548
|
+
TranslateModule,
|
|
549
|
+
ButtonModule,
|
|
550
|
+
FileUploadModule,
|
|
551
|
+
StepsModule,
|
|
552
|
+
ToastModule
|
|
553
|
+
],
|
|
554
|
+
}]
|
|
555
|
+
}], ctorParameters: () => [{ type: i1.DynamicDialogRef }, { type: i1.DynamicDialogConfig }], propDecorators: { config: [{
|
|
556
|
+
type: Input
|
|
557
|
+
}], importComplete: [{
|
|
558
|
+
type: Output
|
|
559
|
+
}], importError: [{
|
|
560
|
+
type: Output
|
|
561
|
+
}] } });
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Generated bundle index. Do not edit.
|
|
565
|
+
*/
|
|
566
|
+
|
|
567
|
+
export { ExcelImportComponent, ExcelImportModule };
|
|
568
|
+
//# sourceMappingURL=elite.framework-ng.ui.core-excel-import.mjs.map
|