@rosoftlab/ionic 1.0.0-alpha-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/esm2022/lib/components/index.mjs +4 -0
- package/esm2022/lib/components/rsl-ionic-crud.component/rsl-ionic-crud.component.mjs +266 -0
- package/esm2022/lib/components/rsl-ionic-data-table/rsl-ionic-data-table.component.mjs +292 -0
- package/esm2022/lib/components/rsl-ionic-grid/rsl-ionic-grid.component.mjs +269 -0
- package/esm2022/lib/decorators/index.mjs +3 -0
- package/esm2022/lib/decorators/ionic-datatable-layout.mjs +10 -0
- package/esm2022/lib/decorators/ionic-list.decorator.mjs +9 -0
- package/esm2022/lib/interfaces/index.mjs +2 -0
- package/esm2022/lib/interfaces/ionic-list-layout-config.mjs +2 -0
- package/esm2022/lib/ionic-dialog.service.mjs +51 -0
- package/esm2022/lib/rsl-ionic-module.module.mjs +86 -0
- package/esm2022/lib/translate.extension.mjs +48 -0
- package/esm2022/lib/types/index.mjs +2 -0
- package/esm2022/lib/types/repeat/repeat-section.type.mjs +135 -0
- package/esm2022/lib/validators/index.mjs +2 -0
- package/esm2022/lib/validators/must-match.mjs +12 -0
- package/esm2022/lib/wrappers/accordion-wrapper.component.mjs +50 -0
- package/esm2022/lib/wrappers/index.mjs +3 -0
- package/esm2022/lib/wrappers/panel-wrapper.component.mjs +37 -0
- package/esm2022/lib/wrappers/wrappers.module.mjs +56 -0
- package/esm2022/public-api.mjs +12 -0
- package/esm2022/rosoftlab-ionic.mjs +5 -0
- package/fesm2022/rosoftlab-ionic.mjs +1251 -0
- package/fesm2022/rosoftlab-ionic.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/rsl-ionic-crud.component/rsl-ionic-crud.component.d.ts +69 -0
- package/lib/components/rsl-ionic-data-table/rsl-ionic-data-table.component.d.ts +66 -0
- package/lib/components/rsl-ionic-grid/rsl-ionic-grid.component.d.ts +58 -0
- package/lib/decorators/index.d.ts +2 -0
- package/lib/decorators/ionic-datatable-layout.d.ts +7 -0
- package/lib/decorators/ionic-list.decorator.d.ts +2 -0
- package/lib/interfaces/index.d.ts +1 -0
- package/lib/interfaces/ionic-list-layout-config.d.ts +8 -0
- package/lib/ionic-dialog.service.d.ts +10 -0
- package/lib/rsl-ionic-module.module.d.ts +13 -0
- package/lib/translate.extension.d.ts +17 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/repeat/repeat-section.type.d.ts +51 -0
- package/lib/validators/index.d.ts +1 -0
- package/lib/validators/must-match.d.ts +6 -0
- package/lib/wrappers/accordion-wrapper.component.d.ts +6 -0
- package/lib/wrappers/index.d.ts +2 -0
- package/lib/wrappers/panel-wrapper.component.d.ts +6 -0
- package/lib/wrappers/wrappers.module.d.ts +13 -0
- package/package.json +31 -0
- package/public-api.d.ts +8 -0
@@ -0,0 +1,1251 @@
|
|
1
|
+
import * as i3$1 from '@angular/common';
|
2
|
+
import { CommonModule } from '@angular/common';
|
3
|
+
import * as i0 from '@angular/core';
|
4
|
+
import { Injectable, NgModule, Component, ViewChild, Input } from '@angular/core';
|
5
|
+
import * as i1 from '@angular/forms';
|
6
|
+
import { ReactiveFormsModule, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
|
7
|
+
import * as i1$1 from '@angular/router';
|
8
|
+
import { UrlSegment, NavigationStart } from '@angular/router';
|
9
|
+
import * as i6$1 from '@ngx-formly/core/json-schema';
|
10
|
+
import * as i2 from '@ngx-translate/core';
|
11
|
+
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
12
|
+
import * as _ from 'lodash';
|
13
|
+
import { Observable, from } from 'rxjs';
|
14
|
+
import * as i4 from '@ionic/angular';
|
15
|
+
import { IonicModule } from '@ionic/angular';
|
16
|
+
import * as i6 from '@ngx-formly/core';
|
17
|
+
import { FormlyModule, FORMLY_CONFIG, FieldArrayType, FieldWrapper } from '@ngx-formly/core';
|
18
|
+
import { FormlyIonicModule } from '@ngx-formly/ionic';
|
19
|
+
import * as i6$2 from '@swimlane/ngx-datatable';
|
20
|
+
import { NgxDatatableModule, ColumnMode, SelectionType } from '@swimlane/ngx-datatable';
|
21
|
+
import { readFileAsync, getValueFromJsonData, GridLayoutFormat } from '@rosoftlab/core';
|
22
|
+
import * as i3 from 'ngx-filesaver';
|
23
|
+
import * as XLSX from 'xlsx';
|
24
|
+
import * as jsonLogic from 'json-logic-js/logic.js';
|
25
|
+
|
26
|
+
class IonicDialogService {
|
27
|
+
constructor(alertController) {
|
28
|
+
this.alertController = alertController;
|
29
|
+
}
|
30
|
+
async confirm(message, title, confirmButtonText = 'Delete', cancelButtonText = 'Cancel') {
|
31
|
+
let choice;
|
32
|
+
const alert = await this.alertController.create({
|
33
|
+
header: title,
|
34
|
+
subHeader: message,
|
35
|
+
buttons: [{
|
36
|
+
text: cancelButtonText,
|
37
|
+
handler: () => {
|
38
|
+
alert.dismiss(false);
|
39
|
+
return false;
|
40
|
+
}
|
41
|
+
}, {
|
42
|
+
text: confirmButtonText,
|
43
|
+
handler: () => {
|
44
|
+
alert.dismiss(true);
|
45
|
+
return true;
|
46
|
+
}
|
47
|
+
}]
|
48
|
+
});
|
49
|
+
await alert.present();
|
50
|
+
await alert.onDidDismiss().then((data) => {
|
51
|
+
choice = data;
|
52
|
+
});
|
53
|
+
return choice;
|
54
|
+
}
|
55
|
+
async showSaveMessage(message, title) {
|
56
|
+
const alert = await this.alertController.create({
|
57
|
+
header: title,
|
58
|
+
subHeader: message,
|
59
|
+
buttons: ['OK']
|
60
|
+
});
|
61
|
+
await alert.present();
|
62
|
+
}
|
63
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: IonicDialogService, deps: [{ token: i4.AlertController }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
64
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: IonicDialogService, providedIn: 'root' }); }
|
65
|
+
}
|
66
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: IonicDialogService, decorators: [{
|
67
|
+
type: Injectable,
|
68
|
+
args: [{
|
69
|
+
providedIn: 'root'
|
70
|
+
}]
|
71
|
+
}], ctorParameters: function () { return [{ type: i4.AlertController }]; } });
|
72
|
+
|
73
|
+
class TranslateExtension {
|
74
|
+
constructor(translate) {
|
75
|
+
this.translate = translate;
|
76
|
+
}
|
77
|
+
prePopulate(field) {
|
78
|
+
const props = field.props || {};
|
79
|
+
if (!props['translate'] || props['_translated']) {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
props['_translated'] = true;
|
83
|
+
field.expressions = {
|
84
|
+
...(field.expressions || {}),
|
85
|
+
'props.label': this.translate.stream(props.label),
|
86
|
+
};
|
87
|
+
if (props.placeholder) {
|
88
|
+
field.expressions = {
|
89
|
+
...(field.expressions || {}),
|
90
|
+
'props.placeholder': this.translate.stream(props.placeholder)
|
91
|
+
};
|
92
|
+
}
|
93
|
+
if (props.description) {
|
94
|
+
field.expressions = {
|
95
|
+
...(field.expressions || {}),
|
96
|
+
'props.description': this.translate.stream(props.description)
|
97
|
+
};
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
function registerTranslateExtension(translate) {
|
102
|
+
return {
|
103
|
+
validationMessages: [
|
104
|
+
{
|
105
|
+
name: 'required',
|
106
|
+
message(error, field) {
|
107
|
+
// console.log(field);
|
108
|
+
return translate.stream('General.Field.Required', { field: field.props.label });
|
109
|
+
},
|
110
|
+
},
|
111
|
+
],
|
112
|
+
extensions: [
|
113
|
+
{
|
114
|
+
name: 'translate',
|
115
|
+
extension: new TranslateExtension(translate),
|
116
|
+
}
|
117
|
+
],
|
118
|
+
};
|
119
|
+
}
|
120
|
+
|
121
|
+
const COMMON_MODULES$1 = [
|
122
|
+
CommonModule,
|
123
|
+
IonicModule,
|
124
|
+
ReactiveFormsModule,
|
125
|
+
FormlyIonicModule,
|
126
|
+
NgxDatatableModule
|
127
|
+
];
|
128
|
+
class WrappersModule {
|
129
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: WrappersModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
130
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.1", ngImport: i0, type: WrappersModule, imports: [CommonModule,
|
131
|
+
IonicModule,
|
132
|
+
ReactiveFormsModule,
|
133
|
+
FormlyIonicModule,
|
134
|
+
NgxDatatableModule, TranslateModule], exports: [CommonModule,
|
135
|
+
IonicModule,
|
136
|
+
ReactiveFormsModule,
|
137
|
+
FormlyIonicModule,
|
138
|
+
NgxDatatableModule, FormlyModule,
|
139
|
+
TranslateModule] }); }
|
140
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: WrappersModule, providers: [
|
141
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: registerTranslateExtension, deps: [TranslateService] },
|
142
|
+
], imports: [COMMON_MODULES$1, TranslateModule, CommonModule,
|
143
|
+
IonicModule,
|
144
|
+
ReactiveFormsModule,
|
145
|
+
FormlyIonicModule,
|
146
|
+
NgxDatatableModule, FormlyModule,
|
147
|
+
TranslateModule] }); }
|
148
|
+
}
|
149
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: WrappersModule, decorators: [{
|
150
|
+
type: NgModule,
|
151
|
+
args: [{
|
152
|
+
imports: [
|
153
|
+
...COMMON_MODULES$1,
|
154
|
+
TranslateModule
|
155
|
+
],
|
156
|
+
providers: [
|
157
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: registerTranslateExtension, deps: [TranslateService] },
|
158
|
+
],
|
159
|
+
exports: [
|
160
|
+
...COMMON_MODULES$1,
|
161
|
+
FormlyModule,
|
162
|
+
TranslateModule
|
163
|
+
],
|
164
|
+
}]
|
165
|
+
}] });
|
166
|
+
|
167
|
+
class RepeatTypeComponent extends FieldArrayType {
|
168
|
+
constructor(dialogService, translate, fileSaverService) {
|
169
|
+
super();
|
170
|
+
this.dialogService = dialogService;
|
171
|
+
this.translate = translate;
|
172
|
+
this.fileSaverService = fileSaverService;
|
173
|
+
this.data = null;
|
174
|
+
this.serach = null;
|
175
|
+
this.showSerach = false;
|
176
|
+
this.filterValue = null;
|
177
|
+
this.importDataProp = null;
|
178
|
+
this.exportDataProp = null;
|
179
|
+
this.deleteMessage = this.translate.instant("General.Delete.Question");
|
180
|
+
this.deleteButton = this.translate.instant("General.Delete.Button");
|
181
|
+
this.cancelButton = this.translate.instant("General.Cancel.Button");
|
182
|
+
}
|
183
|
+
remove(i, { markAsDirty } = { markAsDirty: true }) {
|
184
|
+
this.dialogService.confirm(this.deleteMessage, null, this.deleteButton, this.cancelButton).then((value) => {
|
185
|
+
if (value.data) {
|
186
|
+
var onDelete = this.field.props['onDelete'];
|
187
|
+
if (onDelete) {
|
188
|
+
onDelete(this.field.fieldGroup[i].model).subscribe(() => {
|
189
|
+
super.remove(i);
|
190
|
+
});
|
191
|
+
}
|
192
|
+
super.remove(i);
|
193
|
+
}
|
194
|
+
});
|
195
|
+
}
|
196
|
+
ngOnInit() {
|
197
|
+
this.typeKey = this.field.key;
|
198
|
+
this.serach = this.props['search'];
|
199
|
+
this.exportDataProp = this.props['export'] || null;
|
200
|
+
this.importDataProp = this.props['import'] || null;
|
201
|
+
if (this.serach) {
|
202
|
+
this.showSerach = this.serach.showSerach;
|
203
|
+
}
|
204
|
+
}
|
205
|
+
postPopulate(field) {
|
206
|
+
if (this.showSerach) {
|
207
|
+
this.data = field.fieldGroup;
|
208
|
+
if (this.filterValue) {
|
209
|
+
this.field.fieldGroup = this.data.filter(f => f.formControl.value[this.serach.searchProp].toLowerCase().includes(this.filterValue));
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
handleChange(event) {
|
214
|
+
if (this.showSerach) {
|
215
|
+
if (this.data == null && this.field.fieldGroup !== null) {
|
216
|
+
this.data = this.field.fieldGroup;
|
217
|
+
}
|
218
|
+
this.filterValue = event.target.value.toLowerCase();
|
219
|
+
this.field.fieldGroup = this.data.filter(f => f.formControl.value[this.serach.searchProp].toLowerCase().includes(this.filterValue));
|
220
|
+
}
|
221
|
+
}
|
222
|
+
importData() {
|
223
|
+
this.fileInput.nativeElement.click();
|
224
|
+
}
|
225
|
+
async handleImportFile(event) {
|
226
|
+
const file = event.target.files[0];
|
227
|
+
if (file) {
|
228
|
+
try {
|
229
|
+
const fileContents = await readFileAsync(file);
|
230
|
+
// Handle the file contents here (e.g., display or process the data)
|
231
|
+
const wb = XLSX.read(fileContents); //, { type: 'binary' });
|
232
|
+
const wsname = wb.SheetNames[0];
|
233
|
+
const ws = wb.Sheets[wsname];
|
234
|
+
const excelData = XLSX.utils.sheet_to_json(ws); //, { header: 1 });
|
235
|
+
excelData.forEach(element => {
|
236
|
+
const jsonX = getValueFromJsonData(element, this.importDataProp.keyProp);
|
237
|
+
const idx = this.field.parent.model[this.typeKey].findIndex(f => f[this.importDataProp.keyProp] === jsonX);
|
238
|
+
if (idx >= 0) {
|
239
|
+
const existingdata = this.field.parent.model[this.typeKey][idx];
|
240
|
+
for (const prop of this.importDataProp.propertiesToImport) {
|
241
|
+
const jsonVal = getValueFromJsonData(element, prop);
|
242
|
+
if (existingdata[prop] !== jsonVal) {
|
243
|
+
var fieldControl = this.field.fieldGroup[idx].formControl;
|
244
|
+
fieldControl.controls[prop].setValue(jsonVal);
|
245
|
+
}
|
246
|
+
}
|
247
|
+
}
|
248
|
+
else {
|
249
|
+
super.add(null, element);
|
250
|
+
}
|
251
|
+
});
|
252
|
+
}
|
253
|
+
catch (error) {
|
254
|
+
console.error('Error reading the file:', error);
|
255
|
+
}
|
256
|
+
}
|
257
|
+
}
|
258
|
+
exportData() {
|
259
|
+
// Filter the data to include only the specified properties
|
260
|
+
const filteredData = this.field.parent.model[this.typeKey].map(item => {
|
261
|
+
const filteredItem = {};
|
262
|
+
for (const prop of this.exportDataProp.propertiesToExport) {
|
263
|
+
filteredItem[prop] = item[prop];
|
264
|
+
}
|
265
|
+
return filteredItem;
|
266
|
+
});
|
267
|
+
const ws = XLSX.utils.json_to_sheet(filteredData);
|
268
|
+
const wb = XLSX.utils.book_new();
|
269
|
+
XLSX.utils.book_append_sheet(wb, ws, this.exportDataProp.sheetName);
|
270
|
+
const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
271
|
+
const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
272
|
+
this.fileSaverService.save(blob, this.exportDataProp.fileName);
|
273
|
+
}
|
274
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RepeatTypeComponent, deps: [{ token: IonicDialogService }, { token: i2.TranslateService }, { token: i3.FileSaverService }], target: i0.ɵɵFactoryTarget.Component }); }
|
275
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: RepeatTypeComponent, isStandalone: true, selector: "formly-repeat-section", viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n <ng-container [ngTemplateOutlet]=\"search\"></ng-container>\r\n</ion-header>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-left\">{{props.label}}</ion-title>\r\n\r\n <ion-button slot=\"end\" (click)=\"exportData()\" fill=\"clear\" [disabled]=\"props.disabled\" *ngIf=\"exportDataProp\">\r\n <ion-icon name=\"cloud-download-outline\"></ion-icon>\r\n </ion-button>\r\n\r\n <ion-button slot=\"end\" (click)=\"importData()\" fill=\"clear\" [disabled]=\"props.disabled\" *ngIf=\"importDataProp\">\r\n <ion-icon name=\"cloud-upload-outline\"></ion-icon>\r\n </ion-button>\r\n <input #fileInput type=\"file\" style=\"display: none\" accept=\".xlsx,.xls,.csv\" (change)=\"handleImportFile($event)\">\r\n\r\n <ion-button slot=\"end\" (click)=\"add()\" fill=\"clear\" [disabled]=\"props.disabled\">\r\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\r\n </ion-button>\r\n</ng-template>\r\n\r\n\r\n<ion-list lines=\"full\">\r\n <ion-item *ngFor=\"let field of field.fieldGroup; let i = index\" class=\"row align-items-baseline\">\r\n <formly-field class=\"formly-ion-list-item\" [field]=\"field\"></formly-field>\r\n <ion-button [disabled]=\"props.disabled\" color=\"danger\" slot=\"end\" (click)='remove(i)'>\r\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\r\n </ion-button>\r\n </ion-item>\r\n</ion-list>\r\n\r\n\r\n<ng-template #search>\r\n <ion-toolbar *ngIf=\"showSerach\">\r\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\r\n </ion-toolbar>\r\n</ng-template>", styles: [".formly-ion-list-item{display:inline;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: WrappersModule }, { kind: "directive", type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i4.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i4.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }, { kind: "component", type: i4.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i4.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i4.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "component", type: i6.FormlyField, selector: "formly-field", inputs: ["field"] }] }); }
|
276
|
+
}
|
277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RepeatTypeComponent, decorators: [{
|
278
|
+
type: Component,
|
279
|
+
args: [{ standalone: true, selector: 'formly-repeat-section', imports: [
|
280
|
+
WrappersModule
|
281
|
+
], template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n <ng-container [ngTemplateOutlet]=\"search\"></ng-container>\r\n</ion-header>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-left\">{{props.label}}</ion-title>\r\n\r\n <ion-button slot=\"end\" (click)=\"exportData()\" fill=\"clear\" [disabled]=\"props.disabled\" *ngIf=\"exportDataProp\">\r\n <ion-icon name=\"cloud-download-outline\"></ion-icon>\r\n </ion-button>\r\n\r\n <ion-button slot=\"end\" (click)=\"importData()\" fill=\"clear\" [disabled]=\"props.disabled\" *ngIf=\"importDataProp\">\r\n <ion-icon name=\"cloud-upload-outline\"></ion-icon>\r\n </ion-button>\r\n <input #fileInput type=\"file\" style=\"display: none\" accept=\".xlsx,.xls,.csv\" (change)=\"handleImportFile($event)\">\r\n\r\n <ion-button slot=\"end\" (click)=\"add()\" fill=\"clear\" [disabled]=\"props.disabled\">\r\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\r\n </ion-button>\r\n</ng-template>\r\n\r\n\r\n<ion-list lines=\"full\">\r\n <ion-item *ngFor=\"let field of field.fieldGroup; let i = index\" class=\"row align-items-baseline\">\r\n <formly-field class=\"formly-ion-list-item\" [field]=\"field\"></formly-field>\r\n <ion-button [disabled]=\"props.disabled\" color=\"danger\" slot=\"end\" (click)='remove(i)'>\r\n <ion-icon slot=\"icon-only\" name=\"trash\"></ion-icon>\r\n </ion-button>\r\n </ion-item>\r\n</ion-list>\r\n\r\n\r\n<ng-template #search>\r\n <ion-toolbar *ngIf=\"showSerach\">\r\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\r\n </ion-toolbar>\r\n</ng-template>", styles: [".formly-ion-list-item{display:inline;width:100%}\n"] }]
|
282
|
+
}], ctorParameters: function () { return [{ type: IonicDialogService }, { type: i2.TranslateService }, { type: i3.FileSaverService }]; }, propDecorators: { fileInput: [{
|
283
|
+
type: ViewChild,
|
284
|
+
args: ['fileInput']
|
285
|
+
}] } });
|
286
|
+
|
287
|
+
function fieldMatchValidator(control) {
|
288
|
+
const { password, confirmPassword } = control.value;
|
289
|
+
// avoid displaying the message error when values are empty
|
290
|
+
if (!confirmPassword || !password) {
|
291
|
+
return null;
|
292
|
+
}
|
293
|
+
if (confirmPassword === password) {
|
294
|
+
return null;
|
295
|
+
}
|
296
|
+
return { fieldMatch: { message: 'Fields.Not.Matching' } };
|
297
|
+
}
|
298
|
+
|
299
|
+
class AccordionWrapperComponent extends FieldWrapper {
|
300
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: AccordionWrapperComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
301
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: AccordionWrapperComponent, isStandalone: true, selector: "formly-accordion-panel", usesInheritance: true, ngImport: i0, template: `
|
302
|
+
|
303
|
+
<ion-accordion-group [value]="['first']">
|
304
|
+
<ion-accordion value="first">
|
305
|
+
<ion-item slot="header">
|
306
|
+
<ion-card-title>{{ props.label}}</ion-card-title>
|
307
|
+
</ion-item>
|
308
|
+
<div class="ion-padding" slot="content">
|
309
|
+
<ng-container #fieldComponent></ng-container>
|
310
|
+
</div>
|
311
|
+
</ion-accordion>
|
312
|
+
</ion-accordion-group>
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: WrappersModule }, { kind: "component", type: i4.IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: i4.IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: i4.IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }] }); }
|
317
|
+
}
|
318
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: AccordionWrapperComponent, decorators: [{
|
319
|
+
type: Component,
|
320
|
+
args: [{
|
321
|
+
standalone: true,
|
322
|
+
// eslint-disable-next-line @angular-eslint/component-selector
|
323
|
+
selector: 'formly-accordion-panel',
|
324
|
+
template: `
|
325
|
+
|
326
|
+
<ion-accordion-group [value]="['first']">
|
327
|
+
<ion-accordion value="first">
|
328
|
+
<ion-item slot="header">
|
329
|
+
<ion-card-title>{{ props.label}}</ion-card-title>
|
330
|
+
</ion-item>
|
331
|
+
<div class="ion-padding" slot="content">
|
332
|
+
<ng-container #fieldComponent></ng-container>
|
333
|
+
</div>
|
334
|
+
</ion-accordion>
|
335
|
+
</ion-accordion-group>
|
336
|
+
|
337
|
+
|
338
|
+
|
339
|
+
`,
|
340
|
+
imports: [WrappersModule]
|
341
|
+
}]
|
342
|
+
}] });
|
343
|
+
|
344
|
+
class PanelWrapperComponent extends FieldWrapper {
|
345
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: PanelWrapperComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
346
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: PanelWrapperComponent, isStandalone: true, selector: "formly-wrapper-panel", usesInheritance: true, ngImport: i0, template: `
|
347
|
+
<ion-card>
|
348
|
+
<ion-card-header>
|
349
|
+
<ion-card-title>{{ props.label}}</ion-card-title>
|
350
|
+
</ion-card-header>
|
351
|
+
<ion-card-content>
|
352
|
+
<ng-container #fieldComponent></ng-container>
|
353
|
+
</ion-card-content>
|
354
|
+
</ion-card>
|
355
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: WrappersModule }, { kind: "component", type: i4.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i4.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i4.IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: i4.IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }] }); }
|
356
|
+
}
|
357
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: PanelWrapperComponent, decorators: [{
|
358
|
+
type: Component,
|
359
|
+
args: [{
|
360
|
+
standalone: true,
|
361
|
+
selector: 'formly-wrapper-panel',
|
362
|
+
template: `
|
363
|
+
<ion-card>
|
364
|
+
<ion-card-header>
|
365
|
+
<ion-card-title>{{ props.label}}</ion-card-title>
|
366
|
+
</ion-card-header>
|
367
|
+
<ion-card-content>
|
368
|
+
<ng-container #fieldComponent></ng-container>
|
369
|
+
</ion-card-content>
|
370
|
+
</ion-card>
|
371
|
+
`,
|
372
|
+
imports: [WrappersModule]
|
373
|
+
}]
|
374
|
+
}] });
|
375
|
+
|
376
|
+
const COMMON_MODULES = [
|
377
|
+
CommonModule,
|
378
|
+
IonicModule,
|
379
|
+
ReactiveFormsModule,
|
380
|
+
FormlyIonicModule,
|
381
|
+
NgxDatatableModule
|
382
|
+
];
|
383
|
+
class RslIonicModuleModule {
|
384
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RslIonicModuleModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
385
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.1", ngImport: i0, type: RslIonicModuleModule, imports: [CommonModule,
|
386
|
+
IonicModule,
|
387
|
+
ReactiveFormsModule,
|
388
|
+
FormlyIonicModule,
|
389
|
+
NgxDatatableModule, TranslateModule, i6.FormlyModule], exports: [CommonModule,
|
390
|
+
IonicModule,
|
391
|
+
ReactiveFormsModule,
|
392
|
+
FormlyIonicModule,
|
393
|
+
NgxDatatableModule, FormlyModule,
|
394
|
+
TranslateModule] }); }
|
395
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RslIonicModuleModule, providers: [
|
396
|
+
IonicDialogService,
|
397
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: registerTranslateExtension, deps: [TranslateService] },
|
398
|
+
], imports: [COMMON_MODULES, TranslateModule,
|
399
|
+
FormlyModule.forRoot({
|
400
|
+
types: [{ name: 'repeat', component: RepeatTypeComponent }],
|
401
|
+
validators: [{ name: 'fieldMatch', validation: fieldMatchValidator }],
|
402
|
+
wrappers: [
|
403
|
+
{ name: 'panel', component: PanelWrapperComponent },
|
404
|
+
{ name: 'accordion', component: AccordionWrapperComponent }
|
405
|
+
],
|
406
|
+
validationMessages: [
|
407
|
+
{ name: 'required', message: 'This field is required' },
|
408
|
+
],
|
409
|
+
}), CommonModule,
|
410
|
+
IonicModule,
|
411
|
+
ReactiveFormsModule,
|
412
|
+
FormlyIonicModule,
|
413
|
+
NgxDatatableModule, FormlyModule,
|
414
|
+
TranslateModule] }); }
|
415
|
+
}
|
416
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RslIonicModuleModule, decorators: [{
|
417
|
+
type: NgModule,
|
418
|
+
args: [{
|
419
|
+
imports: [
|
420
|
+
...COMMON_MODULES,
|
421
|
+
TranslateModule,
|
422
|
+
FormlyModule.forRoot({
|
423
|
+
types: [{ name: 'repeat', component: RepeatTypeComponent }],
|
424
|
+
validators: [{ name: 'fieldMatch', validation: fieldMatchValidator }],
|
425
|
+
wrappers: [
|
426
|
+
{ name: 'panel', component: PanelWrapperComponent },
|
427
|
+
{ name: 'accordion', component: AccordionWrapperComponent }
|
428
|
+
],
|
429
|
+
validationMessages: [
|
430
|
+
{ name: 'required', message: 'This field is required' },
|
431
|
+
],
|
432
|
+
}),
|
433
|
+
],
|
434
|
+
providers: [
|
435
|
+
IonicDialogService,
|
436
|
+
{ provide: FORMLY_CONFIG, multi: true, useFactory: registerTranslateExtension, deps: [TranslateService] },
|
437
|
+
],
|
438
|
+
exports: [
|
439
|
+
...COMMON_MODULES,
|
440
|
+
FormlyModule,
|
441
|
+
TranslateModule
|
442
|
+
],
|
443
|
+
}]
|
444
|
+
}] });
|
445
|
+
|
446
|
+
class GenericIonicCrudComponent {
|
447
|
+
//#endregion
|
448
|
+
constructor(fb, router, route, dialogService, translate, location, injector, formlyJsonschema) {
|
449
|
+
this.fb = fb;
|
450
|
+
this.router = router;
|
451
|
+
this.route = route;
|
452
|
+
this.dialogService = dialogService;
|
453
|
+
this.translate = translate;
|
454
|
+
this.location = location;
|
455
|
+
this.injector = injector;
|
456
|
+
this.formlyJsonschema = formlyJsonschema;
|
457
|
+
this.isLoading = true;
|
458
|
+
this.changeUrlRoute = true;
|
459
|
+
this.options = {};
|
460
|
+
const SERVICE_TOKEN = route.snapshot.data['requiredService'];
|
461
|
+
this.modelService = this.injector.get(SERVICE_TOKEN);
|
462
|
+
this.modelService = this.injector.get(SERVICE_TOKEN);
|
463
|
+
this.confirmQuestion = this.translate.instant('General.Discard.Question');
|
464
|
+
this.confirmButton = this.translate.instant('General.Discard.ConfirmButton');
|
465
|
+
this.saveMessage = this.translate.instant('General.Save.Message');
|
466
|
+
}
|
467
|
+
ionViewWillLeave() {
|
468
|
+
this.options.resetModel();
|
469
|
+
this.baseForm.reset();
|
470
|
+
}
|
471
|
+
afterSave(model) {
|
472
|
+
return new Observable((observer) => {
|
473
|
+
observer.next(model);
|
474
|
+
observer.complete();
|
475
|
+
});
|
476
|
+
}
|
477
|
+
beforeSave(model) {
|
478
|
+
return new Observable((observer) => {
|
479
|
+
observer.next(model);
|
480
|
+
observer.complete();
|
481
|
+
});
|
482
|
+
}
|
483
|
+
ngOnInit() {
|
484
|
+
this.initForm();
|
485
|
+
}
|
486
|
+
initForm(customInclude = '', newModelId = null, model = null) {
|
487
|
+
if (model === null) {
|
488
|
+
this.modelId = this.route.snapshot.paramMap.get('id') ?? newModelId;
|
489
|
+
this.isEdit = false;
|
490
|
+
if (this.modelId) {
|
491
|
+
this.modelService.get(this.modelId, customInclude).subscribe((value) => {
|
492
|
+
this.isEdit = true;
|
493
|
+
this.generateForm(value);
|
494
|
+
});
|
495
|
+
}
|
496
|
+
else {
|
497
|
+
if (this.changeUrlRoute) {
|
498
|
+
const addUrl = this.router.createUrlTree([]).toString();
|
499
|
+
this.editRoute = this.router.createUrlTree([addUrl.replace('add', 'edit')]).toString();
|
500
|
+
}
|
501
|
+
// }
|
502
|
+
this.generateForm(this.modelService.newModel());
|
503
|
+
}
|
504
|
+
}
|
505
|
+
else {
|
506
|
+
this.modelId = model.id;
|
507
|
+
this.isEdit = true;
|
508
|
+
this.generateForm(model);
|
509
|
+
}
|
510
|
+
}
|
511
|
+
generateForm(model) {
|
512
|
+
this.isLoading = false;
|
513
|
+
this.modelId = model.id;
|
514
|
+
this.model = model;
|
515
|
+
this.origModel = _.cloneDeep(model);
|
516
|
+
;
|
517
|
+
this.title = this.model.modelConfig.formTitle;
|
518
|
+
this.baseForm = new UntypedFormGroup({}); //= this.modelService.toFormGroup(this.fb, model);
|
519
|
+
this.afterFormGenerated();
|
520
|
+
this.fields = this.modelService.getFormlyFields(this.model);
|
521
|
+
}
|
522
|
+
afterFormGenerated() {
|
523
|
+
}
|
524
|
+
getFromGroup(formGroup = null) {
|
525
|
+
if (!formGroup)
|
526
|
+
return this.baseForm;
|
527
|
+
if (formGroup instanceof UntypedFormGroup)
|
528
|
+
return formGroup;
|
529
|
+
return this.baseForm.controls[formGroup];
|
530
|
+
}
|
531
|
+
validateAllFormFields(formGroup = null) {
|
532
|
+
const fg = this.getFromGroup(formGroup);
|
533
|
+
Object.keys(fg.controls).forEach(field => {
|
534
|
+
// console.log(field);
|
535
|
+
const control = fg.get(field);
|
536
|
+
if (control instanceof UntypedFormControl) {
|
537
|
+
control.markAsTouched({ onlySelf: true });
|
538
|
+
}
|
539
|
+
else if (control instanceof UntypedFormGroup) {
|
540
|
+
this.validateAllFormFields(control);
|
541
|
+
}
|
542
|
+
});
|
543
|
+
}
|
544
|
+
isFieldValid(field, formGroup = null) {
|
545
|
+
const fg = this.getFromGroup(formGroup);
|
546
|
+
const filedControl = fg.get(field);
|
547
|
+
return !filedControl.valid && filedControl.touched;
|
548
|
+
}
|
549
|
+
isFieldValidFromArray(arrayIndex, field, arrayName = 'formArray') {
|
550
|
+
const fieldControl = this.baseForm.get(arrayName).get([arrayIndex]).get(field);
|
551
|
+
return !fieldControl.valid && fieldControl.touched;
|
552
|
+
}
|
553
|
+
displayFieldCss(field) {
|
554
|
+
return {
|
555
|
+
'has-error': this.isFieldValid(field),
|
556
|
+
'has-feedback': this.isFieldValid(field)
|
557
|
+
};
|
558
|
+
}
|
559
|
+
onCancel() {
|
560
|
+
this.router.navigate([this.cancelRoute]);
|
561
|
+
}
|
562
|
+
onSave() {
|
563
|
+
this.saveModel(this.baseForm);
|
564
|
+
}
|
565
|
+
onSubmit(model) {
|
566
|
+
this.saveModel(this.baseForm);
|
567
|
+
}
|
568
|
+
saveModel(formGroup = null) {
|
569
|
+
const fg = this.getFromGroup(formGroup);
|
570
|
+
const that = this;
|
571
|
+
if (fg) {
|
572
|
+
if (fg.valid) {
|
573
|
+
this.beforeSave(this.model).subscribe(_ => {
|
574
|
+
this.modelService.save(this.model, this.modelId, this.origModel).subscribe((newModel) => {
|
575
|
+
this.model = newModel;
|
576
|
+
this.modelId = newModel.id;
|
577
|
+
if (this.editRoute) {
|
578
|
+
this.isEdit = true;
|
579
|
+
if (this.changeUrlRoute) {
|
580
|
+
const url = this.router.createUrlTree([this.editRoute, this.modelId]).toString();
|
581
|
+
this.location.replaceState(url);
|
582
|
+
}
|
583
|
+
}
|
584
|
+
this.afterSave(newModel).subscribe((val) => {
|
585
|
+
from(this.dialogService.showSaveMessage(this.saveMessage)).subscribe(d => {
|
586
|
+
this.options.updateInitialValue();
|
587
|
+
fg.markAsPristine();
|
588
|
+
});
|
589
|
+
});
|
590
|
+
}, err => {
|
591
|
+
this.serverErrors(err);
|
592
|
+
});
|
593
|
+
});
|
594
|
+
}
|
595
|
+
else {
|
596
|
+
this.validateAllFormFields(formGroup);
|
597
|
+
}
|
598
|
+
}
|
599
|
+
}
|
600
|
+
serverErrors(err) {
|
601
|
+
if (err.error) {
|
602
|
+
if (err.error.errors) {
|
603
|
+
const validationErrors = err.error.errors;
|
604
|
+
if (Array.isArray(validationErrors)) {
|
605
|
+
validationErrors.forEach(prop => {
|
606
|
+
const formControl = this.baseForm.get(this.firstCharToLowerCase(prop));
|
607
|
+
if (formControl) {
|
608
|
+
// activate the error message
|
609
|
+
formControl.setErrors({
|
610
|
+
serverError: { message: validationErrors[prop].join('\n') }
|
611
|
+
});
|
612
|
+
}
|
613
|
+
});
|
614
|
+
}
|
615
|
+
else {
|
616
|
+
const keys = Object.keys(validationErrors);
|
617
|
+
keys.forEach(prop => {
|
618
|
+
const formControl = this.baseForm.get(this.firstCharToLowerCase(prop));
|
619
|
+
if (formControl) {
|
620
|
+
// activate the error message
|
621
|
+
formControl.setErrors({
|
622
|
+
serverError: { message: validationErrors[prop].join('\n') }
|
623
|
+
});
|
624
|
+
}
|
625
|
+
});
|
626
|
+
}
|
627
|
+
}
|
628
|
+
}
|
629
|
+
}
|
630
|
+
firstCharToLowerCase(str) {
|
631
|
+
if (str.length === 0) {
|
632
|
+
return str; // Return an empty string if the input is empty
|
633
|
+
}
|
634
|
+
const firstChar = str.charAt(0).toLowerCase();
|
635
|
+
const restOfString = str.slice(1);
|
636
|
+
return firstChar + restOfString;
|
637
|
+
}
|
638
|
+
async canDeactivate() {
|
639
|
+
if (!this.baseForm.dirty) {
|
640
|
+
return true;
|
641
|
+
}
|
642
|
+
var result = await this.dialogService.confirm(this.confirmQuestion, null, this.confirmButton);
|
643
|
+
return result;
|
644
|
+
}
|
645
|
+
getFiledName(filedTranslationKey) {
|
646
|
+
return { field: this.translate.instant(filedTranslationKey) };
|
647
|
+
}
|
648
|
+
getCustomErrorMessage(error, fieldLabel) {
|
649
|
+
return '';
|
650
|
+
}
|
651
|
+
getErrorMessageFromArray(arrayIndex, field, filedTranslationKey, arrayName = 'formArray') {
|
652
|
+
const fieldControl = this.baseForm.get(arrayName).get([arrayIndex]).get(field);
|
653
|
+
return this.getErrorMessageForField(fieldControl, filedTranslationKey);
|
654
|
+
}
|
655
|
+
getErrorMessage(field, filedTranslationKey, formGroup = null) {
|
656
|
+
const fg = this.getFromGroup(formGroup);
|
657
|
+
return this.getErrorMessageForField(fg.get(field), filedTranslationKey);
|
658
|
+
}
|
659
|
+
getErrorMessageForField(fieldControl, filedTranslationKey) {
|
660
|
+
const error = fieldControl.errors;
|
661
|
+
const fieldLabel = this.translate.instant(filedTranslationKey);
|
662
|
+
let rvalue = '';
|
663
|
+
if (error !== null) {
|
664
|
+
if (error['required'] === true) {
|
665
|
+
rvalue = this.translate.instant('General.Field.Required', { field: fieldLabel });
|
666
|
+
}
|
667
|
+
if (error['minlength']) {
|
668
|
+
rvalue = this.translate.instant('General.Field.MinLength', { field: fieldLabel, requiredLength: error.minlength.requiredLength });
|
669
|
+
}
|
670
|
+
if (error['email'] === true) {
|
671
|
+
rvalue = this.translate.instant('General.Field.InvalidEmail');
|
672
|
+
}
|
673
|
+
if (error['url'] === true) {
|
674
|
+
rvalue = this.translate.instant('General.Field.InvalidUrl');
|
675
|
+
}
|
676
|
+
if (error['serverError']) {
|
677
|
+
rvalue = error['serverError'];
|
678
|
+
}
|
679
|
+
if (rvalue === '') {
|
680
|
+
rvalue = this.getCustomErrorMessage(error, fieldLabel);
|
681
|
+
}
|
682
|
+
}
|
683
|
+
return rvalue;
|
684
|
+
}
|
685
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: GenericIonicCrudComponent, deps: [{ token: i1.UntypedFormBuilder }, { token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: IonicDialogService }, { token: i2.TranslateService }, { token: i3$1.Location }, { token: i0.Injector }, { token: i6$1.FormlyJsonschema }], target: i0.ɵɵFactoryTarget.Component }); }
|
686
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: GenericIonicCrudComponent, isStandalone: true, selector: "rslc-ionic-crud", ngImport: i0, template: "<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <ng-container *ngIf=\"!isLoading\">\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\n </form>\n </ng-container>\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\n </ion-button>\n</ng-template>", styles: [""], dependencies: [{ kind: "ngmodule", type: RslIonicModuleModule }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.IonBackButton, selector: "ion-back-button", inputs: ["color", "defaultHref", "disabled", "icon", "mode", "routerAnimation", "text", "type"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i4.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }, { kind: "component", type: i4.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i4.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i4.IonBackButtonDelegate, selector: "ion-back-button", inputs: ["defaultHref", "routerAnimation"] }, { 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: "component", type: i6.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
|
687
|
+
}
|
688
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: GenericIonicCrudComponent, decorators: [{
|
689
|
+
type: Component,
|
690
|
+
args: [{ standalone: true, selector: 'rslc-ionic-crud', imports: [RslIonicModuleModule], template: "<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <ng-container *ngIf=\"!isLoading\">\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\n </form>\n </ng-container>\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\n </ion-button>\n</ng-template>" }]
|
691
|
+
}], ctorParameters: function () { return [{ type: i1.UntypedFormBuilder }, { type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: IonicDialogService }, { type: i2.TranslateService }, { type: i3$1.Location }, { type: i0.Injector }, { type: i6$1.FormlyJsonschema }]; } });
|
692
|
+
|
693
|
+
class RslIonicDataTableComponent {
|
694
|
+
constructor(router, route, translate, location, injector, navCtrl, dialogService, el) {
|
695
|
+
this.router = router;
|
696
|
+
this.route = route;
|
697
|
+
this.translate = translate;
|
698
|
+
this.location = location;
|
699
|
+
this.injector = injector;
|
700
|
+
this.navCtrl = navCtrl;
|
701
|
+
this.dialogService = dialogService;
|
702
|
+
this.el = el;
|
703
|
+
this.data = [];
|
704
|
+
this.pageIndex = 1;
|
705
|
+
this.pageSize = 30;
|
706
|
+
this.columns = [];
|
707
|
+
this.allColumns = [];
|
708
|
+
this.ColumnMode = ColumnMode;
|
709
|
+
this.SelectionType = SelectionType;
|
710
|
+
this.headerHeight = 50;
|
711
|
+
this.rowHeight = 50;
|
712
|
+
}
|
713
|
+
ngOnInit() {
|
714
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'showSerach', false);
|
715
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'searchFields', null);
|
716
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'customInclude', null);
|
717
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'defaultSort', null);
|
718
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'defaultSortDirection', '');
|
719
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'deletePropertyName', 'name');
|
720
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'defaultFilter', null);
|
721
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'showHeader', true);
|
722
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'deleteDisableRule', null);
|
723
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'hasAdd', true);
|
724
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'canDelete', true);
|
725
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'canEdit', true);
|
726
|
+
if (!this.modelService) {
|
727
|
+
const SERVICE_TOKEN = this.route.snapshot.data['requiredService'];
|
728
|
+
this.modelService = this.injector.get(SERVICE_TOKEN);
|
729
|
+
}
|
730
|
+
this.model = this.modelService.newModel();
|
731
|
+
this.title = this.model.modelConfig.formTitle;
|
732
|
+
this.getListLayout();
|
733
|
+
const currentUrlSegments = this.router.url.split('/').map(segment => new UrlSegment(segment, {}));
|
734
|
+
this.basePath = currentUrlSegments.map(segment => segment.path).join('/');
|
735
|
+
this.router.events.subscribe(event => {
|
736
|
+
if (event instanceof NavigationStart) {
|
737
|
+
// Navigation to another page is about to occur
|
738
|
+
this.data = [];
|
739
|
+
this.pageIndex = 1;
|
740
|
+
// Perform actions or update component as needed
|
741
|
+
}
|
742
|
+
});
|
743
|
+
// this.isLoading = true;
|
744
|
+
// this.onScroll(0);
|
745
|
+
}
|
746
|
+
setValueFromSnapshot(component, snapshot, key, defaultValue) {
|
747
|
+
if (component[key] === undefined) {
|
748
|
+
let dataFromSnapshot = snapshot.data[key];
|
749
|
+
if (dataFromSnapshot === null || dataFromSnapshot === undefined) {
|
750
|
+
dataFromSnapshot = snapshot.params[key];
|
751
|
+
}
|
752
|
+
component[key] = dataFromSnapshot !== undefined ? dataFromSnapshot : defaultValue;
|
753
|
+
}
|
754
|
+
}
|
755
|
+
onScroll(offsetY) {
|
756
|
+
if (offsetY) {
|
757
|
+
if (this.oldOffsetY !== offsetY) {
|
758
|
+
this.oldOffsetY = offsetY;
|
759
|
+
const viewHeight = this.el.nativeElement.getBoundingClientRect().height - this.headerHeight;
|
760
|
+
if (!this.isLoading && offsetY + viewHeight >= this.data.length * this.rowHeight) {
|
761
|
+
// total number of results to load
|
762
|
+
let limit = this.pageSize;
|
763
|
+
// check if we haven't fetched any results yet
|
764
|
+
if (this.data.length === 0) {
|
765
|
+
// calculate the number of rows that fit within viewport
|
766
|
+
const pageSize = Math.ceil(viewHeight / this.rowHeight);
|
767
|
+
// change the limit to pageSize such that we fill the first page entirely
|
768
|
+
// (otherwise, we won't be able to scroll past it)
|
769
|
+
limit = Math.max(pageSize, this.pageSize);
|
770
|
+
}
|
771
|
+
// this.pageIndex
|
772
|
+
this.pageSize = limit;
|
773
|
+
this.loadData();
|
774
|
+
// this.loadPage(limit);
|
775
|
+
}
|
776
|
+
}
|
777
|
+
}
|
778
|
+
}
|
779
|
+
async ionViewWillEnter() {
|
780
|
+
this.data = [];
|
781
|
+
this.loadData();
|
782
|
+
}
|
783
|
+
async handleChange(event) {
|
784
|
+
this.filterValue = event.target.value.toLowerCase();
|
785
|
+
this.data = [];
|
786
|
+
this.pageIndex = 1;
|
787
|
+
this.loadData();
|
788
|
+
}
|
789
|
+
loadData(event = null) {
|
790
|
+
const filters = [];
|
791
|
+
let sorts = '';
|
792
|
+
this.isLoading = true;
|
793
|
+
if (this.defaultSort) {
|
794
|
+
if (this.defaultSortDirection === 'desc') {
|
795
|
+
sorts = '-' + this.defaultSort;
|
796
|
+
}
|
797
|
+
else {
|
798
|
+
sorts = this.defaultSort;
|
799
|
+
}
|
800
|
+
}
|
801
|
+
if (this.showSerach) {
|
802
|
+
if (this.filterValue) {
|
803
|
+
const y = '(' + this.searchFields.replace(',', '|') + ')';
|
804
|
+
filters.push(y + '@=*' + this.filterValue);
|
805
|
+
}
|
806
|
+
}
|
807
|
+
if (this.defaultFilter) {
|
808
|
+
filters.push(this.defaultFilter);
|
809
|
+
}
|
810
|
+
setTimeout(() => {
|
811
|
+
const filtersValue = filters.join(', ');
|
812
|
+
this.modelService.getAll(this.pageIndex, this.pageSize, sorts, filtersValue, this.customInclude).subscribe((response) => {
|
813
|
+
if (this.pageIndex !== response.getMeta().meta.count) {
|
814
|
+
this.pageIndex++;
|
815
|
+
}
|
816
|
+
else {
|
817
|
+
if (event)
|
818
|
+
event.target.disabled = true;
|
819
|
+
}
|
820
|
+
// if (this.filterValue)
|
821
|
+
// this.data = response.getModels();
|
822
|
+
// else
|
823
|
+
const rows = [...this.data, ...response.getModels()];
|
824
|
+
this.data = rows;
|
825
|
+
// this.data = this.data.concat();
|
826
|
+
if (event)
|
827
|
+
event.target.complete();
|
828
|
+
this.isLoading = false;
|
829
|
+
});
|
830
|
+
}, 700);
|
831
|
+
}
|
832
|
+
async handleRefresh(event) {
|
833
|
+
this.pageIndex = 1;
|
834
|
+
this.data = [];
|
835
|
+
this.loadData();
|
836
|
+
event.target.complete();
|
837
|
+
}
|
838
|
+
onAdd() {
|
839
|
+
console.log(this.basePath);
|
840
|
+
this.router.navigate([this.basePath + '/add']);
|
841
|
+
// this.navCtrl.navigateForward(this.basePath + '/add');
|
842
|
+
}
|
843
|
+
editModel(model) {
|
844
|
+
if (this.canEdit)
|
845
|
+
this.router.navigate([this.basePath + '/edit/', model.id]);
|
846
|
+
// this.navCtrl.navigateForward(this.basePath + '/edit/' + model.id);
|
847
|
+
}
|
848
|
+
getListLayout() {
|
849
|
+
if (!this.model) {
|
850
|
+
this.model = this.modelService.newModel();
|
851
|
+
}
|
852
|
+
this.allColumns = [];
|
853
|
+
this.columns = [];
|
854
|
+
this.allColumns = Reflect.getMetadata('IonicDataTableLayout', this.model).map((item) => {
|
855
|
+
if (!item.isTranslated) {
|
856
|
+
item.name = this.translate.instant(item.name);
|
857
|
+
item.isTranslated = true;
|
858
|
+
}
|
859
|
+
return item;
|
860
|
+
});
|
861
|
+
this.allColumns.sort((a, b) => a.order - b.order);
|
862
|
+
if (this.canDelete || this.canEdit) {
|
863
|
+
this.allColumns.push({
|
864
|
+
cellTemplate: this.actionsTmpl,
|
865
|
+
name: '',
|
866
|
+
cellClass: 'actions-cell',
|
867
|
+
draggable: false,
|
868
|
+
sortable: false,
|
869
|
+
visible: true
|
870
|
+
// width: 100,
|
871
|
+
// maxWidth: 100,
|
872
|
+
// minWidth: 100
|
873
|
+
});
|
874
|
+
}
|
875
|
+
this.columns = this.allColumns.filter((item) => item.visible);
|
876
|
+
// Sort the columns array by the order property
|
877
|
+
}
|
878
|
+
deleteModel(model) {
|
879
|
+
const msg = 'Do you want to delete ' + model[this.deletePropertyName] + '?';
|
880
|
+
this.dialogService.confirm(msg).then((value) => {
|
881
|
+
if (value.data) {
|
882
|
+
this.modelService.delete(model.id).subscribe(() => {
|
883
|
+
const tempData = [];
|
884
|
+
// this.selectedObject.emit(null);
|
885
|
+
this.data.map((item) => {
|
886
|
+
if (item.id !== model.id) {
|
887
|
+
tempData.push(item);
|
888
|
+
}
|
889
|
+
});
|
890
|
+
this.data = tempData;
|
891
|
+
});
|
892
|
+
}
|
893
|
+
});
|
894
|
+
}
|
895
|
+
deleteEnabled(model) {
|
896
|
+
if (this.canDelete) {
|
897
|
+
if (this.deleteDisableRule) {
|
898
|
+
return this.evaluateRule(this.deleteDisableRule, model);
|
899
|
+
}
|
900
|
+
else {
|
901
|
+
return true;
|
902
|
+
}
|
903
|
+
}
|
904
|
+
else {
|
905
|
+
return false;
|
906
|
+
}
|
907
|
+
}
|
908
|
+
evaluateRule(rules, model) {
|
909
|
+
let result = true;
|
910
|
+
rules.forEach(rule => {
|
911
|
+
let jsonRule;
|
912
|
+
if (typeof rule.rule === 'string') {
|
913
|
+
jsonRule = JSON.parse(rule.rule);
|
914
|
+
}
|
915
|
+
else {
|
916
|
+
jsonRule = rule.rule;
|
917
|
+
}
|
918
|
+
if (rule.parameters) {
|
919
|
+
const data = '{' + rule.parameters.map((item) => {
|
920
|
+
return '"' + item + '":"' + model[item] + '"';
|
921
|
+
}).join(',') + '}';
|
922
|
+
result = jsonLogic.apply(jsonRule, JSON.parse(data));
|
923
|
+
}
|
924
|
+
else {
|
925
|
+
result = jsonLogic.apply(jsonRule);
|
926
|
+
}
|
927
|
+
});
|
928
|
+
return result;
|
929
|
+
}
|
930
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RslIonicDataTableComponent, deps: [{ token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: i2.TranslateService }, { token: i3$1.Location }, { token: i0.Injector }, { token: i4.NavController }, { token: IonicDialogService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
931
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: RslIonicDataTableComponent, isStandalone: true, selector: "app-rsl-ionic-data-table", inputs: { showSerach: "showSerach", searchFields: "searchFields", customInclude: "customInclude", defaultSort: "defaultSort", defaultSortDirection: "defaultSortDirection", deletePropertyName: "deletePropertyName", defaultFilter: "defaultFilter", showHeader: "showHeader", deleteDisableRule: "deleteDisableRule", hasAdd: "hasAdd", canDelete: "canDelete", canEdit: "canEdit", model: "model", modelService: "modelService" }, viewQueries: [{ propertyName: "actionsTmpl", first: true, predicate: ["actionsTmpl"], descendants: true, static: true }], ngImport: i0, template: "<ion-header *ngIf=\"showHeader\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n <ng-container [ngTemplateOutlet]=\"search\"></ng-container>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n\n <ion-refresher slot=\"fixed\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <ngx-datatable class=\"material fullscreen rls-server-scrolling\" style=\"top: 115px\" [rows]=\"data\" [columns]=\"columns\"\n [columnMode]=\"ColumnMode.standard\" [headerHeight]=\"headerHeight\" [rowHeight]=\"rowHeight\" [scrollbarV]=\"true\"\n [loadingIndicator]=\"isLoading\" [scrollbarH]=\"true\" (scroll)=\"onScroll($event.offsetY)\"\n >\n </ngx-datatable>\n \n <ng-template #actionsTmpl let-row=\"row\" let-value=\"value\">\n <ion-button fill=\"clear\" *ngIf=\"canEdit\" (click)='editModel(row)'>\n <ion-icon slot=\"icon-only\" name=\"create\" (click)='editModel(row)'></ion-icon>\n </ion-button>\n <ion-button fill=\"clear\" *ngIf=\"deleteEnabled(row)\" (click)='deleteModel(row)'>\n <ion-icon color=\"danger\" slot=\"icon-only\" name=\"trash\" (click)='deleteModel(row)'></ion-icon>\n </ion-button>\n </ng-template>\n\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title}}</ion-title>\n <ion-button slot=\"end\" (click)=\"onAdd()\" fill=\"clear\" *ngIf=\"hasAdd\">\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\n </ion-button>\n</ng-template>\n\n<ng-template #search>\n <ion-toolbar *ngIf=\"showSerach\">\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\n </ion-toolbar>\n</ng-template>", styles: [".rls-server-scrolling{height:calc(100vh - 110px)}::ng-deep .progress-linear{position:fixed!important;bottom:0}::ng-deep .actions-cell{padding:5px 0 0 .9rem!important}::ng-deep .align-right{text-align:right!important}\n"], dependencies: [{ kind: "ngmodule", type: RslIonicModuleModule }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.IonBackButton, selector: "ion-back-button", inputs: ["color", "defaultHref", "disabled", "icon", "mode", "routerAnimation", "text", "type"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i4.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }, { kind: "component", type: i4.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i4.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i4.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }, { kind: "component", type: i4.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i4.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i4.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "directive", type: i4.IonBackButtonDelegate, selector: "ion-back-button", inputs: ["defaultHref", "routerAnimation"] }, { kind: "component", type: i6$2.DatatableComponent, selector: "ngx-datatable", inputs: ["targetMarkerTemplate", "rows", "groupRowsBy", "groupedRows", "columns", "selected", "scrollbarV", "scrollbarH", "rowHeight", "columnMode", "headerHeight", "footerHeight", "externalPaging", "externalSorting", "limit", "count", "offset", "loadingIndicator", "selectionType", "reorderable", "swapColumns", "sortType", "sorts", "cssClasses", "messages", "rowClass", "selectCheck", "displayCheck", "groupExpansionDefault", "trackByProp", "selectAllRowsOnPage", "virtualization", "treeFromRelation", "treeToRelation", "summaryRow", "summaryHeight", "summaryPosition", "rowIdentity"], outputs: ["scroll", "activate", "select", "sort", "page", "reorder", "resize", "tableContextmenu", "treeAction"] }] }); }
|
932
|
+
}
|
933
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RslIonicDataTableComponent, decorators: [{
|
934
|
+
type: Component,
|
935
|
+
args: [{ standalone: true, selector: 'app-rsl-ionic-data-table', imports: [RslIonicModuleModule], template: "<ion-header *ngIf=\"showHeader\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n <ng-container [ngTemplateOutlet]=\"search\"></ng-container>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n\n <ion-refresher slot=\"fixed\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <ngx-datatable class=\"material fullscreen rls-server-scrolling\" style=\"top: 115px\" [rows]=\"data\" [columns]=\"columns\"\n [columnMode]=\"ColumnMode.standard\" [headerHeight]=\"headerHeight\" [rowHeight]=\"rowHeight\" [scrollbarV]=\"true\"\n [loadingIndicator]=\"isLoading\" [scrollbarH]=\"true\" (scroll)=\"onScroll($event.offsetY)\"\n >\n </ngx-datatable>\n \n <ng-template #actionsTmpl let-row=\"row\" let-value=\"value\">\n <ion-button fill=\"clear\" *ngIf=\"canEdit\" (click)='editModel(row)'>\n <ion-icon slot=\"icon-only\" name=\"create\" (click)='editModel(row)'></ion-icon>\n </ion-button>\n <ion-button fill=\"clear\" *ngIf=\"deleteEnabled(row)\" (click)='deleteModel(row)'>\n <ion-icon color=\"danger\" slot=\"icon-only\" name=\"trash\" (click)='deleteModel(row)'></ion-icon>\n </ion-button>\n </ng-template>\n\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title}}</ion-title>\n <ion-button slot=\"end\" (click)=\"onAdd()\" fill=\"clear\" *ngIf=\"hasAdd\">\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\n </ion-button>\n</ng-template>\n\n<ng-template #search>\n <ion-toolbar *ngIf=\"showSerach\">\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\n </ion-toolbar>\n</ng-template>", styles: [".rls-server-scrolling{height:calc(100vh - 110px)}::ng-deep .progress-linear{position:fixed!important;bottom:0}::ng-deep .actions-cell{padding:5px 0 0 .9rem!important}::ng-deep .align-right{text-align:right!important}\n"] }]
|
936
|
+
}], ctorParameters: function () { return [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: i2.TranslateService }, { type: i3$1.Location }, { type: i0.Injector }, { type: i4.NavController }, { type: IonicDialogService }, { type: i0.ElementRef }]; }, propDecorators: { actionsTmpl: [{
|
937
|
+
type: ViewChild,
|
938
|
+
args: ['actionsTmpl', { static: true }]
|
939
|
+
}], showSerach: [{
|
940
|
+
type: Input
|
941
|
+
}], searchFields: [{
|
942
|
+
type: Input
|
943
|
+
}], customInclude: [{
|
944
|
+
type: Input
|
945
|
+
}], defaultSort: [{
|
946
|
+
type: Input
|
947
|
+
}], defaultSortDirection: [{
|
948
|
+
type: Input
|
949
|
+
}], deletePropertyName: [{
|
950
|
+
type: Input
|
951
|
+
}], defaultFilter: [{
|
952
|
+
type: Input
|
953
|
+
}], showHeader: [{
|
954
|
+
type: Input
|
955
|
+
}], deleteDisableRule: [{
|
956
|
+
type: Input
|
957
|
+
}], hasAdd: [{
|
958
|
+
type: Input
|
959
|
+
}], canDelete: [{
|
960
|
+
type: Input
|
961
|
+
}], canEdit: [{
|
962
|
+
type: Input
|
963
|
+
}], model: [{
|
964
|
+
type: Input
|
965
|
+
}], modelService: [{
|
966
|
+
type: Input
|
967
|
+
}] } });
|
968
|
+
|
969
|
+
class RslIonicGridComponent {
|
970
|
+
constructor(router, route, translate, location, injector, loadingCtrl, navCtrl, dialogService, datePipe, numberPipe, percentPipe) {
|
971
|
+
this.router = router;
|
972
|
+
this.route = route;
|
973
|
+
this.translate = translate;
|
974
|
+
this.location = location;
|
975
|
+
this.injector = injector;
|
976
|
+
this.loadingCtrl = loadingCtrl;
|
977
|
+
this.navCtrl = navCtrl;
|
978
|
+
this.dialogService = dialogService;
|
979
|
+
this.datePipe = datePipe;
|
980
|
+
this.numberPipe = numberPipe;
|
981
|
+
this.percentPipe = percentPipe;
|
982
|
+
this.data = [];
|
983
|
+
this.pageIndex = 1;
|
984
|
+
this.pageSize = 30;
|
985
|
+
}
|
986
|
+
ngOnInit() {
|
987
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'showSerach', false);
|
988
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'searchFields', null);
|
989
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'customInclude', null);
|
990
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'defaultSort', null);
|
991
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'defaultSortDirection', '');
|
992
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'deletePropertyName', 'name');
|
993
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'defaultFilter', null);
|
994
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'showHeader', true);
|
995
|
+
this.setValueFromSnapshot(this, this.route.snapshot, 'deleteDisableRule', null);
|
996
|
+
// this.showSerach = route.snapshot.data['showSerach'] || false;
|
997
|
+
// this.searchFields = this.route.snapshot.data['searchFields'] || null;
|
998
|
+
// this.customInclude = this.route.snapshot.data['customInclude'] || null;
|
999
|
+
// this.defaultSort = this.route.snapshot.data['defaultSort'] || null;
|
1000
|
+
// this.defaultSortDirection = this.route.snapshot.data['defaultSortDirection'] || '';
|
1001
|
+
// this.deletePropertyName = this.route.snapshot.data['deletePropertyName'] || 'name';
|
1002
|
+
// this.defaultFilter = this.route.snapshot.data['defaultFilter'] || null;
|
1003
|
+
if (!this.modelService) {
|
1004
|
+
const SERVICE_TOKEN = this.route.snapshot.data['requiredService'];
|
1005
|
+
this.modelService = this.injector.get(SERVICE_TOKEN);
|
1006
|
+
}
|
1007
|
+
this.model = this.modelService.newModel();
|
1008
|
+
this.title = this.model.modelConfig.formTitle;
|
1009
|
+
this.getListLayout();
|
1010
|
+
const currentUrlSegments = this.router.url.split('/').map(segment => new UrlSegment(segment, {}));
|
1011
|
+
this.basePath = currentUrlSegments.map(segment => segment.path).join('/');
|
1012
|
+
this.router.events.subscribe(event => {
|
1013
|
+
if (event instanceof NavigationStart) {
|
1014
|
+
// Navigation to another page is about to occur
|
1015
|
+
this.data = [];
|
1016
|
+
this.pageIndex = 1;
|
1017
|
+
// Perform actions or update component as needed
|
1018
|
+
}
|
1019
|
+
});
|
1020
|
+
}
|
1021
|
+
setValueFromSnapshot(component, snapshot, key, defaultValue) {
|
1022
|
+
if (component[key] === undefined) {
|
1023
|
+
let dataFromSnapshot = snapshot.data[key];
|
1024
|
+
if (!dataFromSnapshot)
|
1025
|
+
dataFromSnapshot = snapshot.params[key];
|
1026
|
+
component[key] = dataFromSnapshot !== undefined ? dataFromSnapshot : defaultValue;
|
1027
|
+
}
|
1028
|
+
}
|
1029
|
+
async ionViewWillEnter() {
|
1030
|
+
this.data = [];
|
1031
|
+
const loading = await this.loadingCtrl.create({
|
1032
|
+
message: this.translate.instant('General.Loading'),
|
1033
|
+
spinner: 'circles',
|
1034
|
+
});
|
1035
|
+
loading.present();
|
1036
|
+
this.loadData(null, null, loading);
|
1037
|
+
}
|
1038
|
+
async handleChange(event) {
|
1039
|
+
const loading = await this.loadingCtrl.create({
|
1040
|
+
message: this.translate.instant('General.Loading'),
|
1041
|
+
spinner: 'circles',
|
1042
|
+
});
|
1043
|
+
loading.present();
|
1044
|
+
const query = event.target.value.toLowerCase();
|
1045
|
+
this.pageIndex = 1;
|
1046
|
+
this.loadData(null, query, loading);
|
1047
|
+
// this.results = this.data.filter((d) => d.toLowerCase().indexOf(query) > -1);
|
1048
|
+
}
|
1049
|
+
loadData(event = null, filterValue = undefined, loading = null) {
|
1050
|
+
const filters = [];
|
1051
|
+
let sorts = '';
|
1052
|
+
if (this.defaultSort) {
|
1053
|
+
if (this.defaultSortDirection === 'desc') {
|
1054
|
+
sorts = '-' + this.defaultSort;
|
1055
|
+
}
|
1056
|
+
else {
|
1057
|
+
sorts = this.defaultSort;
|
1058
|
+
}
|
1059
|
+
}
|
1060
|
+
if (this.showSerach) {
|
1061
|
+
if (filterValue) {
|
1062
|
+
const y = '(' + this.searchFields.replace(',', '|') + ')';
|
1063
|
+
filters.push(y + '@=*' + filterValue);
|
1064
|
+
}
|
1065
|
+
}
|
1066
|
+
if (this.defaultFilter) {
|
1067
|
+
filters.push(this.defaultFilter);
|
1068
|
+
}
|
1069
|
+
setTimeout(() => {
|
1070
|
+
const filtersValue = filters.join(', ');
|
1071
|
+
this.modelService.getAll(this.pageIndex, this.pageSize, sorts, filtersValue, this.customInclude).subscribe((response) => {
|
1072
|
+
if (this.pageIndex !== response.getMeta().meta.count) {
|
1073
|
+
this.pageIndex++;
|
1074
|
+
}
|
1075
|
+
else {
|
1076
|
+
if (event)
|
1077
|
+
event.target.disabled = true;
|
1078
|
+
}
|
1079
|
+
if (filterValue || loading)
|
1080
|
+
this.data = response.getModels();
|
1081
|
+
else
|
1082
|
+
this.data = this.data.concat(response.getModels());
|
1083
|
+
if (event)
|
1084
|
+
event.target.complete();
|
1085
|
+
if (loading)
|
1086
|
+
loading.dismiss();
|
1087
|
+
});
|
1088
|
+
}, 700);
|
1089
|
+
}
|
1090
|
+
async handleRefresh(event) {
|
1091
|
+
const loading = await this.loadingCtrl.create({
|
1092
|
+
message: this.translate.instant('General.Loading'),
|
1093
|
+
spinner: 'circles',
|
1094
|
+
});
|
1095
|
+
loading.present();
|
1096
|
+
this.pageIndex = 1;
|
1097
|
+
this.loadData(null, null, loading);
|
1098
|
+
event.target.complete();
|
1099
|
+
}
|
1100
|
+
onAdd() {
|
1101
|
+
console.log(this.basePath);
|
1102
|
+
this.navCtrl.navigateForward(this.basePath + '/add');
|
1103
|
+
}
|
1104
|
+
editModel(model) {
|
1105
|
+
this.navCtrl.navigateForward(this.basePath + '/edit/' + model.id);
|
1106
|
+
}
|
1107
|
+
getListLayout() {
|
1108
|
+
if (!this.model) {
|
1109
|
+
this.model = this.modelService.newModel();
|
1110
|
+
}
|
1111
|
+
this.gridLayout = Reflect.getMetadata('IonicListLayout', this.model);
|
1112
|
+
}
|
1113
|
+
deleteModel(model) {
|
1114
|
+
const msg = 'Do you want to delete ' + model[this.deletePropertyName] + '?';
|
1115
|
+
this.dialogService.confirm(msg).then((value) => {
|
1116
|
+
if (value.data) {
|
1117
|
+
this.modelService.delete(model.id).subscribe(() => {
|
1118
|
+
const tempData = [];
|
1119
|
+
// this.selectedObject.emit(null);
|
1120
|
+
this.data.map((item) => {
|
1121
|
+
if (item.id !== model.id) {
|
1122
|
+
tempData.push(item);
|
1123
|
+
}
|
1124
|
+
});
|
1125
|
+
this.data = tempData;
|
1126
|
+
});
|
1127
|
+
}
|
1128
|
+
});
|
1129
|
+
}
|
1130
|
+
getCelValue(row, propertyName) {
|
1131
|
+
if (!row)
|
1132
|
+
return "";
|
1133
|
+
// if (propertyName == 'kompetenzenStdev')
|
1134
|
+
// console.log(propertyName);
|
1135
|
+
if (propertyName.indexOf('.') === -1) {
|
1136
|
+
var gridLayout = this.gridLayout.find(f => f.key.indexOf(propertyName) > -1);
|
1137
|
+
return this.getFormatedValue(gridLayout, row[propertyName]);
|
1138
|
+
}
|
1139
|
+
else {
|
1140
|
+
const prop = propertyName.split('.')[0];
|
1141
|
+
const subProp = propertyName.replace(prop + '.', '');
|
1142
|
+
return this.getCelValue(row[prop], subProp);
|
1143
|
+
}
|
1144
|
+
}
|
1145
|
+
getFormatedValue(gridLayout, value) {
|
1146
|
+
if (gridLayout) {
|
1147
|
+
switch (gridLayout.formating) {
|
1148
|
+
case GridLayoutFormat.date:
|
1149
|
+
return this.datePipe.transform(value, gridLayout.customFormat);
|
1150
|
+
break;
|
1151
|
+
case GridLayoutFormat.number:
|
1152
|
+
return this.numberPipe.transform(value, gridLayout.customFormat);
|
1153
|
+
case GridLayoutFormat.percent:
|
1154
|
+
const valuePrc = value / 100;
|
1155
|
+
return this.percentPipe.transform(valuePrc, gridLayout.customFormat);
|
1156
|
+
default:
|
1157
|
+
return value;
|
1158
|
+
break;
|
1159
|
+
}
|
1160
|
+
}
|
1161
|
+
return value;
|
1162
|
+
}
|
1163
|
+
deleteEnabled(model) {
|
1164
|
+
if (this.deleteDisableRule) {
|
1165
|
+
return this.evaluateRule(this.deleteDisableRule, model);
|
1166
|
+
}
|
1167
|
+
else {
|
1168
|
+
return true;
|
1169
|
+
}
|
1170
|
+
}
|
1171
|
+
evaluateRule(rules, model) {
|
1172
|
+
let result = true;
|
1173
|
+
rules.forEach(rule => {
|
1174
|
+
let jsonRule;
|
1175
|
+
if (typeof rule.rule === 'string') {
|
1176
|
+
jsonRule = JSON.parse(rule.rule);
|
1177
|
+
}
|
1178
|
+
else {
|
1179
|
+
jsonRule = rule.rule;
|
1180
|
+
}
|
1181
|
+
if (rule.parameters) {
|
1182
|
+
const data = '{' + rule.parameters.map((item) => {
|
1183
|
+
return '"' + item + '":"' + model[item] + '"';
|
1184
|
+
}).join(',') + '}';
|
1185
|
+
result = jsonLogic.apply(jsonRule, JSON.parse(data));
|
1186
|
+
}
|
1187
|
+
else {
|
1188
|
+
result = jsonLogic.apply(jsonRule);
|
1189
|
+
}
|
1190
|
+
});
|
1191
|
+
return result;
|
1192
|
+
}
|
1193
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RslIonicGridComponent, deps: [{ token: i1$1.Router }, { token: i1$1.ActivatedRoute }, { token: i2.TranslateService }, { token: i3$1.Location }, { token: i0.Injector }, { token: i4.LoadingController }, { token: i4.NavController }, { token: IonicDialogService }, { token: i3$1.DatePipe }, { token: i3$1.DecimalPipe }, { token: i3$1.PercentPipe }], target: i0.ɵɵFactoryTarget.Component }); }
|
1194
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.1", type: RslIonicGridComponent, isStandalone: true, selector: "rsl-ionic-grid", inputs: { showSerach: "showSerach", searchFields: "searchFields", customInclude: "customInclude", defaultSort: "defaultSort", defaultSortDirection: "defaultSortDirection", deletePropertyName: "deletePropertyName", defaultFilter: "defaultFilter", showHeader: "showHeader", deleteDisableRule: "deleteDisableRule", model: "model", modelService: "modelService" }, ngImport: i0, template: "<ion-header *ngIf=\"showHeader\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n <ng-container [ngTemplateOutlet]=\"search\"></ng-container>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n\n <ion-refresher slot=\"fixed\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <ion-list>\n <ng-container *ngFor=\"let item of data\">\n <ion-item-sliding>\n <ng-container [ngTemplateOutlet]=\"listItem\" [ngTemplateOutletContext]=\"{item}\"></ng-container>\n <ion-item-options *ngIf=\"deleteEnabled(item)\" side=\"end\">\n <ion-item-option color=\"danger\">\n <ion-icon slot=\"icon-only\" name=\"trash\" (click)='deleteModel(item)'></ion-icon>\n </ion-item-option>\n </ion-item-options>\n </ion-item-sliding>\n </ng-container>\n </ion-list>\n <ion-infinite-scroll threshold=\"100px\" (ionInfinite)=\"loadData($event)\">\n <ion-infinite-scroll-content loadingSpinner=\"bubbles\" loadingText=\"Loading more data...\">\n </ion-infinite-scroll-content>\n </ion-infinite-scroll>\n\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\n <ion-button slot=\"end\" (click)=\"onAdd()\" fill=\"clear\">\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\n </ion-button>\n</ng-template>\n\n<ng-template #search>\n <ion-toolbar *ngIf=\"showSerach\">\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\n </ion-toolbar>\n</ng-template>\n\n<ng-template #listItem let-item='item'>\n <ion-item button (click)='editModel(item)'>\n <ion-label>\n <ng-container *ngFor=\"let row of gridLayout\">\n <h2 *ngIf=\"row.primary\"> {{getCelValue(item,row.key)}} </h2>\n <h3 *ngIf=\"!row.primary\">{{getCelValue(item,row.key)}} </h3>\n </ng-container>\n </ion-label>\n </ion-item>\n</ng-template>", dependencies: [{ kind: "ngmodule", type: RslIonicModuleModule }, { kind: "directive", type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.IonBackButton, selector: "ion-back-button", inputs: ["color", "defaultHref", "disabled", "icon", "mode", "routerAnimation", "text", "type"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i4.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: i4.IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i4.IonItemOption, selector: "ion-item-option", inputs: ["color", "disabled", "download", "expandable", "href", "mode", "rel", "target", "type"] }, { kind: "component", type: i4.IonItemOptions, selector: "ion-item-options", inputs: ["side"] }, { kind: "component", type: i4.IonItemSliding, selector: "ion-item-sliding", inputs: ["disabled"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i4.IonMenuButton, selector: "ion-menu-button", inputs: ["autoHide", "color", "disabled", "menu", "mode", "type"] }, { kind: "component", type: i4.IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: i4.IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: i4.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }, { kind: "component", type: i4.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i4.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i4.TextValueAccessor, selector: "ion-input:not([type=number]),ion-textarea,ion-searchbar" }, { kind: "directive", type: i4.IonBackButtonDelegate, selector: "ion-back-button", inputs: ["defaultHref", "routerAnimation"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
|
1195
|
+
}
|
1196
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.1", ngImport: i0, type: RslIonicGridComponent, decorators: [{
|
1197
|
+
type: Component,
|
1198
|
+
args: [{ standalone: true, selector: 'rsl-ionic-grid', imports: [RslIonicModuleModule], template: "<ion-header *ngIf=\"showHeader\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-menu-button></ion-menu-button>\n <ion-back-button></ion-back-button>\n </ion-buttons>\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\n </ion-toolbar>\n <ng-container [ngTemplateOutlet]=\"search\"></ng-container>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n\n <ion-refresher slot=\"fixed\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content></ion-refresher-content>\n </ion-refresher>\n\n <ion-list>\n <ng-container *ngFor=\"let item of data\">\n <ion-item-sliding>\n <ng-container [ngTemplateOutlet]=\"listItem\" [ngTemplateOutletContext]=\"{item}\"></ng-container>\n <ion-item-options *ngIf=\"deleteEnabled(item)\" side=\"end\">\n <ion-item-option color=\"danger\">\n <ion-icon slot=\"icon-only\" name=\"trash\" (click)='deleteModel(item)'></ion-icon>\n </ion-item-option>\n </ion-item-options>\n </ion-item-sliding>\n </ng-container>\n </ion-list>\n <ion-infinite-scroll threshold=\"100px\" (ionInfinite)=\"loadData($event)\">\n <ion-infinite-scroll-content loadingSpinner=\"bubbles\" loadingText=\"Loading more data...\">\n </ion-infinite-scroll-content>\n </ion-infinite-scroll>\n\n</ion-content>\n\n<ng-template #header>\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\n <ion-button slot=\"end\" (click)=\"onAdd()\" fill=\"clear\">\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\n </ion-button>\n</ng-template>\n\n<ng-template #search>\n <ion-toolbar *ngIf=\"showSerach\">\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\n </ion-toolbar>\n</ng-template>\n\n<ng-template #listItem let-item='item'>\n <ion-item button (click)='editModel(item)'>\n <ion-label>\n <ng-container *ngFor=\"let row of gridLayout\">\n <h2 *ngIf=\"row.primary\"> {{getCelValue(item,row.key)}} </h2>\n <h3 *ngIf=\"!row.primary\">{{getCelValue(item,row.key)}} </h3>\n </ng-container>\n </ion-label>\n </ion-item>\n</ng-template>" }]
|
1199
|
+
}], ctorParameters: function () { return [{ type: i1$1.Router }, { type: i1$1.ActivatedRoute }, { type: i2.TranslateService }, { type: i3$1.Location }, { type: i0.Injector }, { type: i4.LoadingController }, { type: i4.NavController }, { type: IonicDialogService }, { type: i3$1.DatePipe }, { type: i3$1.DecimalPipe }, { type: i3$1.PercentPipe }]; }, propDecorators: { showSerach: [{
|
1200
|
+
type: Input
|
1201
|
+
}], searchFields: [{
|
1202
|
+
type: Input
|
1203
|
+
}], customInclude: [{
|
1204
|
+
type: Input
|
1205
|
+
}], defaultSort: [{
|
1206
|
+
type: Input
|
1207
|
+
}], defaultSortDirection: [{
|
1208
|
+
type: Input
|
1209
|
+
}], deletePropertyName: [{
|
1210
|
+
type: Input
|
1211
|
+
}], defaultFilter: [{
|
1212
|
+
type: Input
|
1213
|
+
}], showHeader: [{
|
1214
|
+
type: Input
|
1215
|
+
}], deleteDisableRule: [{
|
1216
|
+
type: Input
|
1217
|
+
}], model: [{
|
1218
|
+
type: Input
|
1219
|
+
}], modelService: [{
|
1220
|
+
type: Input
|
1221
|
+
}] } });
|
1222
|
+
|
1223
|
+
function IonicDataTableLayout(config) {
|
1224
|
+
return (target, propertyName) => {
|
1225
|
+
const annotations = Reflect.getMetadata('IonicDataTableLayout', target) || [];
|
1226
|
+
config.prop = propertyName;
|
1227
|
+
config.visible = config.visible === undefined ? true : config.visible;
|
1228
|
+
annotations.push(config);
|
1229
|
+
Reflect.defineMetadata('IonicDataTableLayout', annotations, target);
|
1230
|
+
};
|
1231
|
+
}
|
1232
|
+
|
1233
|
+
function IonicListLayout(config) {
|
1234
|
+
return (target, propertyName) => {
|
1235
|
+
const annotations = Reflect.getMetadata('IonicListLayout', target) || [];
|
1236
|
+
config.key = propertyName;
|
1237
|
+
annotations.push(config);
|
1238
|
+
Reflect.defineMetadata('IonicListLayout', annotations, target);
|
1239
|
+
};
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
/*
|
1243
|
+
* Public API Surface of ionic
|
1244
|
+
*/
|
1245
|
+
|
1246
|
+
/**
|
1247
|
+
* Generated bundle index. Do not edit.
|
1248
|
+
*/
|
1249
|
+
|
1250
|
+
export { AccordionWrapperComponent, GenericIonicCrudComponent, IonicDataTableLayout, IonicDialogService, IonicListLayout, PanelWrapperComponent, RepeatTypeComponent, RslIonicDataTableComponent, RslIonicGridComponent, TranslateExtension, fieldMatchValidator, registerTranslateExtension };
|
1251
|
+
//# sourceMappingURL=rosoftlab-ionic.mjs.map
|