@rosoftlab/ionic 1.0.5-alpha-7 → 1.0.5-alpha-9

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.
@@ -10,10 +10,10 @@ import * as i6$1 from '@ngx-formly/core/json-schema';
10
10
  import * as i2 from '@ngx-translate/core';
11
11
  import { TranslateModule, TranslateService } from '@ngx-translate/core';
12
12
  import * as _ from 'lodash';
13
- import { Observable, from, map } from 'rxjs';
13
+ import { Observable, from, Subject, map } from 'rxjs';
14
14
  import * as i4 from '@ionic/angular';
15
15
  import { IonicModule } from '@ionic/angular';
16
- import * as i7 from '@ngx-formly/core';
16
+ import * as i8 from '@ngx-formly/core';
17
17
  import { FormlyModule, FORMLY_CONFIG, FieldType, FieldArrayType, FieldWrapper } from '@ngx-formly/core';
18
18
  import { FormlyIonicModule } from '@ngx-formly/ionic';
19
19
  import * as i6 from '@swimlane/ngx-datatable';
@@ -23,11 +23,13 @@ import { SmActionService } from '@rosoftlab/statemachine';
23
23
  import * as i3$1 from 'ngx-filesaver';
24
24
  import * as XLSX from 'xlsx';
25
25
  import * as i1$3 from '@rosoftlab/core';
26
- import { readFileAsync, getValueFromJsonData, MetadataStorage, GridLayoutFormat } from '@rosoftlab/core';
26
+ import { readFileAsync, getValueFromJsonData, MetadataStorage, BaseTableImplementation, BaseService, GridLayoutFormat } from '@rosoftlab/core';
27
27
  import { addIcons } from 'ionicons';
28
28
  import { add } from 'ionicons/icons';
29
29
  import * as jsonLogic from 'json-logic-js/logic.js';
30
30
  import * as i4$1 from '@rosoftlab/rdict';
31
+ import { ReactiveDictionary } from '@rosoftlab/rdict';
32
+ import { takeUntil } from 'rxjs/operators';
31
33
 
32
34
  class IonicDialogService {
33
35
  constructor(alertController) {
@@ -383,7 +385,7 @@ class RepeatDatatableComponent extends FieldArrayType {
383
385
  });
384
386
  }
385
387
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RepeatDatatableComponent, deps: [{ token: IonicDialogService }, { token: i2.TranslateService }, { token: i3$1.FileSaverService }], target: i0.ɵɵFactoryTarget.Component }); }
386
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", type: RepeatDatatableComponent, isStandalone: true, selector: "app-repeat-datatable", viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "defaultColumn", first: true, predicate: ["defaultColumn"], descendants: true, static: true }, { propertyName: "actionsTmpl", first: true, predicate: ["actionsTmpl"], descendants: true, static: 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<ngx-datatable #table class=\"material fullscreen rls-server-scrolling\" [rows]=\"model\" [columns]=\"props['columns']\" [columnMode]=\"props['columnMode']\"\r\n [rowHeight]=\"props['rowHeight']\" [headerHeight]=\"props['headerHeight']\" [footerHeight]=\"props['footerHeight']\" [limit]=\"props['limit']\"\r\n [scrollbarH]=\"props['scrollbarH']\" [reorderable]=\"props['reorderable']\" [externalSorting]=\"true\">\r\n <ng-template #defaultColumn ngx-datatable-cell-template let-rowIndex=\"rowIndex\" let-value=\"value\" let-row=\"row\"\r\n let-column=\"column\">\r\n <formly-field class=\"formly-ion-list-item\" [field]=\"getField(field, column, rowIndex)\"></formly-field>\r\n </ng-template>\r\n</ngx-datatable>\r\n\r\n<ng-template #actionsTmpl let-row=\"row\" let-value=\"value\" let-rowIndex=\"rowIndex\">\r\n <ion-button style=\"height: 100%;\" fill=\"clear\"[disabled]=\"props.disabled\" (click)='remove(rowIndex)'>\r\n <ion-icon color=\"danger\" slot=\"icon-only\" name=\"trash\" (click)='remove(rowIndex)'></ion-icon>\r\n </ion-button>\r\n</ng-template>\r\n\r\n<ng-template #search>\r\n <ion-toolbar *ngIf=\"showSearch\">\r\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\r\n </ion-toolbar>\r\n</ng-template>", styles: [".rls-server-scrolling{height:calc(100vh - 110px);position:relative!important}::ng-deep .datatable-body-cell{padding:0!important}::ng-deep .datatable-body-cell-label{height:100%!important}::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: WrappersModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "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-input-otp[type=text],ion-textarea,ion-searchbar" }, { kind: "component", type: i6.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"] }, { kind: "directive", type: i6.DataTableColumnCellDirective, selector: "[ngx-datatable-cell-template]" }, { kind: "component", type: i7.LegacyFormlyField, selector: "formly-field" }] }); }
388
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", type: RepeatDatatableComponent, isStandalone: true, selector: "app-repeat-datatable", viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "defaultColumn", first: true, predicate: ["defaultColumn"], descendants: true, static: true }, { propertyName: "actionsTmpl", first: true, predicate: ["actionsTmpl"], descendants: true, static: 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<ngx-datatable #table class=\"material fullscreen rls-server-scrolling\" [rows]=\"model\" [columns]=\"props['columns']\" [columnMode]=\"props['columnMode']\"\r\n [rowHeight]=\"props['rowHeight']\" [headerHeight]=\"props['headerHeight']\" [footerHeight]=\"props['footerHeight']\" [limit]=\"props['limit']\"\r\n [scrollbarH]=\"props['scrollbarH']\" [reorderable]=\"props['reorderable']\" [externalSorting]=\"true\">\r\n <ng-template #defaultColumn ngx-datatable-cell-template let-rowIndex=\"rowIndex\" let-value=\"value\" let-row=\"row\"\r\n let-column=\"column\">\r\n <formly-field class=\"formly-ion-list-item\" [field]=\"getField(field, column, rowIndex)\"></formly-field>\r\n </ng-template>\r\n</ngx-datatable>\r\n\r\n<ng-template #actionsTmpl let-row=\"row\" let-value=\"value\" let-rowIndex=\"rowIndex\">\r\n <ion-button style=\"height: 100%;\" fill=\"clear\"[disabled]=\"props.disabled\" (click)='remove(rowIndex)'>\r\n <ion-icon color=\"danger\" slot=\"icon-only\" name=\"trash\" (click)='remove(rowIndex)'></ion-icon>\r\n </ion-button>\r\n</ng-template>\r\n\r\n<ng-template #search>\r\n <ion-toolbar *ngIf=\"showSearch\">\r\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\r\n </ion-toolbar>\r\n</ng-template>", styles: [".rls-server-scrolling{height:calc(100vh - 110px);position:relative!important}::ng-deep .datatable-body-cell{padding:0!important}::ng-deep .datatable-body-cell-label{height:100%!important}::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: WrappersModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "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-input-otp[type=text],ion-textarea,ion-searchbar" }, { kind: "component", type: i6.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"] }, { kind: "directive", type: i6.DataTableColumnCellDirective, selector: "[ngx-datatable-cell-template]" }, { kind: "component", type: i8.LegacyFormlyField, selector: "formly-field" }] }); }
387
389
  }
388
390
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RepeatDatatableComponent, decorators: [{
389
391
  type: Component,
@@ -509,7 +511,7 @@ class RepeatTypeComponent extends FieldArrayType {
509
511
  this.fileSaverService.save(blob, this.exportDataProp.fileName);
510
512
  }
511
513
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RepeatTypeComponent, deps: [{ token: IonicDialogService }, { token: i2.TranslateService }, { token: i3$1.FileSaverService }], target: i0.ɵɵFactoryTarget.Component }); }
512
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", 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=\"showSearch\">\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.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i4.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i4.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "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-input-otp[type=text],ion-textarea,ion-searchbar" }, { kind: "component", type: i7.LegacyFormlyField, selector: "formly-field" }] }); }
514
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", 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=\"showSearch\">\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.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i4.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i4.IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "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-input-otp[type=text],ion-textarea,ion-searchbar" }, { kind: "component", type: i8.LegacyFormlyField, selector: "formly-field" }] }); }
513
515
  }
514
516
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: RepeatTypeComponent, decorators: [{
515
517
  type: Component,
@@ -621,7 +623,7 @@ class RslIonicModuleModule {
621
623
  IonicModule,
622
624
  ReactiveFormsModule,
623
625
  FormlyIonicModule,
624
- NgxDatatableModule, TranslateModule, i7.FormlyModule], exports: [CommonModule,
626
+ NgxDatatableModule, TranslateModule, i8.FormlyModule], exports: [CommonModule,
625
627
  IonicModule,
626
628
  ReactiveFormsModule,
627
629
  FormlyIonicModule,
@@ -926,7 +928,7 @@ class GenericIonicCrudComponent {
926
928
  return rvalue;
927
929
  }
928
930
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: GenericIonicCrudComponent, deps: [{ token: i1$1.UntypedFormBuilder }, { token: i1$2.Router }, { token: i1$2.ActivatedRoute }, { token: IonicDialogService }, { token: i2.TranslateService }, { token: i3.Location }, { token: i0.Injector }, { token: i6$1.FormlyJsonschema }], target: i0.ɵɵFactoryTarget.Component }); }
929
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", type: GenericIonicCrudComponent, isStandalone: true, selector: "rslc-ionic-crud", ngImport: i0, template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n</ion-header>\r\n\r\n<ion-content [fullscreen]=\"true\">\r\n <ng-container *ngIf=\"!isLoading\">\r\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n </form>\r\n </ng-container>\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\r\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\r\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\r\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\r\n </ion-button>\r\n</ng-template>", styles: [""], dependencies: [{ kind: "ngmodule", type: RslIonicModuleModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "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: "component", type: i4.IonBackButton, selector: "ion-back-button" }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i7.LegacyFormlyForm, selector: "formly-form" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
931
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", type: GenericIonicCrudComponent, isStandalone: true, selector: "rslc-ionic-crud", ngImport: i0, template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n</ion-header>\r\n\r\n<ion-content [fullscreen]=\"true\">\r\n <ng-container *ngIf=\"!isLoading\">\r\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n </form>\r\n </ng-container>\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\r\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\r\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\r\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\r\n </ion-button>\r\n</ng-template>", styles: [""], dependencies: [{ kind: "ngmodule", type: RslIonicModuleModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "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: "component", type: i4.IonBackButton, selector: "ion-back-button" }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i8.LegacyFormlyForm, selector: "formly-form" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
930
932
  }
931
933
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: GenericIonicCrudComponent, decorators: [{
932
934
  type: Component,
@@ -1216,6 +1218,667 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImpor
1216
1218
  type: Input
1217
1219
  }] } });
1218
1220
 
1221
+ class GenericIonicCrudPageComponent {
1222
+ //#endregion
1223
+ constructor(fb, router, route, dialogService, translate, location, injector, formlyJsonschema) {
1224
+ this.fb = fb;
1225
+ this.router = router;
1226
+ this.route = route;
1227
+ this.dialogService = dialogService;
1228
+ this.translate = translate;
1229
+ this.location = location;
1230
+ this.injector = injector;
1231
+ this.formlyJsonschema = formlyJsonschema;
1232
+ this.isLoading = true;
1233
+ this.changeUrlRoute = true;
1234
+ this.options = {};
1235
+ const SERVICE_TOKEN = route.snapshot.data['requiredService'];
1236
+ this.modelService = this.injector.get(SERVICE_TOKEN);
1237
+ this.modelService = this.injector.get(SERVICE_TOKEN);
1238
+ this.confirmQuestion = this.translate.instant('General.Discard.Question');
1239
+ this.confirmButton = this.translate.instant('General.Discard.ConfirmButton');
1240
+ this.saveMessage = this.translate.instant('General.Save.Message');
1241
+ }
1242
+ ionViewWillLeave() {
1243
+ this.options.resetModel();
1244
+ this.baseForm.reset();
1245
+ }
1246
+ afterSave(model) {
1247
+ return new Observable((observer) => {
1248
+ observer.next(model);
1249
+ observer.complete();
1250
+ });
1251
+ }
1252
+ beforeSave(model) {
1253
+ return new Observable((observer) => {
1254
+ observer.next(model);
1255
+ observer.complete();
1256
+ });
1257
+ }
1258
+ ngOnInit() {
1259
+ this.initForm();
1260
+ }
1261
+ initForm(customInclude = '', newModelId = null, model = null) {
1262
+ if (model === null) {
1263
+ this.modelId = this.route.snapshot.paramMap.get('id') ?? newModelId;
1264
+ this.isEdit = false;
1265
+ if (this.modelId) {
1266
+ this.modelService.get(this.modelId, customInclude).subscribe((value) => {
1267
+ this.isEdit = true;
1268
+ this.generateForm(value);
1269
+ });
1270
+ }
1271
+ else {
1272
+ if (this.changeUrlRoute) {
1273
+ const addUrl = this.router.createUrlTree([]).toString();
1274
+ this.editRoute = this.router.createUrlTree([addUrl.replace('add', 'edit')]).toString();
1275
+ }
1276
+ // }
1277
+ this.generateForm(this.modelService.newModel());
1278
+ }
1279
+ }
1280
+ else {
1281
+ this.modelId = model.id;
1282
+ this.isEdit = true;
1283
+ this.generateForm(model);
1284
+ }
1285
+ }
1286
+ generateForm(model) {
1287
+ this.isLoading = false;
1288
+ this.modelId = model.id;
1289
+ this.model = model;
1290
+ this.origModel = _.cloneDeep(model);
1291
+ ;
1292
+ this.title = this.model.modelConfig.formTitle;
1293
+ this.baseForm = new UntypedFormGroup({}); //= this.modelService.toFormGroup(this.fb, model);
1294
+ this.afterFormGenerated();
1295
+ this.fields = this.modelService.getFormlyFields(this.model);
1296
+ }
1297
+ afterFormGenerated() {
1298
+ }
1299
+ getFromGroup(formGroup = null) {
1300
+ if (!formGroup)
1301
+ return this.baseForm;
1302
+ if (formGroup instanceof UntypedFormGroup)
1303
+ return formGroup;
1304
+ return this.baseForm.controls[formGroup];
1305
+ }
1306
+ validateAllFormFields(formGroup = null) {
1307
+ const fg = this.getFromGroup(formGroup);
1308
+ Object.keys(fg.controls).forEach(field => {
1309
+ // console.log(field);
1310
+ const control = fg.get(field);
1311
+ if (control instanceof UntypedFormControl) {
1312
+ control.markAsTouched({ onlySelf: true });
1313
+ }
1314
+ else if (control instanceof UntypedFormGroup) {
1315
+ this.validateAllFormFields(control);
1316
+ }
1317
+ });
1318
+ }
1319
+ isFieldValid(field, formGroup = null) {
1320
+ const fg = this.getFromGroup(formGroup);
1321
+ const filedControl = fg.get(field);
1322
+ return !filedControl.valid && filedControl.touched;
1323
+ }
1324
+ isFieldValidFromArray(arrayIndex, field, arrayName = 'formArray') {
1325
+ const fieldControl = this.baseForm.get(arrayName).get([arrayIndex]).get(field);
1326
+ return !fieldControl.valid && fieldControl.touched;
1327
+ }
1328
+ displayFieldCss(field) {
1329
+ return {
1330
+ 'has-error': this.isFieldValid(field),
1331
+ 'has-feedback': this.isFieldValid(field)
1332
+ };
1333
+ }
1334
+ onCancel() {
1335
+ this.router.navigate([this.cancelRoute]);
1336
+ }
1337
+ onSave() {
1338
+ this.saveModel(this.baseForm);
1339
+ }
1340
+ onSubmit(model) {
1341
+ this.saveModel(this.baseForm);
1342
+ }
1343
+ saveModel(formGroup = null) {
1344
+ const fg = this.getFromGroup(formGroup);
1345
+ const that = this;
1346
+ if (fg) {
1347
+ if (fg.valid) {
1348
+ this.beforeSave(this.model).subscribe(_ => {
1349
+ this.modelService.save(this.model, this.modelId, this.origModel).subscribe((newModel) => {
1350
+ this.model = newModel;
1351
+ this.modelId = newModel.id;
1352
+ if (this.editRoute) {
1353
+ this.isEdit = true;
1354
+ if (this.changeUrlRoute) {
1355
+ const url = this.router.createUrlTree([this.editRoute, this.modelId]).toString();
1356
+ this.location.replaceState(url);
1357
+ }
1358
+ }
1359
+ this.afterSave(newModel).subscribe((val) => {
1360
+ from(this.dialogService.showSaveMessage(this.saveMessage)).subscribe(d => {
1361
+ this.options.updateInitialValue();
1362
+ fg.markAsPristine();
1363
+ });
1364
+ });
1365
+ }, err => {
1366
+ this.serverErrors(err);
1367
+ });
1368
+ });
1369
+ }
1370
+ else {
1371
+ this.validateAllFormFields(formGroup);
1372
+ }
1373
+ }
1374
+ }
1375
+ serverErrors(err) {
1376
+ if (err.error) {
1377
+ if (err.error.errors) {
1378
+ const validationErrors = err.error.errors;
1379
+ if (Array.isArray(validationErrors)) {
1380
+ validationErrors.forEach(prop => {
1381
+ const formControl = this.baseForm.get(this.firstCharToLowerCase(prop));
1382
+ if (formControl) {
1383
+ // activate the error message
1384
+ formControl.setErrors({
1385
+ serverError: { message: validationErrors[prop].join('\n') }
1386
+ });
1387
+ }
1388
+ });
1389
+ }
1390
+ else {
1391
+ const keys = Object.keys(validationErrors);
1392
+ keys.forEach(prop => {
1393
+ const formControl = this.baseForm.get(this.firstCharToLowerCase(prop));
1394
+ if (formControl) {
1395
+ // activate the error message
1396
+ formControl.setErrors({
1397
+ serverError: { message: validationErrors[prop].join('\n') }
1398
+ });
1399
+ }
1400
+ });
1401
+ }
1402
+ }
1403
+ }
1404
+ }
1405
+ firstCharToLowerCase(str) {
1406
+ if (str.length === 0) {
1407
+ return str; // Return an empty string if the input is empty
1408
+ }
1409
+ const firstChar = str.charAt(0).toLowerCase();
1410
+ const restOfString = str.slice(1);
1411
+ return firstChar + restOfString;
1412
+ }
1413
+ async canDeactivate() {
1414
+ if (!this.baseForm.dirty) {
1415
+ return true;
1416
+ }
1417
+ var result = await this.dialogService.confirm(this.confirmQuestion, null, this.confirmButton);
1418
+ return result;
1419
+ }
1420
+ getFiledName(filedTranslationKey) {
1421
+ return { field: this.translate.instant(filedTranslationKey) };
1422
+ }
1423
+ getCustomErrorMessage(error, fieldLabel) {
1424
+ return '';
1425
+ }
1426
+ getErrorMessageFromArray(arrayIndex, field, filedTranslationKey, arrayName = 'formArray') {
1427
+ const fieldControl = this.baseForm.get(arrayName).get([arrayIndex]).get(field);
1428
+ return this.getErrorMessageForField(fieldControl, filedTranslationKey);
1429
+ }
1430
+ getErrorMessage(field, filedTranslationKey, formGroup = null) {
1431
+ const fg = this.getFromGroup(formGroup);
1432
+ return this.getErrorMessageForField(fg.get(field), filedTranslationKey);
1433
+ }
1434
+ getErrorMessageForField(fieldControl, filedTranslationKey) {
1435
+ const error = fieldControl.errors;
1436
+ const fieldLabel = this.translate.instant(filedTranslationKey);
1437
+ let rvalue = '';
1438
+ if (error !== null) {
1439
+ if (error['required'] === true) {
1440
+ rvalue = this.translate.instant('General.Field.Required', { field: fieldLabel });
1441
+ }
1442
+ if (error['minlength']) {
1443
+ rvalue = this.translate.instant('General.Field.MinLength', { field: fieldLabel, requiredLength: error.minlength.requiredLength });
1444
+ }
1445
+ if (error['email'] === true) {
1446
+ rvalue = this.translate.instant('General.Field.InvalidEmail');
1447
+ }
1448
+ if (error['url'] === true) {
1449
+ rvalue = this.translate.instant('General.Field.InvalidUrl');
1450
+ }
1451
+ if (error['serverError']) {
1452
+ rvalue = error['serverError'];
1453
+ }
1454
+ if (rvalue === '') {
1455
+ rvalue = this.getCustomErrorMessage(error, fieldLabel);
1456
+ }
1457
+ }
1458
+ return rvalue;
1459
+ }
1460
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: GenericIonicCrudPageComponent, deps: [{ token: i1$1.UntypedFormBuilder }, { token: i1$2.Router }, { token: i1$2.ActivatedRoute }, { token: IonicDialogService }, { token: i2.TranslateService }, { token: i3.Location }, { token: i0.Injector }, { token: i6$1.FormlyJsonschema }], target: i0.ɵɵFactoryTarget.Component }); }
1461
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", type: GenericIonicCrudPageComponent, isStandalone: true, selector: "generic-ionic-crud", ngImport: i0, template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n</ion-header>\r\n\r\n<ion-content [fullscreen]=\"true\">\r\n <ng-container *ngIf=\"!isLoading\">\r\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n </form>\r\n </ng-container>\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\r\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\r\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\r\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\r\n </ion-button>\r\n</ng-template>", styles: [""], dependencies: [{ kind: "ngmodule", type: RslIonicModuleModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "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: "component", type: i4.IonBackButton, selector: "ion-back-button" }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i8.LegacyFormlyForm, selector: "formly-form" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
1462
+ }
1463
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: GenericIonicCrudPageComponent, decorators: [{
1464
+ type: Component,
1465
+ args: [{ selector: 'generic-ionic-crud', imports: [RslIonicModuleModule], template: "<ion-header [translucent]=\"true\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\r\n <ng-container [ngTemplateOutlet]=\"header\"></ng-container>\r\n </ion-toolbar>\r\n</ion-header>\r\n\r\n<ion-content [fullscreen]=\"true\">\r\n <ng-container *ngIf=\"!isLoading\">\r\n <form [formGroup]=\"baseForm\" (ngSubmit)=\"onSubmit(model)\">\r\n <formly-form [form]=\"baseForm\" [fields]=\"fields\" [model]=\"model\" [options]=\"options\"></formly-form>\r\n </form>\r\n </ng-container>\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title |translate}}</ion-title>\r\n <ion-button *ngIf=\"!isLoading\" slot=\"end\" fill=\"clear\" (click)=\"onSave()\"\r\n [disabled]=\"baseForm.invalid || !baseForm.dirty\">\r\n <ion-icon size=\"large\" name=\"save\"></ion-icon>\r\n </ion-button>\r\n</ng-template>" }]
1466
+ }], ctorParameters: () => [{ type: i1$1.UntypedFormBuilder }, { type: i1$2.Router }, { type: i1$2.ActivatedRoute }, { type: IonicDialogService }, { type: i2.TranslateService }, { type: i3.Location }, { type: i0.Injector }, { type: i6$1.FormlyJsonschema }] });
1467
+
1468
+ class GenericIonicGridComponent extends BaseTableImplementation {
1469
+ constructor(router, translate, dialogServiceIonic, el, localFileService) {
1470
+ super();
1471
+ this.router = router;
1472
+ this.translate = translate;
1473
+ this.dialogServiceIonic = dialogServiceIonic;
1474
+ this.el = el;
1475
+ this.localFileService = localFileService;
1476
+ // @Input() modelService: BaseService<BaseModel>;
1477
+ // @Input() modelName: string | null = null;
1478
+ this.data = [];
1479
+ this.pageIndex = 1;
1480
+ this.pageSize = 30;
1481
+ this.columns = [];
1482
+ this.allColumns = [];
1483
+ this.referenceData = new Map();
1484
+ this.ColumnMode = ColumnMode;
1485
+ this.SelectionType = SelectionType;
1486
+ this.headerHeight = 50;
1487
+ this.rowHeight = 50;
1488
+ this.isRdict = false;
1489
+ this.destroy$ = new Subject();
1490
+ }
1491
+ async ngOnInit() {
1492
+ super.ngOnInit();
1493
+ const service = this.dataService;
1494
+ this.isRdict = false;
1495
+ if (service instanceof BaseService) {
1496
+ this.initStandard();
1497
+ }
1498
+ else if (service instanceof ReactiveDictionary) {
1499
+ this.rdict = service;
1500
+ await this.initRdict();
1501
+ }
1502
+ this.router.events.pipe(takeUntil(this.destroy$)).subscribe((event) => {
1503
+ if (event instanceof NavigationStart) {
1504
+ this.data = [];
1505
+ this.pageIndex = 1;
1506
+ }
1507
+ });
1508
+ }
1509
+ ngOnDestroy() {
1510
+ this.destroy$.next();
1511
+ this.destroy$.complete();
1512
+ }
1513
+ initStandard() {
1514
+ this.getListLayout();
1515
+ this.loadData();
1516
+ }
1517
+ async initRdict() {
1518
+ this.isRdict = true;
1519
+ const urlTree = this.router.url.split('?')[0];
1520
+ const currentUrlSegments = urlTree
1521
+ .split('/')
1522
+ .filter((segment) => segment !== '')
1523
+ .map((segment) => new UrlSegment(segment, {}));
1524
+ this.basePath = currentUrlSegments.map((segment) => segment.path).join('/');
1525
+ const filteredSegments = currentUrlSegments.filter((segment) => segment.path !== '');
1526
+ this.dictPath = filteredSegments.map((segment) => segment.path).join('.');
1527
+ this.model = filteredSegments.length > 0 ? filteredSegments[filteredSegments.length - 1].path : '';
1528
+ if (this.useView) {
1529
+ await this.getParentDict();
1530
+ }
1531
+ this.getListLayout();
1532
+ this.loadData();
1533
+ }
1534
+ async getParentDict() {
1535
+ const lastDotIndex = (this.dictPath ?? '').lastIndexOf('.');
1536
+ const parentPath = lastDotIndex !== -1 ? (this.dictPath ?? '').substring(0, lastDotIndex) : this.dictPath;
1537
+ this.parentDict = await this.rdict.asyncGet(parentPath);
1538
+ }
1539
+ onScroll(offsetY) {
1540
+ if (offsetY) {
1541
+ if (this.oldOffsetY !== offsetY) {
1542
+ this.oldOffsetY = offsetY;
1543
+ const viewHeight = this.el.nativeElement.getBoundingClientRect().height - this.headerHeight;
1544
+ if (!this.isLoading && offsetY + viewHeight >= this.data.length * this.rowHeight) {
1545
+ let limit = this.pageSize;
1546
+ if (this.data.length === 0) {
1547
+ const pageSize = Math.ceil(viewHeight / this.rowHeight);
1548
+ limit = Math.max(pageSize, this.pageSize);
1549
+ }
1550
+ this.pageSize = limit;
1551
+ this.loadData();
1552
+ }
1553
+ }
1554
+ }
1555
+ }
1556
+ async ionViewWillEnter() {
1557
+ this.data = [];
1558
+ this.loadData();
1559
+ }
1560
+ async handleChange(event) {
1561
+ this.filterValue = event.target.value.toLowerCase();
1562
+ this.data = [];
1563
+ this.pageIndex = 1;
1564
+ this.loadData();
1565
+ }
1566
+ async handleRefresh(event) {
1567
+ this.pageIndex = 1;
1568
+ this.data = [];
1569
+ this.loadData();
1570
+ if (event?.target) {
1571
+ event.target.complete();
1572
+ }
1573
+ }
1574
+ loadData() {
1575
+ if (this.isRdict) {
1576
+ this.loadDataRdict();
1577
+ }
1578
+ else {
1579
+ this.loadDataStandard();
1580
+ }
1581
+ }
1582
+ loadDataStandard() {
1583
+ const filters = [];
1584
+ let sorts = '';
1585
+ this.isLoading = true;
1586
+ if (this.defaultSort) {
1587
+ sorts = this.defaultSortDirection === 'desc' ? '-' + this.defaultSort : this.defaultSort;
1588
+ }
1589
+ if (this.showSearch && this.filterValue) {
1590
+ const searchFieldsValue = Array.isArray(this.searchFields) ? this.searchFields.join(',') : this.searchFields;
1591
+ if (!searchFieldsValue) {
1592
+ filters.push('@=*' + this.filterValue);
1593
+ }
1594
+ else {
1595
+ const y = '(' + searchFieldsValue.replace(',', '|') + ')';
1596
+ filters.push(y + '@=*' + this.filterValue);
1597
+ }
1598
+ }
1599
+ if (this.defaultFilter) {
1600
+ filters.push(this.defaultFilter);
1601
+ }
1602
+ setTimeout(() => {
1603
+ const filtersValue = filters.join(', ');
1604
+ this.dataService
1605
+ .getAll(this.pageIndex, this.pageSize, sorts, filtersValue, this.customInclude)
1606
+ .subscribe((response) => {
1607
+ if (this.pageIndex !== response.getMeta().meta.count) {
1608
+ this.pageIndex++;
1609
+ }
1610
+ const rows = [...this.data, ...response.getModels()];
1611
+ this.data = rows;
1612
+ this.isLoading = false;
1613
+ });
1614
+ }, 700);
1615
+ }
1616
+ loadDataRdict() {
1617
+ if (!this.dictPath)
1618
+ return;
1619
+ if (this.useView) {
1620
+ this.loadDataViewRdict();
1621
+ return;
1622
+ }
1623
+ this.rdict
1624
+ .get$(this.dictPath)
1625
+ .pipe(takeUntil(this.destroy$))
1626
+ .subscribe({
1627
+ next: (rdictData) => {
1628
+ this.tableRdict = rdictData;
1629
+ this.tableRdict
1630
+ .onChange$()
1631
+ .pipe(takeUntil(this.destroy$))
1632
+ .subscribe((changes) => this.onChangeEventRdict(changes));
1633
+ this.tableRdict
1634
+ .onDelete$()
1635
+ .pipe(takeUntil(this.destroy$))
1636
+ .subscribe((changes) => this.onDeleteEventRdict(changes));
1637
+ this.rdict
1638
+ .getArray$(this.dictPath, this.tableRdict)
1639
+ .pipe(takeUntil(this.destroy$))
1640
+ .subscribe({
1641
+ next: (value) => (this.data = value),
1642
+ error: (err) => console.error('Error:', err.message)
1643
+ });
1644
+ },
1645
+ error: (err) => console.error('Error:', err.message)
1646
+ });
1647
+ }
1648
+ loadDataViewRdict() {
1649
+ if (!this.parentDict || !this.model)
1650
+ return;
1651
+ const request = { skip: 0, take: this.pageSize };
1652
+ this.parentDict.getFilteredView(this.model, request).subscribe({
1653
+ next: (view) => (this.data = view)
1654
+ });
1655
+ }
1656
+ onDeleteEventRdict(changes) {
1657
+ if (changes?.key) {
1658
+ const index = this.data.findIndex((item) => item.oid === changes.key);
1659
+ if (index > -1) {
1660
+ this.data.splice(index, 1);
1661
+ }
1662
+ }
1663
+ }
1664
+ onChangeEventRdict(changes) {
1665
+ if (!changes)
1666
+ return;
1667
+ const key = changes?.key;
1668
+ const value = changes?.value;
1669
+ if (key === 'transactions') {
1670
+ for (const [tKey, tValue] of Object.entries(value)) {
1671
+ const index = this.data.findIndex((item) => item.oid === tKey);
1672
+ if (index > -1) {
1673
+ this.data[index] = tValue;
1674
+ }
1675
+ else {
1676
+ this.data.push(tValue);
1677
+ }
1678
+ }
1679
+ }
1680
+ else if (key && value) {
1681
+ const index = this.data.findIndex((item) => item.oid === key);
1682
+ if (index > -1) {
1683
+ this.data[index] = value.getPlainObject();
1684
+ }
1685
+ else {
1686
+ this.tableRdict.get$(key).subscribe((val) => {
1687
+ this.data.push(val.getPlainObject());
1688
+ });
1689
+ }
1690
+ }
1691
+ }
1692
+ getListLayout() {
1693
+ if (this.isRdict) {
1694
+ this.getListLayoutRdict();
1695
+ }
1696
+ else {
1697
+ this.getListLayoutStanderd();
1698
+ }
1699
+ }
1700
+ getListLayoutStanderd() {
1701
+ const modelKey = this.model;
1702
+ if (!modelKey)
1703
+ return;
1704
+ const layoutSource$ = this.fileLayout
1705
+ ? this.localFileService.getJsonData(this.fileLayout)
1706
+ : this.rdict
1707
+ ? this.rdict.get$('config.models.' + modelKey + '.tableLayout')
1708
+ : null;
1709
+ if (!layoutSource$)
1710
+ return;
1711
+ layoutSource$.subscribe({
1712
+ next: (value) => {
1713
+ const layout = this.fileLayout ? value.find((item) => item.model === modelKey) : value;
1714
+ this.setLayout(this.fileLayout ? layout?.tableLayout : layout);
1715
+ },
1716
+ error: (err) => console.error('Error loading layout:', err.message)
1717
+ });
1718
+ }
1719
+ getListLayoutRdict() {
1720
+ const modelKey = this.model;
1721
+ if (!modelKey)
1722
+ return;
1723
+ const layoutSource$ = this.fileLayout
1724
+ ? this.localFileService.getJsonData(this.fileLayout)
1725
+ : this.rdict.get$('config.models.' + modelKey + '.tableLayout');
1726
+ layoutSource$.subscribe({
1727
+ next: (value) => {
1728
+ const layout = this.fileLayout ? value.find((item) => item.model === modelKey) : value;
1729
+ this.setLayout(this.fileLayout ? layout?.tableLayout : layout);
1730
+ },
1731
+ error: (err) => console.error('Error loading layout:', err.message)
1732
+ });
1733
+ }
1734
+ setLayout(layout) {
1735
+ if (!layout)
1736
+ return;
1737
+ this.title = this.translate.instant(layout['title']);
1738
+ this.allColumns = layout['columns'].map((item) => {
1739
+ if (!item.isTranslated) {
1740
+ item.name = this.translate.instant(item.translateKey);
1741
+ item.isTranslated = true;
1742
+ if (!item.type)
1743
+ item.type = 'property';
1744
+ }
1745
+ return item;
1746
+ });
1747
+ if (this.isRdict) {
1748
+ const referenceColumns = this.allColumns.filter((item) => item.reference);
1749
+ referenceColumns.forEach((item) => {
1750
+ this.rdict.getArray$(item.reference).subscribe((value) => {
1751
+ if (value)
1752
+ this.referenceData.set(item.reference, this.arrayToMap(value, item.referenceKey));
1753
+ });
1754
+ });
1755
+ }
1756
+ this.allColumns.sort((a, b) => a.order - b.order);
1757
+ this.columns = this.allColumns.map((col) => ({
1758
+ prop: col.propertyName,
1759
+ name: col.name,
1760
+ sortable: true
1761
+ }));
1762
+ if (this.canDelete || this.canEdit) {
1763
+ this.columns.push({
1764
+ cellTemplate: this.actionsTmpl,
1765
+ name: '',
1766
+ sortable: false,
1767
+ draggable: false
1768
+ });
1769
+ }
1770
+ }
1771
+ arrayToMap(array, keyProperty) {
1772
+ const map = new Map();
1773
+ array.forEach((item) => map.set(String(item[keyProperty]), item));
1774
+ return map;
1775
+ }
1776
+ editHandler(args) {
1777
+ this.edit(args);
1778
+ }
1779
+ removeHandler(args) {
1780
+ this.delete(args);
1781
+ }
1782
+ delete(dataItem) {
1783
+ const modelName = dataItem?.[this.deletePropertyName];
1784
+ const message = this.translate.instant('Are you sure you want to delete this {{modelName}}?', { modelName });
1785
+ this.dialogServiceIonic.confirm(message).then((value) => {
1786
+ if (value?.data) {
1787
+ const idValue = dataItem?.[this.idProperty] ?? dataItem?.id ?? dataItem?.oid;
1788
+ this.performDelete(idValue);
1789
+ }
1790
+ });
1791
+ }
1792
+ performDelete(id) {
1793
+ if (this.isRdict && this.tableRdict) {
1794
+ this.tableRdict.delete$(id).subscribe(() => {
1795
+ const index = this.data.findIndex((item) => item.oid === id || item.id === id);
1796
+ if (index > -1) {
1797
+ this.data.splice(index, 1);
1798
+ }
1799
+ });
1800
+ return;
1801
+ }
1802
+ this.dataService.delete(id).subscribe(() => {
1803
+ const tempData = [];
1804
+ this.data.map((item) => {
1805
+ if (item.id !== id) {
1806
+ tempData.push(item);
1807
+ }
1808
+ });
1809
+ this.data = tempData;
1810
+ });
1811
+ }
1812
+ getCellValue(item, column) {
1813
+ if (!item || typeof item !== 'object')
1814
+ return null;
1815
+ if (column?.type === 'reference') {
1816
+ const getNested = (obj, path) => path.split('.').reduce((acc, key) => acc?.[key], obj);
1817
+ const propVal = getNested(item, column.propertyName);
1818
+ return this.referenceData.get(column.reference)?.get(String(propVal))?.[column.referenceProperty] ?? propVal;
1819
+ }
1820
+ return item[column?.propertyName ?? column?.prop];
1821
+ }
1822
+ onAdd() {
1823
+ this.addHandler();
1824
+ }
1825
+ editModel(model) {
1826
+ if (this.canEdit)
1827
+ this.editHandler(model);
1828
+ }
1829
+ deleteModel(model) {
1830
+ this.removeHandler(model);
1831
+ }
1832
+ deleteEnabled(model) {
1833
+ if (this.canDelete) {
1834
+ if (this.deleteDisableRule) {
1835
+ return this.evaluateRule(this.deleteDisableRule, model);
1836
+ }
1837
+ else {
1838
+ return true;
1839
+ }
1840
+ }
1841
+ else {
1842
+ return false;
1843
+ }
1844
+ }
1845
+ evaluateRule(rules, model) {
1846
+ let result = true;
1847
+ rules.forEach((rule) => {
1848
+ let jsonRule;
1849
+ if (typeof rule.rule === 'string') {
1850
+ jsonRule = JSON.parse(rule.rule);
1851
+ }
1852
+ else {
1853
+ jsonRule = rule.rule;
1854
+ }
1855
+ if (rule.parameters) {
1856
+ const data = '{' +
1857
+ rule.parameters
1858
+ .map((item) => {
1859
+ return '"' + item + '":"' + model[item] + '"';
1860
+ })
1861
+ .join(',') +
1862
+ '}';
1863
+ result = jsonLogic.apply(jsonRule, JSON.parse(data));
1864
+ }
1865
+ else {
1866
+ result = jsonLogic.apply(jsonRule);
1867
+ }
1868
+ });
1869
+ return result;
1870
+ }
1871
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: GenericIonicGridComponent, deps: [{ token: i1$2.Router }, { token: i2.TranslateService }, { token: IonicDialogService }, { token: i0.ElementRef }, { token: i1$3.LocalFileService }], target: i0.ɵɵFactoryTarget.Component }); }
1872
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.8", type: GenericIonicGridComponent, isStandalone: true, selector: "generic-ionic-grid", viewQueries: [{ propertyName: "actionsTmpl", first: true, predicate: ["actionsTmpl"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ion-header *ngIf=\"showHeader\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\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<ion-content [fullscreen]=\"true\">\r\n\r\n <ion-refresher slot=\"fixed\" (ionRefresh)=\"handleRefresh($event)\">\r\n <ion-refresher-content></ion-refresher-content>\r\n </ion-refresher>\r\n\r\n <ngx-datatable class=\"material fullscreen rls-server-scrolling\" style=\"top: 115px\" [rows]=\"data\" [columns]=\"columns\"\r\n [columnMode]=\"ColumnMode.standard\" [headerHeight]=\"headerHeight\" [rowHeight]=\"rowHeight\" [scrollbarV]=\"true\"\r\n [loadingIndicator]=\"isLoading\" [scrollbarH]=\"true\" (scroll)=\"onScroll($event.offsetY)\"\r\n >\r\n </ngx-datatable>\r\n \r\n <ng-template #actionsTmpl let-row=\"row\" let-value=\"value\">\r\n <ion-button fill=\"clear\" *ngIf=\"canEdit\" (click)='editModel(row)'>\r\n <ion-icon slot=\"icon-only\" name=\"create\" (click)='editModel(row)'></ion-icon>\r\n </ion-button>\r\n <ion-button fill=\"clear\" *ngIf=\"deleteEnabled(row)\" (click)='deleteModel(row)'>\r\n <ion-icon color=\"danger\" slot=\"icon-only\" name=\"trash\" (click)='deleteModel(row)'></ion-icon>\r\n </ion-button>\r\n </ng-template>\r\n\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title}}</ion-title>\r\n <ion-button slot=\"end\" (click)=\"onAdd()\" fill=\"clear\" *ngIf=\"hasAdd\">\r\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\r\n </ion-button>\r\n</ng-template>\r\n\r\n<ng-template #search>\r\n <ion-toolbar *ngIf=\"showSearch\">\r\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\r\n </ion-toolbar>\r\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.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.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.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "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", "mode", "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", "autocapitalize", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "maxlength", "minlength", "mode", "name", "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-input-otp[type=text],ion-textarea,ion-searchbar" }, { kind: "component", type: i4.IonBackButton, selector: "ion-back-button" }, { kind: "component", type: i6.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"] }] }); }
1873
+ }
1874
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: GenericIonicGridComponent, decorators: [{
1875
+ type: Component,
1876
+ args: [{ selector: 'generic-ionic-grid', standalone: true, imports: [RslIonicModuleModule], template: "<ion-header *ngIf=\"showHeader\">\r\n <ion-toolbar>\r\n <ion-buttons slot=\"start\">\r\n <ion-menu-button></ion-menu-button>\r\n <ion-back-button></ion-back-button>\r\n </ion-buttons>\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<ion-content [fullscreen]=\"true\">\r\n\r\n <ion-refresher slot=\"fixed\" (ionRefresh)=\"handleRefresh($event)\">\r\n <ion-refresher-content></ion-refresher-content>\r\n </ion-refresher>\r\n\r\n <ngx-datatable class=\"material fullscreen rls-server-scrolling\" style=\"top: 115px\" [rows]=\"data\" [columns]=\"columns\"\r\n [columnMode]=\"ColumnMode.standard\" [headerHeight]=\"headerHeight\" [rowHeight]=\"rowHeight\" [scrollbarV]=\"true\"\r\n [loadingIndicator]=\"isLoading\" [scrollbarH]=\"true\" (scroll)=\"onScroll($event.offsetY)\"\r\n >\r\n </ngx-datatable>\r\n \r\n <ng-template #actionsTmpl let-row=\"row\" let-value=\"value\">\r\n <ion-button fill=\"clear\" *ngIf=\"canEdit\" (click)='editModel(row)'>\r\n <ion-icon slot=\"icon-only\" name=\"create\" (click)='editModel(row)'></ion-icon>\r\n </ion-button>\r\n <ion-button fill=\"clear\" *ngIf=\"deleteEnabled(row)\" (click)='deleteModel(row)'>\r\n <ion-icon color=\"danger\" slot=\"icon-only\" name=\"trash\" (click)='deleteModel(row)'></ion-icon>\r\n </ion-button>\r\n </ng-template>\r\n\r\n</ion-content>\r\n\r\n<ng-template #header>\r\n <ion-title class=\"ion-text-center\">{{title}}</ion-title>\r\n <ion-button slot=\"end\" (click)=\"onAdd()\" fill=\"clear\" *ngIf=\"hasAdd\">\r\n <ion-icon size=\"large\" name=\"add\"></ion-icon>\r\n </ion-button>\r\n</ng-template>\r\n\r\n<ng-template #search>\r\n <ion-toolbar *ngIf=\"showSearch\">\r\n <ion-searchbar [debounce]=\"1000\" (ionChange)=\"handleChange($event)\"></ion-searchbar>\r\n </ion-toolbar>\r\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"] }]
1877
+ }], ctorParameters: () => [{ type: i1$2.Router }, { type: i2.TranslateService }, { type: IonicDialogService }, { type: i0.ElementRef }, { type: i1$3.LocalFileService }], propDecorators: { actionsTmpl: [{
1878
+ type: ViewChild,
1879
+ args: ['actionsTmpl', { static: true }]
1880
+ }] } });
1881
+
1219
1882
  class RslIonicGridComponent {
1220
1883
  constructor(router, route, translate, location, injector, loadingCtrl, navCtrl, dialogService, datePipe, numberPipe, percentPipe) {
1221
1884
  this.router = router;
@@ -1582,5 +2245,5 @@ function IonicListLayout(config) {
1582
2245
  * Generated bundle index. Do not edit.
1583
2246
  */
1584
2247
 
1585
- export { AccordionWrapperComponent, GenericIonicCrudComponent, IonicDataTableLayout, IonicDialogService, IonicListLayout, PanelWrapperComponent, RepeatTypeComponent, RslIonicDataTableComponent, RslIonicGridComponent, RslIonicLayoutComponent, RslIonicSmButtonsComponent, TranslateExtension, fieldMatchValidator, registerTranslateExtension };
2248
+ export { AccordionWrapperComponent, GenericIonicCrudComponent, GenericIonicCrudPageComponent, GenericIonicGridComponent, IonicDataTableLayout, IonicDialogService, IonicListLayout, PanelWrapperComponent, RepeatTypeComponent, RslIonicDataTableComponent, RslIonicGridComponent, RslIonicLayoutComponent, RslIonicSmButtonsComponent, TranslateExtension, fieldMatchValidator, registerTranslateExtension };
1586
2249
  //# sourceMappingURL=rosoftlab-ionic.mjs.map