ngx-thin-admin 0.0.0-alpha.4 → 0.0.0-alpha.6
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.
|
@@ -5,22 +5,26 @@ import { debounceTime } from 'rxjs/operators';
|
|
|
5
5
|
import * as i4 from '@angular/material/button';
|
|
6
6
|
import { MatButtonModule, MatIconButton, MatButton } from '@angular/material/button';
|
|
7
7
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
8
|
-
import
|
|
9
|
-
import
|
|
8
|
+
import * as i6 from '@angular/material/icon';
|
|
9
|
+
import { MatIcon, MatIconModule } from '@angular/material/icon';
|
|
10
|
+
import * as i2 from '@angular/material/input';
|
|
10
11
|
import { MatInputModule, MatInput, MatPrefix, MatSuffix } from '@angular/material/input';
|
|
11
|
-
import
|
|
12
|
+
import * as i2$1 from '@angular/material/select';
|
|
13
|
+
import { MatSelectModule, MatFormField } from '@angular/material/select';
|
|
12
14
|
import { MatTooltip } from '@angular/material/tooltip';
|
|
13
15
|
import * as i2$2 from '@ng-matero/extensions/grid';
|
|
14
16
|
import { MtxGridModule } from '@ng-matero/extensions/grid';
|
|
15
|
-
import * as
|
|
17
|
+
import * as i3 from '@angular/forms';
|
|
16
18
|
import { FormsModule, ReactiveFormsModule, FormGroup } from '@angular/forms';
|
|
17
19
|
import { MatSelectionList, MatListOption } from '@angular/material/list';
|
|
18
20
|
import { MatMenu, MatMenuItem, MatMenuTrigger, MatMenuContent } from '@angular/material/menu';
|
|
19
21
|
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogClose, MatDialog } from '@angular/material/dialog';
|
|
20
|
-
import * as
|
|
22
|
+
import * as i1 from '@angular/material/form-field';
|
|
21
23
|
import { MatFormFieldModule, MatFormField as MatFormField$1, MatLabel, MatHint, MatSuffix as MatSuffix$1, MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
|
22
24
|
import { stringify } from 'csv-stringify/browser/esm/sync';
|
|
23
25
|
import { RouterLink, Router } from '@angular/router';
|
|
26
|
+
import * as i5 from '@angular/material/progress-spinner';
|
|
27
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
24
28
|
import { MatCard, MatCardHeader, MatCardContent } from '@angular/material/card';
|
|
25
29
|
import { FieldWrapper, FieldType, FormlyAttributes, FormlyForm, provideFormlyCore } from '@ngx-formly/core';
|
|
26
30
|
import { withFormlyMaterial } from '@ngx-formly/material';
|
|
@@ -70,6 +74,12 @@ const messagesEn = {
|
|
|
70
74
|
'item.deletionDialogMessage': 'Are you sure you want to delete "{label}" ({id})? This action cannot be undone.',
|
|
71
75
|
'item.errorFailedDelete': 'Failed to delete "{label}"',
|
|
72
76
|
'item.successDeleted': '"{label}" has been deleted successfully',
|
|
77
|
+
'item.changeCategory': 'Change {categoryType}',
|
|
78
|
+
'item.changeCategoryDialogTitle': 'Change {categoryType}',
|
|
79
|
+
'item.changeCategoryDialogMessage': 'Select a {categoryType} to move "{label}" to.',
|
|
80
|
+
'item.successCategoryChanged': '{categoryType} changed successfully',
|
|
81
|
+
'item.errorFailedCategoryChange': 'Failed to change {categoryType} for "{label}"',
|
|
82
|
+
'category.unselected': 'Uncategorized',
|
|
73
83
|
'csv.exporting': 'Exporting CSV...',
|
|
74
84
|
'csv.exportCompleted': 'CSV export completed. Exported {count} items.',
|
|
75
85
|
'csv.exportCompletedWithErrors': 'CSV exported up to {count} items, but errors occurred: {error}',
|
|
@@ -92,8 +102,8 @@ const messagesJa = {
|
|
|
92
102
|
'list.exportAsCsv': 'CSV でエクスポート',
|
|
93
103
|
'list.exportedFileName': 'exported',
|
|
94
104
|
'list.exportItems': '{count} 件をエクスポート',
|
|
95
|
-
'editor.titleForCreate': '{itemType}
|
|
96
|
-
'editor.titleForEdit': '{itemType}
|
|
105
|
+
'editor.titleForCreate': '{itemType}の作成',
|
|
106
|
+
'editor.titleForEdit': '{itemType}の編集',
|
|
97
107
|
'editor.idLabel': 'ID',
|
|
98
108
|
'editor.saveChanges': '変更を保存',
|
|
99
109
|
'editor.errorInvalidInput': '入力内容が不正です',
|
|
@@ -103,9 +113,9 @@ const messagesJa = {
|
|
|
103
113
|
'category.defaultSingular': 'カテゴリ',
|
|
104
114
|
'category.defaultPlural': 'カテゴリ',
|
|
105
115
|
'category.all': 'すべて',
|
|
106
|
-
'category.editorDialogTitleForCreate': '{categoryType}
|
|
107
|
-
'category.editorDialogTitleForEdit': '{categoryType}
|
|
108
|
-
'category.deletionDialogTitle': '{categoryType}
|
|
116
|
+
'category.editorDialogTitleForCreate': '{categoryType}の作成',
|
|
117
|
+
'category.editorDialogTitleForEdit': '{categoryType}の編集',
|
|
118
|
+
'category.deletionDialogTitle': '{categoryType}の削除',
|
|
109
119
|
'category.deletionDialogMessage': '{categoryType} "{label}" を削除しますか?この操作は元に戻せません。',
|
|
110
120
|
'category.errorCouldNotCreate': '{categoryType} を作成できませんでした',
|
|
111
121
|
'category.errorFailedUpdate': '{categoryType} "{label}" の更新に失敗しました',
|
|
@@ -115,10 +125,16 @@ const messagesJa = {
|
|
|
115
125
|
'category.successUpdated': '{categoryType} "{label}" を更新しました',
|
|
116
126
|
'category.successDeleted': '{categoryType} "{label}" を削除しました',
|
|
117
127
|
'item.defaultSingular': '項目',
|
|
118
|
-
'item.deletionDialogTitle': '{itemType}
|
|
128
|
+
'item.deletionDialogTitle': '{itemType}の削除',
|
|
119
129
|
'item.deletionDialogMessage': '"{label}" ({id}) を削除しますか?この操作は元に戻せません。',
|
|
120
130
|
'item.errorFailedDelete': '"{label}" の削除に失敗しました',
|
|
121
131
|
'item.successDeleted': '"{label}" を削除しました',
|
|
132
|
+
'item.changeCategory': '{categoryType}を変更',
|
|
133
|
+
'item.changeCategoryDialogTitle': '{categoryType}の変更',
|
|
134
|
+
'item.changeCategoryDialogMessage': '"{label}" の移動先を選択してください',
|
|
135
|
+
'item.successCategoryChanged': '{categoryType}を変更しました',
|
|
136
|
+
'item.errorFailedCategoryChange': '「{label}」の{categoryType}変更に失敗しました',
|
|
137
|
+
'category.unselected': '未分類',
|
|
122
138
|
'csv.exporting': 'CSV をエクスポート中...',
|
|
123
139
|
'csv.exportCompleted': 'CSV エクスポートが完了しました。{count} 件をエクスポートしました。',
|
|
124
140
|
'csv.exportCompletedWithErrors': '{count} 件までエクスポートしましたが、エラーが発生しました: {error}',
|
|
@@ -174,7 +190,7 @@ class CategoryEditorDialog {
|
|
|
174
190
|
});
|
|
175
191
|
}
|
|
176
192
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CategoryEditorDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
177
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: CategoryEditorDialog, isStandalone: true, selector: "lib-category-editor-dialog", ngImport: i0, template: "<h2 mat-dialog-title>\n @if (data.editCategory) {\n {{\n t('category.editorDialogTitleForEdit', {\n categoryType: data.config.singularLabel ?? t('category.defaultSingular'),\n })\n }}\n } @else {\n {{\n t('category.editorDialogTitleForCreate', {\n categoryType: data.config.singularLabel ?? t('category.defaultSingular'),\n })\n }}\n }\n</h2>\n<form (ngSubmit)=\"save()\">\n <mat-dialog-content>\n <mat-form-field>\n <mat-label>{{ data.config.exampleLabel ?? data.config.singularLabel ?? '' }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"categoryLabel\"\n name=\"categoryLabel\"\n cdkFocusInitial\n [value]=\"data.editCategory ? data.editCategory.label : ''\"\n />\n </mat-form-field>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button type=\"button\" class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText ?? t('common.cancel') }}\n </button>\n <button type=\"submit\" matButton>{{ data.positiveButtonText ?? t('common.save') }}</button>\n </mat-dialog-actions>\n</form>\n", styles: [".cancel-btn{--mat-button-text-label-text-color: #333}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type:
|
|
193
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: CategoryEditorDialog, isStandalone: true, selector: "lib-category-editor-dialog", ngImport: i0, template: "<h2 mat-dialog-title>\n @if (data.editCategory) {\n {{\n t('category.editorDialogTitleForEdit', {\n categoryType: data.config.singularLabel ?? t('category.defaultSingular'),\n })\n }}\n } @else {\n {{\n t('category.editorDialogTitleForCreate', {\n categoryType: data.config.singularLabel ?? t('category.defaultSingular'),\n })\n }}\n }\n</h2>\n<form (ngSubmit)=\"save()\">\n <mat-dialog-content>\n <mat-form-field>\n <mat-label>{{ data.config.exampleLabel ?? data.config.singularLabel ?? '' }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"categoryLabel\"\n name=\"categoryLabel\"\n cdkFocusInitial\n [value]=\"data.editCategory ? data.editCategory.label : ''\"\n />\n </mat-form-field>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button type=\"button\" class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText ?? t('common.cancel') }}\n </button>\n <button type=\"submit\" matButton>{{ data.positiveButtonText ?? t('common.save') }}</button>\n </mat-dialog-actions>\n</form>\n", styles: [".cancel-btn{--mat-button-text-label-text-color: #333}\n"], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }] });
|
|
178
194
|
}
|
|
179
195
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CategoryEditorDialog, decorators: [{
|
|
180
196
|
type: Component,
|
|
@@ -416,7 +432,7 @@ class ListCategorySelector {
|
|
|
416
432
|
this.fetchCategories();
|
|
417
433
|
}
|
|
418
434
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ListCategorySelector, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
419
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: ListCategorySelector, isStandalone: true, selector: "lib-list-category-selector", inputs: { config: "config", selectedCategory: "selectedCategory" }, outputs: { selectedCategoryChange: "selectedCategoryChange" }, usesOnChanges: true, ngImport: i0, template: "<header>\n <!-- Category selector title -->\n <span class=\"category-selector-title\">\n {{ config?.title ?? t('category.defaultPlural') }}\n </span>\n <!---->\n\n <!-- Category Creation button -->\n @if (config?.creator) {\n <button\n mat-icon-button\n (click)=\"openCategoryEditorDialog(undefined)\"\n class=\"create-category-button\"\n >\n <mat-icon>add</mat-icon>\n </button>\n }\n <!---->\n</header>\n\n<mat-selection-list\n #categorySelector\n [multiple]=\"false\"\n [hideSingleSelectionIndicator]=\"true\"\n [(ngModel)]=\"selectedCategory\"\n (selectionChange)=\"this.selectedCategoryChange.emit(selectedCategory)\"\n>\n <!-- \"All\" Category -->\n <mat-list-option\n [value]=\"undefined\"\n [class.active]=\"selectedCategory && selectedCategory[0] === undefined\"\n >\n <div matListItemTitle>\n <!-- Category label -->\n {{ t('category.all') }} \n <!---->\n </div>\n </mat-list-option>\n <!---->\n\n <!-- Each category -->\n @for (category of categories; track category.id) {\n <mat-list-option\n [value]=\"category\"\n [class.active]=\"selectedCategory && selectedCategory[0]?.id === category.id\"\n >\n <div matListItemTitle>\n <!-- Category label -->\n {{ category.label }} \n <!---->\n\n <!-- Count of items in the category -->\n @if (category.itemCount !== undefined) {\n <small> ({{ category.itemCount }}) </small>\n }\n <!---->\n </div>\n\n <!-- Category menu button -->\n @if (\n selectedCategory &&\n selectedCategory[0] !== undefined &&\n selectedCategory[0].id === category.id &&\n (config?.updater || config?.deleter)\n ) {\n <button\n matIconButton\n [matMenuTriggerFor]=\"menu\"\n [matMenuTriggerData]=\"{ category: category }\"\n class=\"category-menu-button\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n <!---->\n </mat-list-option>\n }\n <!---->\n</mat-selection-list>\n\n<!-- Category Menu -->\n<mat-menu #menu=\"matMenu\">\n <ng-template matMenuContent let-category=\"category\">\n @if (config?.updater) {\n <button mat-menu-item (click)=\"openCategoryEditorDialog(category)\">\n {{ t('common.edit') }}\n </button>\n }\n @if (config?.deleter) {\n <button mat-menu-item (click)=\"openCategoryDeletionDialog(category)\">\n {{ t('common.delete') }}\n </button>\n }\n </ng-template>\n</mat-menu>\n<!---->\n", styles: [":host{display:block;border-radius:9px;border:1px solid rgba(198,198,201,.1254901961)}header{display:flex;align-items:center;border-bottom:1px solid #f5f6f8;justify-content:space-between;padding:0 .2rem 0 .1rem}header .category-selector-title{font-size:.9rem;padding:1rem .8rem}header button{transform:translateY(-1px)}header button mat-icon{color:#496487}mat-selection-list mat-list-option div[matListItemTitle]{font-size:.85rem;position:relative}mat-selection-list mat-list-option.active{background-color:#f0f0f0}mat-selection-list mat-list-option.active div[matListItemTitle]{color:#3d649c}mat-selection-list mat-list-option:hover{cursor:pointer;background-color:#f0f0f0}mat-selection-list mat-list-option .category-menu-button{position:absolute;right:0;top:0;height:100%;padding-top:.8rem;vertical-align:middle;z-index:1}mat-selection-list mat-list-option{--mat-icon-button-container-shape: 1px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type:
|
|
435
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: ListCategorySelector, isStandalone: true, selector: "lib-list-category-selector", inputs: { config: "config", selectedCategory: "selectedCategory" }, outputs: { selectedCategoryChange: "selectedCategoryChange" }, usesOnChanges: true, ngImport: i0, template: "<header>\n <!-- Category selector title -->\n <span class=\"category-selector-title\">\n {{ config?.title ?? t('category.defaultPlural') }}\n </span>\n <!---->\n\n <!-- Category Creation button -->\n @if (config?.creator) {\n <button\n mat-icon-button\n (click)=\"openCategoryEditorDialog(undefined)\"\n class=\"create-category-button\"\n >\n <mat-icon>add</mat-icon>\n </button>\n }\n <!---->\n</header>\n\n<mat-selection-list\n #categorySelector\n [multiple]=\"false\"\n [hideSingleSelectionIndicator]=\"true\"\n [(ngModel)]=\"selectedCategory\"\n (selectionChange)=\"this.selectedCategoryChange.emit(selectedCategory)\"\n>\n <!-- \"All\" Category -->\n <mat-list-option\n [value]=\"undefined\"\n [class.active]=\"selectedCategory && selectedCategory[0] === undefined\"\n >\n <div matListItemTitle>\n <!-- Category label -->\n {{ t('category.all') }} \n <!---->\n </div>\n </mat-list-option>\n <!---->\n\n <!-- Each category -->\n @for (category of categories; track category.id) {\n <mat-list-option\n [value]=\"category\"\n [class.active]=\"selectedCategory && selectedCategory[0]?.id === category.id\"\n >\n <div matListItemTitle>\n <!-- Category label -->\n {{ category.label }} \n <!---->\n\n <!-- Count of items in the category -->\n @if (category.itemCount !== undefined) {\n <small> ({{ category.itemCount }}) </small>\n }\n <!---->\n </div>\n\n <!-- Category menu button -->\n @if (\n selectedCategory &&\n selectedCategory[0] !== undefined &&\n selectedCategory[0].id === category.id &&\n (config?.updater || config?.deleter)\n ) {\n <button\n matIconButton\n [matMenuTriggerFor]=\"menu\"\n [matMenuTriggerData]=\"{ category: category }\"\n class=\"category-menu-button\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n <!---->\n </mat-list-option>\n }\n <!---->\n</mat-selection-list>\n\n<!-- Category Menu -->\n<mat-menu #menu=\"matMenu\">\n <ng-template matMenuContent let-category=\"category\">\n @if (config?.updater) {\n <button mat-menu-item (click)=\"openCategoryEditorDialog(category)\">\n {{ t('common.edit') }}\n </button>\n }\n @if (config?.deleter) {\n <button mat-menu-item (click)=\"openCategoryDeletionDialog(category)\">\n {{ t('common.delete') }}\n </button>\n }\n </ng-template>\n</mat-menu>\n<!---->\n", styles: [":host{display:block;border-radius:9px;border:1px solid rgba(198,198,201,.1254901961)}header{display:flex;align-items:center;border-bottom:1px solid #f5f6f8;justify-content:space-between;padding:0 .2rem 0 .1rem}header .category-selector-title{font-size:.9rem;padding:1rem .8rem}header button{transform:translateY(-1px)}header button mat-icon{color:#496487}mat-selection-list mat-list-option div[matListItemTitle]{font-size:.85rem;position:relative}mat-selection-list mat-list-option.active{background-color:#f0f0f0}mat-selection-list mat-list-option.active div[matListItemTitle]{color:#3d649c}mat-selection-list mat-list-option:hover{cursor:pointer;background-color:#f0f0f0}mat-selection-list mat-list-option .category-menu-button{position:absolute;right:0;top:0;height:100%;padding-top:.8rem;vertical-align:middle;z-index:1}mat-selection-list mat-list-option{--mat-icon-button-container-shape: 1px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "directive", type: MatMenuContent, selector: "ng-template[matMenuContent]" }] });
|
|
420
436
|
}
|
|
421
437
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ListCategorySelector, decorators: [{
|
|
422
438
|
type: Component,
|
|
@@ -633,6 +649,100 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
633
649
|
}]
|
|
634
650
|
}], ctorParameters: () => [] });
|
|
635
651
|
|
|
652
|
+
class CategoryChangeDialog {
|
|
653
|
+
dialogRef = inject((MatDialogRef));
|
|
654
|
+
data = inject(MAT_DIALOG_DATA);
|
|
655
|
+
translate = inject(NGX_THIN_ADMIN_TRANSLATE);
|
|
656
|
+
cdr = inject(ChangeDetectorRef);
|
|
657
|
+
dialog = inject(MatDialog);
|
|
658
|
+
snackbar = inject(MatSnackBar);
|
|
659
|
+
categories = [];
|
|
660
|
+
selectedCategoryId;
|
|
661
|
+
isLoading = false;
|
|
662
|
+
t(key, params) {
|
|
663
|
+
return this.translate(key, params);
|
|
664
|
+
}
|
|
665
|
+
async ngOnInit() {
|
|
666
|
+
this.selectedCategoryId = this.data.currentCategoryId;
|
|
667
|
+
this.isLoading = true;
|
|
668
|
+
this.cdr.markForCheck();
|
|
669
|
+
try {
|
|
670
|
+
const result = await Promise.resolve(this.data.categorySelectorConfig.fetcher());
|
|
671
|
+
this.categories = result.categories;
|
|
672
|
+
}
|
|
673
|
+
catch (e) {
|
|
674
|
+
console.error('Failed to fetch categories:', e);
|
|
675
|
+
}
|
|
676
|
+
finally {
|
|
677
|
+
this.isLoading = false;
|
|
678
|
+
this.cdr.markForCheck();
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
save() {
|
|
682
|
+
this.dialogRef.close({
|
|
683
|
+
categoryId: this.selectedCategoryId,
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
async createNewCategory() {
|
|
687
|
+
if (!this.data.categorySelectorConfig.creator)
|
|
688
|
+
return;
|
|
689
|
+
const dialogRef = this.dialog.open(CategoryEditorDialog, {
|
|
690
|
+
width: '400px',
|
|
691
|
+
data: {
|
|
692
|
+
config: this.data.categorySelectorConfig,
|
|
693
|
+
editCategory: undefined,
|
|
694
|
+
positiveButtonText: this.t('common.create'),
|
|
695
|
+
cancelButtonText: this.t('common.cancel'),
|
|
696
|
+
},
|
|
697
|
+
});
|
|
698
|
+
const result = await lastValueFrom(dialogRef.afterClosed());
|
|
699
|
+
if (!result || !result.label) {
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
this.isLoading = true;
|
|
703
|
+
this.cdr.markForCheck();
|
|
704
|
+
try {
|
|
705
|
+
const newCategory = await Promise.resolve(this.data.categorySelectorConfig.creator(result.label));
|
|
706
|
+
this.snackbar.open(this.t('category.successCreated', {
|
|
707
|
+
categoryType: this.data.categorySelectorConfig.singularLabel ?? this.t('category.defaultSingular'),
|
|
708
|
+
label: result.label,
|
|
709
|
+
}), undefined, { duration: 3000 });
|
|
710
|
+
// Re-fetch categories
|
|
711
|
+
const fetchResult = await Promise.resolve(this.data.categorySelectorConfig.fetcher());
|
|
712
|
+
this.categories = fetchResult.categories;
|
|
713
|
+
// Auto-select the newly created category
|
|
714
|
+
this.selectedCategoryId = newCategory.id;
|
|
715
|
+
}
|
|
716
|
+
catch (e) {
|
|
717
|
+
this.snackbar.open(`Error: ${e?.message ??
|
|
718
|
+
this.t('category.errorCouldNotSave', {
|
|
719
|
+
categoryType: this.data.categorySelectorConfig.singularLabel ?? this.t('category.defaultSingular'),
|
|
720
|
+
})}`, undefined, { duration: 3000 });
|
|
721
|
+
}
|
|
722
|
+
finally {
|
|
723
|
+
this.isLoading = false;
|
|
724
|
+
this.cdr.markForCheck();
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CategoryChangeDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
728
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: CategoryChangeDialog, isStandalone: true, selector: "lib-category-change-dialog", ngImport: i0, template: "<h2 mat-dialog-title>\n {{\n t('item.changeCategoryDialogTitle', {\n categoryType: data.categorySelectorConfig.singularLabel || t('category.defaultSingular'),\n })\n }}\n</h2>\n\n<mat-dialog-content>\n @if (data.itemLabel) {\n <p style=\"margin-top: 5px; margin-bottom: 1rem\">\n {{\n t('item.changeCategoryDialogMessage', {\n label: data.itemLabel,\n categoryType: data.categorySelectorConfig.singularLabel || t('category.defaultSingular'),\n })\n }}\n </p>\n }\n\n <mat-form-field appearance=\"outline\" style=\"width: 100%; margin-top: 10px\">\n <mat-label>{{\n data.categorySelectorConfig.singularLabel || t('category.defaultSingular')\n }}</mat-label>\n <mat-select [(ngModel)]=\"selectedCategoryId\" [disabled]=\"isLoading\">\n <mat-option [value]=\"undefined\">{{ t('category.unselected') }}</mat-option>\n @for (category of categories; track category.id) {\n <mat-option [value]=\"category.id\">{{ category.label }}</mat-option>\n }\n </mat-select>\n @if (isLoading) {\n <mat-spinner matSuffix diameter=\"20\" style=\"margin-right: 12px\"></mat-spinner>\n }\n </mat-form-field>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n @if (data.categorySelectorConfig.creator) {\n <button mat-button (click)=\"createNewCategory()\" [disabled]=\"isLoading\">\n <mat-icon style=\"margin-right: 4px; font-size: 1.2rem; width: 1.2rem; height: 1.2rem\"\n >add</mat-icon\n >\n <span>{{ t('common.create') }}</span>\n </button>\n }\n\n <span style=\"flex: 1\"></span>\n\n <button mat-button mat-dialog-close>\n {{ data.cancelButtonText || t('common.cancel') }}\n </button>\n <button mat-flat-button color=\"primary\" (click)=\"save()\" [disabled]=\"isLoading\">\n {{ data.positiveButtonText || t('common.save') }}\n </button>\n</mat-dialog-actions>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
729
|
+
}
|
|
730
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CategoryChangeDialog, decorators: [{
|
|
731
|
+
type: Component,
|
|
732
|
+
args: [{ selector: 'lib-category-change-dialog', imports: [
|
|
733
|
+
MatFormFieldModule,
|
|
734
|
+
MatSelectModule,
|
|
735
|
+
FormsModule,
|
|
736
|
+
MatButtonModule,
|
|
737
|
+
MatDialogTitle,
|
|
738
|
+
MatDialogContent,
|
|
739
|
+
MatDialogActions,
|
|
740
|
+
MatDialogClose,
|
|
741
|
+
MatProgressSpinnerModule,
|
|
742
|
+
MatIconModule,
|
|
743
|
+
], template: "<h2 mat-dialog-title>\n {{\n t('item.changeCategoryDialogTitle', {\n categoryType: data.categorySelectorConfig.singularLabel || t('category.defaultSingular'),\n })\n }}\n</h2>\n\n<mat-dialog-content>\n @if (data.itemLabel) {\n <p style=\"margin-top: 5px; margin-bottom: 1rem\">\n {{\n t('item.changeCategoryDialogMessage', {\n label: data.itemLabel,\n categoryType: data.categorySelectorConfig.singularLabel || t('category.defaultSingular'),\n })\n }}\n </p>\n }\n\n <mat-form-field appearance=\"outline\" style=\"width: 100%; margin-top: 10px\">\n <mat-label>{{\n data.categorySelectorConfig.singularLabel || t('category.defaultSingular')\n }}</mat-label>\n <mat-select [(ngModel)]=\"selectedCategoryId\" [disabled]=\"isLoading\">\n <mat-option [value]=\"undefined\">{{ t('category.unselected') }}</mat-option>\n @for (category of categories; track category.id) {\n <mat-option [value]=\"category.id\">{{ category.label }}</mat-option>\n }\n </mat-select>\n @if (isLoading) {\n <mat-spinner matSuffix diameter=\"20\" style=\"margin-right: 12px\"></mat-spinner>\n }\n </mat-form-field>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n @if (data.categorySelectorConfig.creator) {\n <button mat-button (click)=\"createNewCategory()\" [disabled]=\"isLoading\">\n <mat-icon style=\"margin-right: 4px; font-size: 1.2rem; width: 1.2rem; height: 1.2rem\"\n >add</mat-icon\n >\n <span>{{ t('common.create') }}</span>\n </button>\n }\n\n <span style=\"flex: 1\"></span>\n\n <button mat-button mat-dialog-close>\n {{ data.cancelButtonText || t('common.cancel') }}\n </button>\n <button mat-flat-button color=\"primary\" (click)=\"save()\" [disabled]=\"isLoading\">\n {{ data.positiveButtonText || t('common.save') }}\n </button>\n</mat-dialog-actions>\n" }]
|
|
744
|
+
}] });
|
|
745
|
+
|
|
636
746
|
function getErrorMessage(error) {
|
|
637
747
|
if (typeof error === 'string') {
|
|
638
748
|
return error;
|
|
@@ -724,13 +834,8 @@ class NgxThinAdminList {
|
|
|
724
834
|
}
|
|
725
835
|
ngOnChanges(changes) {
|
|
726
836
|
// Columns
|
|
727
|
-
if (changes.listColumns?.currentValue) {
|
|
728
|
-
this.
|
|
729
|
-
if (col.link || col.routerLink) {
|
|
730
|
-
return { ...col, cellTemplate: this.cellTplWithLink };
|
|
731
|
-
}
|
|
732
|
-
return col;
|
|
733
|
-
});
|
|
837
|
+
if (changes.listColumns?.currentValue || changes.listConfig?.currentValue) {
|
|
838
|
+
this.buildGridColumns();
|
|
734
839
|
}
|
|
735
840
|
// List - trigger strictly when listFetcher is newly provided or explicitly changed
|
|
736
841
|
if (changes.listConfig?.currentValue?.fetcher !== changes.listConfig?.previousValue?.fetcher) {
|
|
@@ -738,6 +843,48 @@ class NgxThinAdminList {
|
|
|
738
843
|
this.fetchList();
|
|
739
844
|
}
|
|
740
845
|
}
|
|
846
|
+
buildGridColumns() {
|
|
847
|
+
if (!this.listColumns) {
|
|
848
|
+
this.gridColumns = [];
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
let columns = this.listColumns.map((col) => {
|
|
852
|
+
if (col.link || col.routerLink) {
|
|
853
|
+
return { ...col, cellTemplate: this.cellTplWithLink };
|
|
854
|
+
}
|
|
855
|
+
return col;
|
|
856
|
+
});
|
|
857
|
+
if (this.listConfig?.categoryChanger && this.categorySelectorConfig) {
|
|
858
|
+
const actionsColIndex = columns.findIndex((col) => col.field === 'actions' && col.type === 'button');
|
|
859
|
+
const categoryType = this.categorySelectorConfig.singularLabel || this.t('category.defaultSingular');
|
|
860
|
+
const changeCategoryBtn = {
|
|
861
|
+
type: 'icon',
|
|
862
|
+
icon: 'folder_shared',
|
|
863
|
+
tooltip: this.t('item.changeCategory', { categoryType }),
|
|
864
|
+
click: (record) => this.openItemCategoryChangeDialog(record),
|
|
865
|
+
};
|
|
866
|
+
if (actionsColIndex >= 0) {
|
|
867
|
+
const col = { ...columns[actionsColIndex] };
|
|
868
|
+
const originalButtons = col.buttons;
|
|
869
|
+
if (typeof originalButtons === 'function') {
|
|
870
|
+
col.buttons = (record) => [...originalButtons(record), changeCategoryBtn];
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
col.buttons = [...(originalButtons || []), changeCategoryBtn];
|
|
874
|
+
}
|
|
875
|
+
columns[actionsColIndex] = col;
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
columns.push({
|
|
879
|
+
header: 'Actions',
|
|
880
|
+
field: 'actions',
|
|
881
|
+
type: 'button',
|
|
882
|
+
buttons: [changeCategoryBtn],
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
this.gridColumns = columns;
|
|
887
|
+
}
|
|
741
888
|
async fetchList() {
|
|
742
889
|
if (!this.listFetcher) {
|
|
743
890
|
return;
|
|
@@ -848,8 +995,55 @@ class NgxThinAdminList {
|
|
|
848
995
|
// Refresh the list after deletion
|
|
849
996
|
this.fetchList();
|
|
850
997
|
}
|
|
998
|
+
async openItemCategoryChangeDialog(item) {
|
|
999
|
+
if (!this.listConfig?.categoryChanger || !this.categorySelectorConfig) {
|
|
1000
|
+
return;
|
|
1001
|
+
}
|
|
1002
|
+
const idKey = this.listConfig?.idFieldKey;
|
|
1003
|
+
const labelKey = this.listConfig?.labelFieldKey;
|
|
1004
|
+
const id = idKey ? item[idKey] : (item.id ?? JSON.stringify(item));
|
|
1005
|
+
const label = labelKey ? item[labelKey] : id;
|
|
1006
|
+
let currentCategoryId;
|
|
1007
|
+
if (typeof this.listConfig.categoryFieldKey === 'function') {
|
|
1008
|
+
currentCategoryId = this.listConfig.categoryFieldKey(item);
|
|
1009
|
+
}
|
|
1010
|
+
else if (typeof this.listConfig.categoryFieldKey === 'string') {
|
|
1011
|
+
currentCategoryId = item[this.listConfig.categoryFieldKey];
|
|
1012
|
+
}
|
|
1013
|
+
else {
|
|
1014
|
+
currentCategoryId = item.categoryId ?? item.category?.id;
|
|
1015
|
+
}
|
|
1016
|
+
const dialogRef = this.dialog.open(CategoryChangeDialog, {
|
|
1017
|
+
width: '400px',
|
|
1018
|
+
data: {
|
|
1019
|
+
itemLabel: label,
|
|
1020
|
+
categorySelectorConfig: this.categorySelectorConfig,
|
|
1021
|
+
currentCategoryId: currentCategoryId,
|
|
1022
|
+
positiveButtonText: this.t('common.save'),
|
|
1023
|
+
cancelButtonText: this.t('common.cancel'),
|
|
1024
|
+
},
|
|
1025
|
+
});
|
|
1026
|
+
const result = await lastValueFrom(dialogRef.afterClosed());
|
|
1027
|
+
if (!result) {
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const newCategoryId = result.categoryId;
|
|
1031
|
+
const categoryType = this.categorySelectorConfig.singularLabel || this.t('category.defaultSingular');
|
|
1032
|
+
try {
|
|
1033
|
+
await this.listConfig.categoryChanger(id, newCategoryId);
|
|
1034
|
+
}
|
|
1035
|
+
catch (e) {
|
|
1036
|
+
const errorMessage = getErrorMessage(e);
|
|
1037
|
+
this.snackbar.open(`Error: ${errorMessage || this.t('item.errorFailedCategoryChange', { label, categoryType })}`, undefined, { duration: 3000 });
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
this.snackbar.open(this.t('item.successCategoryChanged', { label, categoryType }), undefined, {
|
|
1041
|
+
duration: 3000,
|
|
1042
|
+
});
|
|
1043
|
+
this.fetchList();
|
|
1044
|
+
}
|
|
851
1045
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
852
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: NgxThinAdminList, isStandalone: true, selector: "ngx-thin-admin-list", inputs: { listConfig: "listConfig", categorySelectorConfig: "categorySelectorConfig", itemDeleterConfig: "itemDeleterConfig", listColumns: "listColumns", query: "query" }, viewQueries: [{ propertyName: "cellTplWithLink", first: true, predicate: ["cellTplWithLink"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Category Selector -->\n@if (categorySelectorConfig) {\n <lib-list-category-selector\n [config]=\"categorySelectorConfig\"\n [(selectedCategory)]=\"selectedCategory\"\n (selectedCategoryChange)=\"onSelectedCategoryChange($event)\"\n ></lib-list-category-selector>\n}\n<!---->\n\n<!-- Toolbar Template -->\n<ng-template #toolbarTpl>\n <div class=\"custom-toolbar\">\n <!-- List Title -->\n <span class=\"list-title\">\n @if (listConfig?.title; as listTitle) {\n @if (query.keyword || query.categoryId) {\n <!-- Title (with link for reset filter) -->\n <a\n href=\"javascript:void(0)\"\n (click)=\"query.keyword = ''; query.categoryId = undefined; this.fetchList()\"\n [matTooltip]=\"t('list.clearFilters')\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n {{ t('list.defaultTitle') }}\n <!---->\n }\n\n @if (query.categoryId && selectedCategory?.[0]; as categoryLabel) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Category -->\n {{ categoryLabel.label }}\n <!---->\n }\n\n @if (query.keyword) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Keyword -->\n \"{{ query.keyword }}\"\n <!---->\n }\n </span>\n <!---->\n\n @if (query.keyword || query.categoryId) {\n <span style=\"width: 8px\"></span>\n <!-- Clear Filters Button -->\n <button\n mat-icon-button\n class=\"clear-filters-button\"\n [matTooltip]=\"t('list.clearFilters')\"\n (click)=\"clearFilters()\"\n >\n <mat-icon>filter_alt_off</mat-icon>\n </button>\n <!---->\n }\n\n <span style=\"flex: 1\"></span>\n\n <!-- Create Button -->\n @if (listConfig?.createButton; as createBtn) {\n @if ($any(createBtn).routerLink; as routerLinkUrl) {\n <!-- Create Button with Router Link -->\n <a\n [routerLink]=\"routerLinkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).link; as linkUrl) {\n <!-- Create Button with Link -->\n <a\n [href]=\"linkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).click; as handler) {\n <!-- Create Button with Handler -->\n <button\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </button>\n }\n }\n <!---->\n\n <span style=\"width: 30px\"></span>\n\n <!-- Search Field -->\n <mat-form-field class=\"search-keyword xs-input\" appearance=\"outline\">\n <mat-icon matPrefix>search</mat-icon>\n <input\n matInput\n [placeholder]=\"\n selectedCategory?.[0]?.label\n ? t('list.searchInCategoryPlaceholder', { category: selectedCategory?.[0]?.label })\n : t('list.searchDefaultPlaceholder')\n \"\n [(ngModel)]=\"query.keyword\"\n (keyup)=\"onKeywordInput()\"\n style=\"padding-top: 3px\"\n />\n\n <!-- Search clear button -->\n <button\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"t('list.clearSearchKeyword')\"\n [matTooltip]=\"t('list.clearSearchKeyword')\"\n (click)=\"query.keyword = ''; this.fetchList()\"\n [style.visibility]=\"query.keyword ? 'visible' : 'hidden'\"\n >\n <mat-icon>highlight_off</mat-icon>\n </button>\n <!---->\n </mat-form-field>\n <!---->\n\n <span style=\"width: 8px\"></span>\n\n <!-- Refresh Button -->\n <button mat-icon-button [matTooltip]=\"t('list.refresh')\" (click)=\"fetchList()\">\n <mat-icon>refresh</mat-icon>\n </button>\n <!---->\n\n <span style=\"width: 5px\"></span>\n\n <!-- CSV Export Button -->\n <button\n mat-icon-button\n [matMenuTriggerFor]=\"csvExportMenu\"\n [matTooltip]=\"t('list.exportAsCsv')\"\n >\n <mat-icon>download</mat-icon>\n </button>\n <!---->\n\n <!-- CSV Export Menu -->\n <mat-menu #csvExportMenu=\"matMenu\">\n @for (encoder of csvExportService.getAvailableEncoders(); track encoder.key) {\n <!-- Export with specific charset -->\n <p style=\"color: #333; font-size: 0.8rem; margin: 1rem 0.75rem 1rem 0.7rem\">\n CSV ({{ encoder.label }})\n </p>\n <button mat-menu-item (click)=\"exportAsCsv(encoder.key)\">\n <mat-icon>download</mat-icon>\n <span>{{ t('list.exportItems', { count: totalCount }) }}</span>\n </button>\n <!---->\n }\n </mat-menu>\n <!---->\n </div>\n</ng-template>\n<!---->\n\n<!-- List (Grid) -->\n<mtx-grid\n [data]=\"gridData\"\n [columns]=\"gridColumns\"\n [showToolbar]=\"true\"\n [toolbarTemplate]=\"toolbarTpl\"\n [length]=\"totalCount\"\n [loading]=\"isLoading\"\n [pageOnFront]=\"false\"\n [pageIndex]=\"query.page\"\n [pageSize]=\"query.perPage\"\n [pageSizeOptions]=\"listConfig?.pageSizes ?? [10, 25, 50, 100]\"\n columnMenuButtonType=\"icon\"\n columnMenuButtonClass=\"column-menu-button\"\n columnMenuButtonIcon=\"view_column\"\n (page)=\"onPageChange($event)\"\n></mtx-grid>\n<!---->\n\n<!-- Cell Template with Link -->\n<ng-template #cellTplWithLink let-row let-index=\"index\" let-col=\"colDef\">\n @if (col.link) {\n <a [href]=\"col.link(row)\">\n {{ row[col.field] }}\n </a>\n } @else if (col.routerLink) {\n <a [routerLink]=\"col.routerLink(row)\">\n {{ row[col.field] }}\n </a>\n } @else {\n {{ row[col.field] }}\n }\n</ng-template>\n<!---->\n", styles: [":host{display:flex;gap:1rem;padding:1rem;box-sizing:border-box}lib-list-category-selector{display:block;width:200px;background-color:#fcfcfc;border-radius:9px;padding:.5rem;box-sizing:border-box}lib-list-category-selector .category-list{max-height:300px;overflow-y:auto}::ng-deep .mtx-grid-toolbar{display:block;background-color:#fcfcfc;border-top-left-radius:9px;border-top-right-radius:9px;margin-bottom:1px}::ng-deep .mtx-grid-toolbar .custom-toolbar{display:flex;align-items:center;justify-content:space-between;height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title{font-size:1rem;line-height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a{color:var(--mat-theme-primary)}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a:hover{text-decoration:underline}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title .list-title-separator{color:#aaa;vertical-align:middle;margin:auto .2rem 4px}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button{color:var(--mat-sys-on-primary-container);min-width:32px;padding:0;vertical-align:middle}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button mat-icon{vertical-align:middle;margin-bottom:3px}::ng-deep .mtx-grid-toolbar .custom-toolbar .create-item-button{text-decoration:none!important}::ng-deep .mtx-grid-toolbar .custom-toolbar .search-keyword{width:15rem;--mat-form-field-container-height: 18.5px;--mat-form-field-container-text-line-height: 18.5px;--mat-form-field-container-vertical-padding: 8.5px;--mat-form-field-outlined-container-shape: 28px;--mat-form-field-subscript-text-line-height: 0px}::ng-deep .mtx-grid-toolbar .custom-toolbar button{color:var(--mat-sys-on-primary-container)}::ng-deep .mtx-grid-toolbar ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mtx-grid-toolbar ::ng-deep mtx-grid-column-menu button[mat-icon-button]{color:var(--mat-sys-on-primary-container);margin-right:.5rem}::ng-deep .mtx-grid-main{background-color:#fcfcfc}table{width:100%}::ng-deep table thead,::ng-deep table tbody{background-color:#fcfcfc!important}::ng-deep .mtx-grid-footer,::ng-deep .mat-mdc-paginator{display:block;background-color:#fcfcfc!important;border-bottom-left-radius:9px!important;border-bottom-right-radius:9px!important}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MtxGridModule }, { kind: "component", type: i2$2.MtxGrid, selector: "mtx-grid", inputs: ["displayedColumns", "columns", "data", "length", "loading", "trackBy", "columnResizable", "emptyValuePlaceholder", "pageOnFront", "showPaginator", "pageDisabled", "showFirstLastButtons", "pageIndex", "pageSize", "pageSizeOptions", "hidePageSize", "paginationTemplate", "sortOnFront", "sortActive", "sortDirection", "sortDisableClear", "sortDisabled", "sortStart", "rowHover", "rowStriped", "expandable", "expansionTemplate", "multiSelectable", "multiSelectionWithClick", "rowSelectable", "hideRowSelectionCheckbox", "disableRowClickSelection", "rowSelectionFormatter", "rowClassFormatter", "rowSelected", "cellSelectable", "showToolbar", "toolbarTitle", "toolbarTemplate", "columnHideable", "columnHideableChecked", "columnSortable", "columnPinnable", "columnPinOptions", "showColumnMenuButton", "columnMenuButtonText", "columnMenuButtonType", "columnMenuButtonColor", "columnMenuButtonClass", "columnMenuButtonIcon", "columnMenuButtonFontIcon", "columnMenuButtonSvgIcon", "showColumnMenuHeader", "columnMenuHeaderText", "columnMenuHeaderTemplate", "showColumnMenuFooter", "columnMenuFooterText", "columnMenuFooterTemplate", "noResultText", "noResultTemplate", "headerTemplate", "headerExtraTemplate", "cellTemplate", "useContentRowTemplate", "useContentHeaderRowTemplate", "useContentFooterRowTemplate", "showSummary", "summaryTemplate", "showSidebar", "sidebarTemplate", "showStatusbar", "statusbarTemplate"], outputs: ["page", "sortChange", "rowClick", "rowContextMenu", "expansionChange", "rowSelectedChange", "cellSelectedChange", "columnChange"], exportAs: ["mtxGrid"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: ListCategorySelector, selector: "lib-list-category-selector", inputs: ["config", "selectedCategory"], outputs: ["selectedCategoryChange"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
|
|
1046
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: NgxThinAdminList, isStandalone: true, selector: "ngx-thin-admin-list", inputs: { listConfig: "listConfig", categorySelectorConfig: "categorySelectorConfig", itemDeleterConfig: "itemDeleterConfig", listColumns: "listColumns", query: "query" }, viewQueries: [{ propertyName: "cellTplWithLink", first: true, predicate: ["cellTplWithLink"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Category Selector -->\n@if (categorySelectorConfig) {\n <lib-list-category-selector\n [config]=\"categorySelectorConfig\"\n [(selectedCategory)]=\"selectedCategory\"\n (selectedCategoryChange)=\"onSelectedCategoryChange($event)\"\n ></lib-list-category-selector>\n}\n<!---->\n\n<!-- Toolbar Template -->\n<ng-template #toolbarTpl>\n <div class=\"custom-toolbar\">\n <!-- List Title -->\n <span class=\"list-title\">\n @if (listConfig?.title; as listTitle) {\n @if (query.keyword || query.categoryId) {\n <!-- Title (with link for reset filter) -->\n <a\n href=\"javascript:void(0)\"\n (click)=\"query.keyword = ''; query.categoryId = undefined; this.fetchList()\"\n [matTooltip]=\"t('list.clearFilters')\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n {{ t('list.defaultTitle') }}\n <!---->\n }\n\n @if (query.categoryId && selectedCategory?.[0]; as categoryLabel) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Category -->\n {{ categoryLabel.label }}\n <!---->\n }\n\n @if (query.keyword) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Keyword -->\n \"{{ query.keyword }}\"\n <!---->\n }\n </span>\n <!---->\n\n @if (query.keyword || query.categoryId) {\n <span style=\"width: 8px\"></span>\n <!-- Clear Filters Button -->\n <button\n mat-icon-button\n class=\"clear-filters-button\"\n [matTooltip]=\"t('list.clearFilters')\"\n (click)=\"clearFilters()\"\n >\n <mat-icon>filter_alt_off</mat-icon>\n </button>\n <!---->\n }\n\n <span style=\"flex: 1\"></span>\n\n <!-- Create Button -->\n @if (listConfig?.createButton; as createBtn) {\n @if ($any(createBtn).routerLink; as routerLinkUrl) {\n <!-- Create Button with Router Link -->\n <a\n [routerLink]=\"routerLinkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).link; as linkUrl) {\n <!-- Create Button with Link -->\n <a\n [href]=\"linkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).click; as handler) {\n <!-- Create Button with Handler -->\n <button\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </button>\n }\n }\n <!---->\n\n <span style=\"width: 30px\"></span>\n\n <!-- Search Field -->\n <mat-form-field class=\"search-keyword xs-input\" appearance=\"outline\">\n <mat-icon matPrefix>search</mat-icon>\n <input\n matInput\n [placeholder]=\"\n selectedCategory?.[0]?.label\n ? t('list.searchInCategoryPlaceholder', { category: selectedCategory?.[0]?.label })\n : t('list.searchDefaultPlaceholder')\n \"\n [(ngModel)]=\"query.keyword\"\n (keyup)=\"onKeywordInput()\"\n style=\"padding-top: 3px\"\n />\n\n <!-- Search clear button -->\n <button\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"t('list.clearSearchKeyword')\"\n [matTooltip]=\"t('list.clearSearchKeyword')\"\n (click)=\"query.keyword = ''; this.fetchList()\"\n [style.visibility]=\"query.keyword ? 'visible' : 'hidden'\"\n >\n <mat-icon>highlight_off</mat-icon>\n </button>\n <!---->\n </mat-form-field>\n <!---->\n\n <span style=\"width: 8px\"></span>\n\n <!-- Refresh Button -->\n <button mat-icon-button [matTooltip]=\"t('list.refresh')\" (click)=\"fetchList()\">\n <mat-icon>refresh</mat-icon>\n </button>\n <!---->\n\n <span style=\"width: 5px\"></span>\n\n <!-- CSV Export Button -->\n <button\n mat-icon-button\n [matMenuTriggerFor]=\"csvExportMenu\"\n [matTooltip]=\"t('list.exportAsCsv')\"\n >\n <mat-icon>download</mat-icon>\n </button>\n <!---->\n\n <!-- CSV Export Menu -->\n <mat-menu #csvExportMenu=\"matMenu\">\n @for (encoder of csvExportService.getAvailableEncoders(); track encoder.key) {\n <!-- Export with specific charset -->\n <p style=\"color: #333; font-size: 0.8rem; margin: 1rem 0.75rem 1rem 0.7rem\">\n CSV ({{ encoder.label }})\n </p>\n <button mat-menu-item (click)=\"exportAsCsv(encoder.key)\">\n <mat-icon>download</mat-icon>\n <span>{{ t('list.exportItems', { count: totalCount }) }}</span>\n </button>\n <!---->\n }\n </mat-menu>\n <!---->\n </div>\n</ng-template>\n<!---->\n\n<!-- List (Grid) -->\n<mtx-grid\n [data]=\"gridData\"\n [columns]=\"gridColumns\"\n [showToolbar]=\"true\"\n [toolbarTemplate]=\"toolbarTpl\"\n [length]=\"totalCount\"\n [loading]=\"isLoading\"\n [pageOnFront]=\"false\"\n [pageIndex]=\"query.page\"\n [pageSize]=\"query.perPage\"\n [pageSizeOptions]=\"listConfig?.pageSizes ?? [10, 25, 50, 100]\"\n columnMenuButtonType=\"icon\"\n columnMenuButtonClass=\"column-menu-button\"\n columnMenuButtonIcon=\"view_column\"\n (page)=\"onPageChange($event)\"\n></mtx-grid>\n<!---->\n\n<!-- Cell Template with Link -->\n<ng-template #cellTplWithLink let-row let-index=\"index\" let-col=\"colDef\">\n @if (col.link) {\n <a [href]=\"col.link(row)\">\n {{ row[col.field] }}\n </a>\n } @else if (col.routerLink) {\n <a [routerLink]=\"col.routerLink(row)\">\n {{ row[col.field] }}\n </a>\n } @else {\n {{ row[col.field] }}\n }\n</ng-template>\n<!---->\n", styles: [":host{display:flex;gap:1rem;padding:1rem;box-sizing:border-box}lib-list-category-selector{display:block;width:200px;background-color:#fcfcfc;border-radius:9px;padding:.5rem;box-sizing:border-box}lib-list-category-selector .category-list{max-height:300px;overflow-y:auto}::ng-deep .mtx-grid-toolbar{display:block;background-color:#fcfcfc;border-top-left-radius:9px;border-top-right-radius:9px;margin-bottom:1px}::ng-deep .mtx-grid-toolbar .custom-toolbar{display:flex;align-items:center;justify-content:space-between;height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title{font-size:1rem;line-height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a{color:var(--mat-theme-primary)}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a:hover{text-decoration:underline}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title .list-title-separator{color:#aaa;vertical-align:middle;margin:auto .2rem 4px}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button{color:var(--mat-sys-on-primary-container);min-width:32px;padding:0;vertical-align:middle}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button mat-icon{vertical-align:middle;margin-bottom:3px}::ng-deep .mtx-grid-toolbar .custom-toolbar .create-item-button{text-decoration:none!important}::ng-deep .mtx-grid-toolbar .custom-toolbar .search-keyword{width:15rem;--mat-form-field-container-height: 18.5px;--mat-form-field-container-text-line-height: 18.5px;--mat-form-field-container-vertical-padding: 8.5px;--mat-form-field-outlined-container-shape: 28px;--mat-form-field-subscript-text-line-height: 0px}::ng-deep .mtx-grid-toolbar .custom-toolbar button{color:var(--mat-sys-on-primary-container)}::ng-deep .mtx-grid-toolbar ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mtx-grid-toolbar ::ng-deep mtx-grid-column-menu button[mat-icon-button]{color:var(--mat-sys-on-primary-container);margin-right:.5rem}::ng-deep .mtx-grid-main{background-color:#fcfcfc}table{width:100%}::ng-deep table thead,::ng-deep table tbody{background-color:#fcfcfc!important}::ng-deep .mtx-grid-footer,::ng-deep .mat-mdc-paginator{display:block;background-color:#fcfcfc!important;border-bottom-left-radius:9px!important;border-bottom-right-radius:9px!important}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MtxGridModule }, { kind: "component", type: i2$2.MtxGrid, selector: "mtx-grid", inputs: ["displayedColumns", "columns", "data", "length", "loading", "trackBy", "columnResizable", "emptyValuePlaceholder", "pageOnFront", "showPaginator", "pageDisabled", "showFirstLastButtons", "pageIndex", "pageSize", "pageSizeOptions", "hidePageSize", "paginationTemplate", "sortOnFront", "sortActive", "sortDirection", "sortDisableClear", "sortDisabled", "sortStart", "rowHover", "rowStriped", "expandable", "expansionTemplate", "multiSelectable", "multiSelectionWithClick", "rowSelectable", "hideRowSelectionCheckbox", "disableRowClickSelection", "rowSelectionFormatter", "rowClassFormatter", "rowSelected", "cellSelectable", "showToolbar", "toolbarTitle", "toolbarTemplate", "columnHideable", "columnHideableChecked", "columnSortable", "columnPinnable", "columnPinOptions", "showColumnMenuButton", "columnMenuButtonText", "columnMenuButtonType", "columnMenuButtonColor", "columnMenuButtonClass", "columnMenuButtonIcon", "columnMenuButtonFontIcon", "columnMenuButtonSvgIcon", "showColumnMenuHeader", "columnMenuHeaderText", "columnMenuHeaderTemplate", "showColumnMenuFooter", "columnMenuFooterText", "columnMenuFooterTemplate", "noResultText", "noResultTemplate", "headerTemplate", "headerExtraTemplate", "cellTemplate", "useContentRowTemplate", "useContentHeaderRowTemplate", "useContentFooterRowTemplate", "showSummary", "summaryTemplate", "showSidebar", "sidebarTemplate", "showStatusbar", "statusbarTemplate"], outputs: ["page", "sortChange", "rowClick", "rowContextMenu", "expansionChange", "rowSelectedChange", "cellSelectedChange", "columnChange"], exportAs: ["mtxGrid"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: ListCategorySelector, selector: "lib-list-category-selector", inputs: ["config", "selectedCategory"], outputs: ["selectedCategoryChange"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
|
|
853
1047
|
}
|
|
854
1048
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminList, decorators: [{
|
|
855
1049
|
type: Component,
|
|
@@ -1019,7 +1213,7 @@ class FormlyFieldFile extends FieldType {
|
|
|
1019
1213
|
<mat-hint>{{ props.description }}</mat-hint>
|
|
1020
1214
|
}
|
|
1021
1215
|
</mat-form-field>
|
|
1022
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: FormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2
|
|
1216
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: FormlyAttributes, selector: "[formlyAttributes]", inputs: ["formlyAttributes", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
|
|
1023
1217
|
}
|
|
1024
1218
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FormlyFieldFile, decorators: [{
|
|
1025
1219
|
type: Component,
|
|
@@ -1325,7 +1519,7 @@ class NgxThinAdminEditor {
|
|
|
1325
1519
|
subscriptSizing: 'dynamic',
|
|
1326
1520
|
},
|
|
1327
1521
|
},
|
|
1328
|
-
], usesOnChanges: true, ngImport: i0, template: "<mat-card>\n <mat-card-header style=\"position: relative\">\n <!-- Back button -->\n @if (editorConfig?.backButton) {\n @if ($any(editorConfig?.backButton).historyBack && windowHistory.length > 1) {\n <button mat-button (click)=\"windowHistory.back()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n } @else if ($any(editorConfig?.backButton).routerLink; as backButtonLink) {\n <a [routerLink]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).link; as backButtonLink) {\n <a [href]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).click; as handler) {\n <button mat-button (click)=\"handler()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n }\n }\n <!---->\n\n <!-- Editor title -->\n <h3 style=\"margin: 0\" [style.margin-top]=\"editorConfig?.backButton ? '1rem' : '0'\">\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n {{ t('common.edit') }} <span style=\"color: #aaaaaa\">-</span>\n <span class=\"editor-item-label\">{{ editItem[editorConfig!.labelFieldKey!] }}</span>\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n } @else if (editItem.id) {\n <!-- e.g., \"Edit - ID: 123\" -->\n {{ t('common.edit') }} <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n <!---->\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\" style=\"margin-top: 1rem\"></mat-progress-bar>\n }\n\n @if (!isLoading) {\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <formly-form\n [form]=\"form\"\n [fields]=\"$any(editorFields) ?? []\"\n [model]=\"formData\"\n ></formly-form>\n\n <!-- Button Area -->\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-top: 0.5rem;\n \"\n >\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n", styles: [":host{max-width:600px;display:block;margin:0 auto}mat-card{padding:2rem}mat-card-header h3{font-size:1.2rem;font-weight:400}mat-card-header .editor-item-label{margin-left:1rem}mat-card-header .editor-header-sub{color:#555;margin-left:.85rem;font-size:.9rem;font-style:italic}form{margin-top:2rem}form ::ng-deep .mat-mdc-form-field-subscript-wrapper{margin-bottom:14px!important}.back-link{display:flex;position:absolute;top:-1.5rem;left:-1rem;align-items:center;gap:.3rem;font-size:.8rem}.back-link mat-icon{height:.8rem;width:.8rem;font-size:.8rem}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type:
|
|
1522
|
+
], usesOnChanges: true, ngImport: i0, template: "<mat-card>\n <mat-card-header style=\"position: relative\">\n <!-- Back button -->\n @if (editorConfig?.backButton) {\n @if ($any(editorConfig?.backButton).historyBack && windowHistory.length > 1) {\n <button mat-button (click)=\"windowHistory.back()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n } @else if ($any(editorConfig?.backButton).routerLink; as backButtonLink) {\n <a [routerLink]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).link; as backButtonLink) {\n <a [href]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).click; as handler) {\n <button mat-button (click)=\"handler()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n }\n }\n <!---->\n\n <!-- Editor title -->\n <h3 style=\"margin: 0\" [style.margin-top]=\"editorConfig?.backButton ? '1rem' : '0'\">\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n {{ t('common.edit') }} <span style=\"color: #aaaaaa\">-</span>\n <span class=\"editor-item-label\">{{ editItem[editorConfig!.labelFieldKey!] }}</span>\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n } @else if (editItem.id) {\n <!-- e.g., \"Edit - ID: 123\" -->\n {{ t('common.edit') }} <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n <!---->\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\" style=\"margin-top: 1rem\"></mat-progress-bar>\n }\n\n @if (!isLoading) {\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <formly-form\n [form]=\"form\"\n [fields]=\"$any(editorFields) ?? []\"\n [model]=\"formData\"\n ></formly-form>\n\n <!-- Button Area -->\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-top: 0.5rem;\n \"\n >\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n", styles: [":host{max-width:600px;display:block;margin:0 auto}mat-card{padding:2rem}mat-card-header h3{font-size:1.2rem;font-weight:400}mat-card-header .editor-item-label{margin-left:1rem}mat-card-header .editor-header-sub{color:#555;margin-left:.85rem;font-size:.9rem;font-style:italic}form{margin-top:2rem}form ::ng-deep .mat-mdc-form-field-subscript-wrapper{margin-bottom:14px!important}.back-link{display:flex;position:absolute;top:-1.5rem;left:-1rem;align-items:center;gap:.3rem;font-size:.8rem}.back-link mat-icon{height:.8rem;width:.8rem;font-size:.8rem}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }] });
|
|
1329
1523
|
}
|
|
1330
1524
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminEditor, decorators: [{
|
|
1331
1525
|
type: Component,
|