ngx-thin-admin 0.0.0-alpha.1 → 0.0.0-alpha.2
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Component, EventEmitter, ChangeDetectorRef, Output, Input, Injectable, ViewChild } from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, Component, EventEmitter, ChangeDetectorRef, Output, Input, Injectable, ViewChild } from '@angular/core';
|
|
3
3
|
import { lastValueFrom, Subject } from 'rxjs';
|
|
4
4
|
import { debounceTime } from 'rxjs/operators';
|
|
5
5
|
import * as i4 from '@angular/material/button';
|
|
@@ -26,10 +26,121 @@ import { FieldWrapper, FieldType, FormlyAttributes, FormlyForm, provideFormlyCor
|
|
|
26
26
|
import { withFormlyMaterial } from '@ngx-formly/material';
|
|
27
27
|
import { MatProgressBar } from '@angular/material/progress-bar';
|
|
28
28
|
|
|
29
|
+
const messagesEn = {
|
|
30
|
+
'common.cancel': 'Cancel',
|
|
31
|
+
'common.ok': 'OK',
|
|
32
|
+
'common.save': 'Save',
|
|
33
|
+
'common.create': 'Create',
|
|
34
|
+
'common.edit': 'Edit',
|
|
35
|
+
'common.delete': 'Delete',
|
|
36
|
+
'list.defaultTitle': 'List',
|
|
37
|
+
'list.clearFilters': 'Clear filters',
|
|
38
|
+
'list.searchDefaultPlaceholder': 'Search...',
|
|
39
|
+
'list.searchInCategoryPlaceholder': 'Search in {category}...',
|
|
40
|
+
'list.clearSearchKeyword': 'Clear search keyword',
|
|
41
|
+
'list.refresh': 'Refresh',
|
|
42
|
+
'list.exportAsCsv': 'Export as CSV',
|
|
43
|
+
'list.exportedFileName': 'exported',
|
|
44
|
+
'list.exportItems': 'Export {count} items',
|
|
45
|
+
'editor.idLabel': 'ID',
|
|
46
|
+
'editor.saveChanges': 'Save Changes',
|
|
47
|
+
'editor.errorInvalidInput': 'Invalid input',
|
|
48
|
+
'editor.errorNoSaver': 'No saver function provided',
|
|
49
|
+
'editor.successSaved': 'Data saved successfully',
|
|
50
|
+
'category.defaultSingular': 'Category',
|
|
51
|
+
'category.defaultPlural': 'Categories',
|
|
52
|
+
'category.all': 'All',
|
|
53
|
+
'category.editorDialogTitleForCreate': 'Create {categoryType}',
|
|
54
|
+
'category.editorDialogTitleForEdit': 'Edit {categoryType}',
|
|
55
|
+
'category.deletionDialogTitle': 'Delete {categoryType}',
|
|
56
|
+
'category.deletionDialogMessage': 'Are you sure you want to delete the {categoryType} "{label}"? This action cannot be undone.',
|
|
57
|
+
'category.errorCouldNotCreate': 'Could not create category',
|
|
58
|
+
'category.errorFailedUpdate': 'Failed to update category "{label}"',
|
|
59
|
+
'category.errorFailedDelete': 'Failed to delete category "{label}"',
|
|
60
|
+
'category.errorCouldNotSave': 'Could not save category',
|
|
61
|
+
'csv.exporting': 'Exporting CSV...',
|
|
62
|
+
'csv.exportCompleted': 'CSV export completed. Exported {count} items.',
|
|
63
|
+
'csv.exportCompletedWithErrors': 'CSV exported up to {count} items, but errors occurred: {error}',
|
|
64
|
+
'csv.errorGenerateFailed': 'Failed to generate CSV file.',
|
|
65
|
+
};
|
|
66
|
+
const messagesJa = {
|
|
67
|
+
'common.cancel': 'キャンセル',
|
|
68
|
+
'common.ok': 'OK',
|
|
69
|
+
'common.save': '保存',
|
|
70
|
+
'common.create': '作成',
|
|
71
|
+
'common.edit': '編集',
|
|
72
|
+
'common.delete': '削除',
|
|
73
|
+
'list.defaultTitle': '一覧',
|
|
74
|
+
'list.clearFilters': 'フィルターをクリア',
|
|
75
|
+
'list.searchDefaultPlaceholder': '検索...',
|
|
76
|
+
'list.searchInCategoryPlaceholder': '{category} 内を検索...',
|
|
77
|
+
'list.clearSearchKeyword': '検索キーワードをクリア',
|
|
78
|
+
'list.refresh': '再読み込み',
|
|
79
|
+
'list.exportAsCsv': 'CSV でエクスポート',
|
|
80
|
+
'list.exportedFileName': 'exported',
|
|
81
|
+
'list.exportItems': '{count} 件をエクスポート',
|
|
82
|
+
'editor.idLabel': 'ID',
|
|
83
|
+
'editor.saveChanges': '変更を保存',
|
|
84
|
+
'editor.errorInvalidInput': '入力内容が不正です',
|
|
85
|
+
'editor.errorNoSaver': '保存処理が設定されていません',
|
|
86
|
+
'editor.successSaved': '保存しました',
|
|
87
|
+
'category.defaultSingular': 'カテゴリ',
|
|
88
|
+
'category.defaultPlural': 'カテゴリ',
|
|
89
|
+
'category.all': 'すべて',
|
|
90
|
+
'category.editorDialogTitleForCreate': '{categoryType} の作成',
|
|
91
|
+
'category.editorDialogTitleForEdit': '{categoryType} の編集',
|
|
92
|
+
'category.deletionDialogTitle': '{categoryType} の削除',
|
|
93
|
+
'category.deletionDialogMessage': '{categoryType} "{label}" を削除しますか?この操作は元に戻せません。',
|
|
94
|
+
'category.errorCouldNotCreate': 'カテゴリを作成できませんでした',
|
|
95
|
+
'category.errorFailedUpdate': 'カテゴリ "{label}" の更新に失敗しました',
|
|
96
|
+
'category.errorFailedDelete': 'カテゴリ "{label}" の削除に失敗しました',
|
|
97
|
+
'category.errorCouldNotSave': 'カテゴリを保存できませんでした',
|
|
98
|
+
'csv.exporting': 'CSV をエクスポート中...',
|
|
99
|
+
'csv.exportCompleted': 'CSV エクスポートが完了しました。{count} 件をエクスポートしました。',
|
|
100
|
+
'csv.exportCompletedWithErrors': '{count} 件までエクスポートしましたが、エラーが発生しました: {error}',
|
|
101
|
+
'csv.errorGenerateFailed': 'CSV ファイルの生成に失敗しました。',
|
|
102
|
+
};
|
|
103
|
+
function interpolate(message, params) {
|
|
104
|
+
if (!params) {
|
|
105
|
+
return message;
|
|
106
|
+
}
|
|
107
|
+
return message.replace(/\{(\w+)\}/g, (_, key) => {
|
|
108
|
+
const value = params[key];
|
|
109
|
+
return value === undefined ? '' : String(value);
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function createTranslatorFromMessages(baseMessages, overrides) {
|
|
113
|
+
const merged = { ...baseMessages, ...overrides };
|
|
114
|
+
return (key, params) => {
|
|
115
|
+
return interpolate(merged[key] ?? messagesEn[key], params);
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const NGX_THIN_ADMIN_TRANSLATE = new InjectionToken('NGX_THIN_ADMIN_TRANSLATE', {
|
|
119
|
+
providedIn: 'root',
|
|
120
|
+
factory: () => createTranslatorFromMessages(messagesEn),
|
|
121
|
+
});
|
|
122
|
+
function provideNgxThinAdminI18n(config) {
|
|
123
|
+
return {
|
|
124
|
+
provide: NGX_THIN_ADMIN_TRANSLATE,
|
|
125
|
+
useFactory: () => {
|
|
126
|
+
if (config?.translate) {
|
|
127
|
+
return config.translate;
|
|
128
|
+
}
|
|
129
|
+
const locale = config?.locale ?? 'en';
|
|
130
|
+
const base = locale === 'ja' ? messagesJa : messagesEn;
|
|
131
|
+
return createTranslatorFromMessages(base, config?.messages);
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
29
136
|
class CategoryEditorDialog {
|
|
30
137
|
dialogRef = inject((MatDialogRef));
|
|
31
138
|
data = inject(MAT_DIALOG_DATA);
|
|
139
|
+
translate = inject(NGX_THIN_ADMIN_TRANSLATE);
|
|
32
140
|
categoryLabel;
|
|
141
|
+
t(key, params) {
|
|
142
|
+
return this.translate(key, params);
|
|
143
|
+
}
|
|
33
144
|
save() {
|
|
34
145
|
if (!this.categoryLabel) {
|
|
35
146
|
return;
|
|
@@ -39,7 +150,7 @@ class CategoryEditorDialog {
|
|
|
39
150
|
});
|
|
40
151
|
}
|
|
41
152
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CategoryEditorDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
42
|
-
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
|
|
153
|
+
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: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.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: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.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"] }] });
|
|
43
154
|
}
|
|
44
155
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: CategoryEditorDialog, decorators: [{
|
|
45
156
|
type: Component,
|
|
@@ -52,14 +163,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
52
163
|
MatDialogContent,
|
|
53
164
|
MatDialogActions,
|
|
54
165
|
MatDialogClose,
|
|
55
|
-
], template: "<h2 mat-dialog-title>\n @if (data.editCategory) {\n
|
|
166
|
+
], 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"] }]
|
|
56
167
|
}] });
|
|
57
168
|
|
|
58
169
|
class ConfirmDialog {
|
|
59
170
|
dialogRef = inject((MatDialogRef));
|
|
60
171
|
data = inject(MAT_DIALOG_DATA);
|
|
172
|
+
translate = inject(NGX_THIN_ADMIN_TRANSLATE);
|
|
173
|
+
t(key, params) {
|
|
174
|
+
return this.translate(key, params);
|
|
175
|
+
}
|
|
61
176
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ConfirmDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
62
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: ConfirmDialog, isStandalone: true, selector: "lib-confirm-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{ data.title }}</h2>\n<mat-dialog-content>\n {{ data.message }}\n</mat-dialog-content>\n<mat-dialog-actions>\n <button class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText || '
|
|
177
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.5", type: ConfirmDialog, isStandalone: true, selector: "lib-confirm-dialog", ngImport: i0, template: "<h2 mat-dialog-title>{{ data.title }}</h2>\n<mat-dialog-content>\n {{ data.message }}\n</mat-dialog-content>\n<mat-dialog-actions>\n <button class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText || t('common.cancel') }}\n </button>\n <button matButton [mat-dialog-close]=\"true\" cdkFocusInitial>\n {{ data.positiveButtonText || t('common.ok') }}\n </button>\n</mat-dialog-actions>\n", styles: [".cancel-btn{--mat-button-text-label-text-color: #333}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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"] }] });
|
|
63
178
|
}
|
|
64
179
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ConfirmDialog, decorators: [{
|
|
65
180
|
type: Component,
|
|
@@ -70,7 +185,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
70
185
|
MatDialogContent,
|
|
71
186
|
MatDialogActions,
|
|
72
187
|
MatDialogClose,
|
|
73
|
-
], template: "<h2 mat-dialog-title>{{ data.title }}</h2>\n<mat-dialog-content>\n {{ data.message }}\n</mat-dialog-content>\n<mat-dialog-actions>\n <button class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText || '
|
|
188
|
+
], template: "<h2 mat-dialog-title>{{ data.title }}</h2>\n<mat-dialog-content>\n {{ data.message }}\n</mat-dialog-content>\n<mat-dialog-actions>\n <button class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText || t('common.cancel') }}\n </button>\n <button matButton [mat-dialog-close]=\"true\" cdkFocusInitial>\n {{ data.positiveButtonText || t('common.ok') }}\n </button>\n</mat-dialog-actions>\n", styles: [".cancel-btn{--mat-button-text-label-text-color: #333}\n"] }]
|
|
74
189
|
}] });
|
|
75
190
|
|
|
76
191
|
class ListCategorySelector {
|
|
@@ -96,6 +211,10 @@ class ListCategorySelector {
|
|
|
96
211
|
snackbar = inject(MatSnackBar);
|
|
97
212
|
dialog = inject(MatDialog);
|
|
98
213
|
cdr = inject(ChangeDetectorRef);
|
|
214
|
+
translate = inject(NGX_THIN_ADMIN_TRANSLATE);
|
|
215
|
+
t(key, params) {
|
|
216
|
+
return this.translate(key, params);
|
|
217
|
+
}
|
|
99
218
|
ngOnChanges(changes) {
|
|
100
219
|
if (changes.config &&
|
|
101
220
|
changes.config.currentValue?.fetcher !== changes.config.previousValue?.fetcher) {
|
|
@@ -130,7 +249,7 @@ class ListCategorySelector {
|
|
|
130
249
|
await this.config.creator(categoryLabel);
|
|
131
250
|
}
|
|
132
251
|
catch (e) {
|
|
133
|
-
this.snackbar.open(`Error: ${e?.message ?? '
|
|
252
|
+
this.snackbar.open(`Error: ${e?.message ?? this.t('category.errorCouldNotCreate')}`, undefined, {
|
|
134
253
|
duration: 3000,
|
|
135
254
|
});
|
|
136
255
|
}
|
|
@@ -146,7 +265,7 @@ class ListCategorySelector {
|
|
|
146
265
|
await this.config.updater(category);
|
|
147
266
|
}
|
|
148
267
|
catch (e) {
|
|
149
|
-
this.snackbar.open(`Error: ${e?.message ??
|
|
268
|
+
this.snackbar.open(`Error: ${e?.message ?? this.t('category.errorFailedUpdate', { label: category.label })}`, undefined, {
|
|
150
269
|
duration: 3000,
|
|
151
270
|
});
|
|
152
271
|
}
|
|
@@ -162,7 +281,7 @@ class ListCategorySelector {
|
|
|
162
281
|
await this.config.deleter(category);
|
|
163
282
|
}
|
|
164
283
|
catch (e) {
|
|
165
|
-
this.snackbar.open(`Error: ${e?.message ??
|
|
284
|
+
this.snackbar.open(`Error: ${e?.message ?? this.t('category.errorFailedDelete', { label: category.label })}`, undefined, {
|
|
166
285
|
duration: 3000,
|
|
167
286
|
});
|
|
168
287
|
}
|
|
@@ -176,8 +295,8 @@ class ListCategorySelector {
|
|
|
176
295
|
data: {
|
|
177
296
|
config: this.config,
|
|
178
297
|
editCategory: editCategory,
|
|
179
|
-
positiveButtonText: editCategory ? '
|
|
180
|
-
cancelButtonText: '
|
|
298
|
+
positiveButtonText: editCategory ? this.t('common.save') : this.t('common.create'),
|
|
299
|
+
cancelButtonText: this.t('common.cancel'),
|
|
181
300
|
},
|
|
182
301
|
});
|
|
183
302
|
const result = await lastValueFrom(dialogRef.afterClosed());
|
|
@@ -194,7 +313,7 @@ class ListCategorySelector {
|
|
|
194
313
|
}
|
|
195
314
|
}
|
|
196
315
|
catch (e) {
|
|
197
|
-
this.snackbar.open(`Error: ${e?.message ?? '
|
|
316
|
+
this.snackbar.open(`Error: ${e?.message ?? this.t('category.errorCouldNotSave')}`, undefined, {
|
|
198
317
|
duration: 3000,
|
|
199
318
|
});
|
|
200
319
|
}
|
|
@@ -206,10 +325,15 @@ class ListCategorySelector {
|
|
|
206
325
|
const dialogRef = this.dialog.open(ConfirmDialog, {
|
|
207
326
|
width: '400px',
|
|
208
327
|
data: {
|
|
209
|
-
title: '
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
328
|
+
title: this.t('category.deletionDialogTitle', {
|
|
329
|
+
categoryType: this.config?.singularLabel ?? this.t('category.defaultSingular'),
|
|
330
|
+
}),
|
|
331
|
+
message: this.t('category.deletionDialogMessage', {
|
|
332
|
+
categoryType: this.config?.singularLabel ?? this.t('category.defaultSingular'),
|
|
333
|
+
label: category.label,
|
|
334
|
+
}),
|
|
335
|
+
positiveButtonText: this.t('common.delete'),
|
|
336
|
+
cancelButtonText: this.t('common.cancel'),
|
|
213
337
|
},
|
|
214
338
|
});
|
|
215
339
|
const result = await lastValueFrom(dialogRef.afterClosed());
|
|
@@ -221,7 +345,7 @@ class ListCategorySelector {
|
|
|
221
345
|
await this.deleteCategory(category);
|
|
222
346
|
}
|
|
223
347
|
catch (e) {
|
|
224
|
-
this.snackbar.open(`Error: ${e?.message ??
|
|
348
|
+
this.snackbar.open(`Error: ${e?.message ?? this.t('category.errorFailedDelete', { label: category.label })}`, undefined, {
|
|
225
349
|
duration: 3000,
|
|
226
350
|
});
|
|
227
351
|
}
|
|
@@ -229,7 +353,7 @@ class ListCategorySelector {
|
|
|
229
353
|
this.fetchCategories();
|
|
230
354
|
}
|
|
231
355
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ListCategorySelector, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
232
|
-
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\"
|
|
356
|
+
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: 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: "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]" }] });
|
|
233
357
|
}
|
|
234
358
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: ListCategorySelector, decorators: [{
|
|
235
359
|
type: Component,
|
|
@@ -243,7 +367,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
243
367
|
MatMenuTrigger,
|
|
244
368
|
MatListOption,
|
|
245
369
|
MatMenuContent,
|
|
246
|
-
], template: "<header>\n <!-- Category selector title -->\n <span class=\"category-selector-title\"
|
|
370
|
+
], 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"] }]
|
|
247
371
|
}], propDecorators: { config: [{
|
|
248
372
|
type: Input
|
|
249
373
|
}], selectedCategory: [{
|
|
@@ -254,6 +378,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
254
378
|
|
|
255
379
|
class CsvExportService {
|
|
256
380
|
snackbar = inject(MatSnackBar);
|
|
381
|
+
translate = inject(NGX_THIN_ADMIN_TRANSLATE);
|
|
257
382
|
encoders = [
|
|
258
383
|
{
|
|
259
384
|
key: 'utf8',
|
|
@@ -310,8 +435,8 @@ class CsvExportService {
|
|
|
310
435
|
// Initialize
|
|
311
436
|
const items = [];
|
|
312
437
|
let errorMessage = undefined;
|
|
313
|
-
//
|
|
314
|
-
const mes = this.snackbar.open('
|
|
438
|
+
// 処理中メッセージを表示
|
|
439
|
+
const mes = this.snackbar.open(this.translate('csv.exporting'));
|
|
315
440
|
// Replace characters in the file name prefix that cannot be used in file names
|
|
316
441
|
fileNamePrefix = fileNamePrefix.replace(/[/¥\\*?:"<>|@\s;^.]/g, '_');
|
|
317
442
|
// Truncate the file name prefix if it is too long
|
|
@@ -405,7 +530,7 @@ class CsvExportService {
|
|
|
405
530
|
if (!blob) {
|
|
406
531
|
console.error(`exportListAsCsv - Blob is not created`);
|
|
407
532
|
mes.dismiss();
|
|
408
|
-
this.snackbar.open(
|
|
533
|
+
this.snackbar.open(this.translate('csv.errorGenerateFailed'), undefined, {
|
|
409
534
|
duration: 5000,
|
|
410
535
|
});
|
|
411
536
|
return;
|
|
@@ -420,14 +545,17 @@ class CsvExportService {
|
|
|
420
545
|
URL.revokeObjectURL(objectUrl);
|
|
421
546
|
// Dissmiss processing message
|
|
422
547
|
mes.dismiss();
|
|
423
|
-
//
|
|
548
|
+
// 結果メッセージを表示
|
|
424
549
|
if (errorMessage) {
|
|
425
|
-
this.snackbar.open(
|
|
550
|
+
this.snackbar.open(this.translate('csv.exportCompletedWithErrors', {
|
|
551
|
+
count: numOfExportedItems,
|
|
552
|
+
error: errorMessage,
|
|
553
|
+
}), undefined, {
|
|
426
554
|
duration: 5000,
|
|
427
555
|
});
|
|
428
556
|
}
|
|
429
557
|
else {
|
|
430
|
-
this.snackbar.open(
|
|
558
|
+
this.snackbar.open(this.translate('csv.exportCompleted', { count: numOfExportedItems }), undefined, {
|
|
431
559
|
duration: 3000,
|
|
432
560
|
});
|
|
433
561
|
}
|
|
@@ -499,7 +627,11 @@ class NgxThinAdminList {
|
|
|
499
627
|
* Services
|
|
500
628
|
*/
|
|
501
629
|
cdr = inject(ChangeDetectorRef);
|
|
630
|
+
translate = inject(NGX_THIN_ADMIN_TRANSLATE);
|
|
502
631
|
csvExportService = inject(CsvExportService);
|
|
632
|
+
t(key, params) {
|
|
633
|
+
return this.translate(key, params);
|
|
634
|
+
}
|
|
503
635
|
ngOnChanges(changes) {
|
|
504
636
|
// Columns
|
|
505
637
|
if (changes.listColumns?.currentValue) {
|
|
@@ -552,7 +684,9 @@ class NgxThinAdminList {
|
|
|
552
684
|
return;
|
|
553
685
|
}
|
|
554
686
|
// Determine file name prefix
|
|
555
|
-
let fileNamePrefix = this.listConfig?.title
|
|
687
|
+
let fileNamePrefix = this.listConfig?.title
|
|
688
|
+
? this.listConfig.title
|
|
689
|
+
: this.t('list.exportedFileName');
|
|
556
690
|
if (this.selectedCategory && this.selectedCategory[0]?.id) {
|
|
557
691
|
// If a category is selected, include the category label in the file name prefix
|
|
558
692
|
fileNamePrefix += `_${this.selectedCategory[0]?.label}`;
|
|
@@ -579,7 +713,7 @@ class NgxThinAdminList {
|
|
|
579
713
|
this.fetchList();
|
|
580
714
|
}
|
|
581
715
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminList, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
582
|
-
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", 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=\"Reset filters\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n List\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=\"Clear filters\"\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label }}\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 ? 'Search in ' + selectedCategory?.[0]?.label + '...'\n : 'Search...'\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 aria-label=\"Clear search keyword\"\n matTooltip=\"Clear search keyword\"\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=\"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 mat-icon-button [matMenuTriggerFor]=\"csvExportMenu\" matTooltip=\"Export as CSV\">\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>Export {{ totalCount }} items</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 .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"] }] });
|
|
716
|
+
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", 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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label }}\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 .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"] }] });
|
|
583
717
|
}
|
|
584
718
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminList, decorators: [{
|
|
585
719
|
type: Component,
|
|
@@ -599,7 +733,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
599
733
|
MatMenuItem,
|
|
600
734
|
MatMenuTrigger,
|
|
601
735
|
RouterLink,
|
|
602
|
-
], 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=\"
|
|
736
|
+
], 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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label }}\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 .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"] }]
|
|
603
737
|
}], propDecorators: { listConfig: [{
|
|
604
738
|
type: Input
|
|
605
739
|
}], categorySelectorConfig: [{
|
|
@@ -844,6 +978,10 @@ class NgxThinAdminEditor {
|
|
|
844
978
|
*/
|
|
845
979
|
snackbar = inject(MatSnackBar);
|
|
846
980
|
cdr = inject(ChangeDetectorRef);
|
|
981
|
+
translate = inject(NGX_THIN_ADMIN_TRANSLATE);
|
|
982
|
+
t(key, params) {
|
|
983
|
+
return this.translate(key, params);
|
|
984
|
+
}
|
|
847
985
|
ngOnChanges(changes) {
|
|
848
986
|
// Fetcher
|
|
849
987
|
if (changes.editorConfig &&
|
|
@@ -925,7 +1063,7 @@ class NgxThinAdminEditor {
|
|
|
925
1063
|
}
|
|
926
1064
|
async save() {
|
|
927
1065
|
if (this.form.status === 'INVALID') {
|
|
928
|
-
this.snackbar.open(
|
|
1066
|
+
this.snackbar.open(`Error: ${this.t('editor.errorInvalidInput')}`, undefined, {
|
|
929
1067
|
duration: 3000,
|
|
930
1068
|
});
|
|
931
1069
|
// Mark field to show validation errors
|
|
@@ -936,7 +1074,7 @@ class NgxThinAdminEditor {
|
|
|
936
1074
|
return;
|
|
937
1075
|
}
|
|
938
1076
|
if (!this.editorConfig?.saver) {
|
|
939
|
-
this.snackbar.open(
|
|
1077
|
+
this.snackbar.open(`Error: ${this.t('editor.errorNoSaver')}`, undefined, {
|
|
940
1078
|
duration: 3000,
|
|
941
1079
|
});
|
|
942
1080
|
return;
|
|
@@ -947,7 +1085,7 @@ class NgxThinAdminEditor {
|
|
|
947
1085
|
// Call the saver function
|
|
948
1086
|
let result;
|
|
949
1087
|
try {
|
|
950
|
-
let res = await this.editorConfig
|
|
1088
|
+
let res = await this.editorConfig.saver(this.formData, this.itemId);
|
|
951
1089
|
if (res instanceof Response) {
|
|
952
1090
|
if (!res.ok) {
|
|
953
1091
|
const data = await res.json();
|
|
@@ -968,7 +1106,7 @@ class NgxThinAdminEditor {
|
|
|
968
1106
|
return;
|
|
969
1107
|
}
|
|
970
1108
|
// Show success message
|
|
971
|
-
this.snackbar.open('
|
|
1109
|
+
this.snackbar.open(this.t('editor.successSaved'), undefined, {
|
|
972
1110
|
duration: 3000,
|
|
973
1111
|
});
|
|
974
1112
|
// Update form data with the result from the saver (e.g., to get generated ID)
|
|
@@ -1008,7 +1146,7 @@ class NgxThinAdminEditor {
|
|
|
1008
1146
|
subscriptSizing: 'dynamic',
|
|
1009
1147
|
},
|
|
1010
1148
|
},
|
|
1011
|
-
], usesOnChanges: true, ngImport: i0, template: "<mat-card>\n <mat-card-header>\n <h3>\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n
|
|
1149
|
+
], usesOnChanges: true, ngImport: i0, template: "<mat-card>\n <mat-card-header>\n <h3>\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('common.edit') }}\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\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('common.create') }}\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\n <!---->\n }\n </h3>\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\"></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 @if (editorConfig?.saver) {\n <!-- Submit button -->\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem); float: right\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n <!---->\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}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.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: 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" }] });
|
|
1012
1150
|
}
|
|
1013
1151
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminEditor, decorators: [{
|
|
1014
1152
|
type: Component,
|
|
@@ -1046,7 +1184,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1046
1184
|
subscriptSizing: 'dynamic',
|
|
1047
1185
|
},
|
|
1048
1186
|
},
|
|
1049
|
-
], template: "<mat-card>\n <mat-card-header>\n <h3>\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n
|
|
1187
|
+
], template: "<mat-card>\n <mat-card-header>\n <h3>\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('common.edit') }}\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\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('common.create') }}\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\n <!---->\n }\n </h3>\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\"></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 @if (editorConfig?.saver) {\n <!-- Submit button -->\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem); float: right\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n <!---->\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}\n"] }]
|
|
1050
1188
|
}], propDecorators: { editorConfig: [{
|
|
1051
1189
|
type: Input
|
|
1052
1190
|
}], editorFields: [{
|
|
@@ -1063,5 +1201,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
1063
1201
|
* Generated bundle index. Do not edit.
|
|
1064
1202
|
*/
|
|
1065
1203
|
|
|
1066
|
-
export { NgxThinAdminEditor, NgxThinAdminList };
|
|
1204
|
+
export { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminEditor, NgxThinAdminList, provideNgxThinAdminI18n };
|
|
1067
1205
|
//# sourceMappingURL=ngx-thin-admin.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-thin-admin.mjs","sources":["../../../projects/ngx-thin-admin/src/lib/shared/category-editor-dialog/category-editor-dialog.ts","../../../projects/ngx-thin-admin/src/lib/shared/category-editor-dialog/category-editor-dialog.html","../../../projects/ngx-thin-admin/src/lib/shared/confirm-dialog/confirm-dialog.ts","../../../projects/ngx-thin-admin/src/lib/shared/confirm-dialog/confirm-dialog.html","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/list-category-selector/list-category-selector.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/list-category-selector/list-category-selector.html","../../../projects/ngx-thin-admin/src/lib/shared/csv-export-service.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/ngx-thin-admin-list.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/ngx-thin-admin-list.html","../../../projects/ngx-thin-admin/src/lib/shared/formly/mat-prefix-addon-wrapper/mat-prefix-addon-wrapper.ts","../../../projects/ngx-thin-admin/src/lib/shared/error-handler.ts","../../../projects/ngx-thin-admin/src/lib/shared/formly/file-input/file-type.component.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-editor/ngx-thin-admin-editor.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-editor/ngx-thin-admin-editor.html","../../../projects/ngx-thin-admin/src/public-api.ts","../../../projects/ngx-thin-admin/src/ngx-thin-admin.ts"],"sourcesContent":["import { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport {\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n MAT_DIALOG_DATA,\n MatDialogRef,\n} from '@angular/material/dialog';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { NgxThinAdminCategory, NgxThinAdminCategorySelectorConfig } from '../../interfaces';\n\nexport interface CategoryEditorDialogData {\n config: NgxThinAdminCategorySelectorConfig;\n editCategory?: NgxThinAdminCategory;\n positiveButtonText?: string;\n cancelButtonText?: string;\n}\n\n@Component({\n selector: 'lib-category-editor-dialog',\n imports: [\n MatFormFieldModule,\n MatInputModule,\n FormsModule,\n MatButtonModule,\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n ],\n templateUrl: './category-editor-dialog.html',\n styleUrl: './category-editor-dialog.scss',\n})\nexport class CategoryEditorDialog {\n readonly dialogRef = inject(MatDialogRef<CategoryEditorDialog>);\n readonly data = inject<CategoryEditorDialogData>(MAT_DIALOG_DATA);\n\n categoryLabel?: string;\n\n save() {\n if (!this.categoryLabel) {\n return;\n }\n\n this.dialogRef.close({\n label: this.categoryLabel,\n });\n }\n}\n","<h2 mat-dialog-title>\n @if (data.editCategory) {\n Edit {{ data.config.singularLabel ?? 'Category' }}: \"{{ data.editCategory.label }}\"\n } @else {\n Create {{ data.config.singularLabel ?? 'Category' }}\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 ?? 'Cancel' }}\n </button>\n <button type=\"submit\" matButton>{{ data.positiveButtonText ?? 'Save' }}</button>\n </mat-dialog-actions>\n</form>\n","import { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport {\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n MAT_DIALOG_DATA,\n MatDialogRef,\n} from '@angular/material/dialog';\n\nexport interface ConfirmDialogData {\n title?: string;\n message?: string;\n positiveButtonText?: string;\n cancelButtonText?: string;\n}\n\n@Component({\n selector: 'lib-confirm-dialog',\n imports: [\n FormsModule,\n MatButtonModule,\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n ],\n templateUrl: './confirm-dialog.html',\n styleUrl: './confirm-dialog.scss',\n})\nexport class ConfirmDialog {\n readonly dialogRef = inject(MatDialogRef<ConfirmDialog>);\n readonly data = inject<ConfirmDialogData>(MAT_DIALOG_DATA);\n}\n","<h2 mat-dialog-title>{{ data.title }}</h2>\n<mat-dialog-content>\n {{ data.message }}\n</mat-dialog-content>\n<mat-dialog-actions>\n <button class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText || 'Cancel' }}\n </button>\n <button matButton [mat-dialog-close]=\"true\" cdkFocusInitial>\n {{ data.positiveButtonText || 'OK' }}\n </button>\n</mat-dialog-actions>\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n inject,\n Input,\n Output,\n SimpleChanges,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatListOption, MatSelectionList } from '@angular/material/list';\nimport {\n NgxThinAdminCategory,\n NgxThinAdminCategoryListResponse,\n NgxThinAdminCategorySelectorConfig,\n} from '../../interfaces';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatMenu, MatMenuContent, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { MatDialog } from '@angular/material/dialog';\nimport {\n CategoryEditorDialog,\n CategoryEditorDialogData,\n} from '../../shared/category-editor-dialog/category-editor-dialog';\nimport { lastValueFrom, single } from 'rxjs';\nimport { ConfirmDialog, ConfirmDialogData } from '../../shared/confirm-dialog/confirm-dialog';\n\n@Component({\n selector: 'lib-list-category-selector',\n imports: [\n FormsModule,\n MatIcon,\n MatIconButton,\n MatSelectionList,\n MatMenu,\n MatMenuItem,\n MatMenuTrigger,\n MatListOption,\n MatMenuContent,\n ],\n templateUrl: './list-category-selector.html',\n styleUrl: './list-category-selector.scss',\n})\nexport class ListCategorySelector {\n /**\n * Config for the category selector\n */\n @Input() config?: NgxThinAdminCategorySelectorConfig;\n\n /**\n * Selected category. This will be updated when the user selects a category from the list.\n */\n @Input()\n selectedCategory?: (NgxThinAdminCategory | undefined)[];\n\n /**\n * Event emitted when the selected category changes.\n */\n @Output()\n selectedCategoryChange = new EventEmitter<(NgxThinAdminCategory | undefined)[]>();\n\n /**\n * Categories to be displayed in the category selector.\n */\n categories: NgxThinAdminCategory[] = [];\n\n /**\n * Services\n */\n private snackbar = inject(MatSnackBar);\n private dialog = inject(MatDialog);\n private cdr = inject(ChangeDetectorRef);\n\n ngOnChanges(changes: SimpleChanges<ListCategorySelector>) {\n if (\n changes.config &&\n changes.config.currentValue?.fetcher !== changes.config.previousValue?.fetcher\n ) {\n this.fetchCategories();\n }\n }\n\n async fetchCategories() {\n if (!this.config?.fetcher) {\n return;\n } else if (!(this.config.fetcher instanceof Function)) {\n throw new Error('categoryFetcher must be a function');\n }\n\n console.log('Fetching categories');\n try {\n const result = await Promise.resolve(this.config.fetcher());\n console.log(result);\n this.categories = result.categories;\n this.cdr.markForCheck();\n console.log('Fetched categories:', this.categories);\n } catch (e) {\n console.error('Error fetching categories:', e);\n }\n }\n\n async createCategory(categoryLabel: string) {\n if (!this.config?.creator) {\n return;\n }\n\n // Call the category creator function\n try {\n await this.config.creator(categoryLabel);\n } catch (e: any) {\n this.snackbar.open(`Error: ${e?.message ?? 'Could not create category'}`, undefined, {\n duration: 3000,\n });\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async updateCategory(category: NgxThinAdminCategory) {\n if (!this.config?.updater) {\n return;\n }\n\n // Call the category updater function\n try {\n await this.config.updater(category);\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? `Failed to update category \"${category.label}\"`}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async deleteCategory(category: NgxThinAdminCategory) {\n if (!this.config?.deleter) {\n return;\n }\n\n // Call the category deleter function\n try {\n await this.config.deleter(category);\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? `Failed to delete category: \"${category.label}\"`}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async openCategoryEditorDialog(editCategory: NgxThinAdminCategory | undefined) {\n // Open a dialog for category creation / editing\n const dialogRef = this.dialog.open(CategoryEditorDialog, {\n width: '400px',\n data: {\n config: this.config!,\n editCategory: editCategory,\n positiveButtonText: editCategory ? 'Save' : 'Create',\n cancelButtonText: 'Cancel',\n } satisfies CategoryEditorDialogData,\n });\n const result = await lastValueFrom(dialogRef.afterClosed());\n if (!result || !result.label) {\n return;\n }\n\n // Call the category creator / updater function\n try {\n if (editCategory) {\n await this.updateCategory({ ...editCategory, label: result.label });\n } else {\n await this.createCategory(result.label);\n }\n } catch (e: any) {\n this.snackbar.open(`Error: ${e?.message ?? 'Could not save category'}`, undefined, {\n duration: 3000,\n });\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async openCategoryDeletionDialog(category: NgxThinAdminCategory) {\n // Open a dialog for category deletion\n const dialogRef = this.dialog.open(ConfirmDialog, {\n width: '400px',\n data: {\n title: 'Confirm Deletion',\n message: `Are you sure you want to delete the ${this.config?.singularLabel ?? 'category'} \"${category.label}\"? This action cannot be undone.`,\n positiveButtonText: 'Delete',\n cancelButtonText: 'Cancel',\n } satisfies ConfirmDialogData,\n });\n const result = await lastValueFrom(dialogRef.afterClosed());\n if (!result) {\n return;\n }\n\n // Call the category deleter function\n try {\n await this.deleteCategory(category);\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? `Failed to delete category \"${category.label}\"`}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n}\n","<header>\n <!-- Category selector title -->\n <span class=\"category-selector-title\"> {{ config?.title ?? 'Categories' }} </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 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)\">Edit</button>\n }\n @if (config?.deleter) {\n <button mat-menu-item (click)=\"openCategoryDeletionDialog(category)\">Delete</button>\n }\n </ng-template>\n</mat-menu>\n<!---->\n","import { inject, Injectable } from '@angular/core';\nimport {\n ListFetcher,\n NgxThinAdminListColumn,\n NgxThinAdminListQuery,\n NgxThinAdminListResponse,\n} from '../interfaces';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { ColumnOption, stringify as csvStringify } from 'csv-stringify/browser/esm/sync';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class CsvExportService {\n private snackbar = inject(MatSnackBar);\n\n private encoders: {\n key: string;\n label: string;\n mimeCharset: string;\n encoder: ((input: string) => ArrayBuffer | null) | undefined;\n }[] = [\n {\n key: 'utf8',\n label: 'UTF-8',\n mimeCharset: 'UTF-8',\n encoder: undefined,\n },\n ];\n\n constructor() {\n this.loadOptionalEncoders();\n }\n\n private async loadOptionalEncoders() {\n // Optional charset support for Shift_JIS (commonly used in Japan)\n try {\n // @ts-ignore\n const Encoding = (await import('encoding-japanese')) as any;\n this.encoders.push({\n key: 'sjis',\n label: 'Shift_JIS',\n mimeCharset: 'Shift_JIS',\n encoder: (input: string) => {\n const sjisArrayBuffer = Encoding.convert(input, {\n from: 'UNICODE',\n to: 'SJIS',\n type: 'arraybuffer',\n });\n return new Uint8Array(sjisArrayBuffer).buffer;\n },\n });\n } catch (error) {\n console.error(\n 'Shift_JIS encoder is not available. If you need it, please install \"encoding-japanese\" package.',\n error,\n );\n // Do nothing\n }\n }\n\n getAvailableEncoders() {\n return this.encoders.map((encoder) => ({\n key: encoder.key,\n label: encoder.label,\n }));\n }\n\n async exportListAsCsv(\n encoderKey: string,\n fileNamePrefix: string,\n fetcher: ListFetcher,\n listQuery: Omit<NgxThinAdminListQuery, 'page' | 'perPage'>,\n columns: NgxThinAdminListColumn[],\n ) {\n const CSV_EXPORT_MAX_PAGE_INDEX = 1000;\n const CSV_EXPORT_PAGE_SIZE = 25;\n\n console.log('Starting CSV export', listQuery, encoderKey);\n\n // Get encoder\n const encoderInfo = this.encoders.find((e) => e.key === encoderKey);\n if (!encoderInfo) {\n console.error(`exportListAsCsv - Encoder not found for key: ${encoderKey}`);\n return;\n }\n const mimeCharset = encoderInfo.mimeCharset;\n const encoder = encoderInfo.encoder;\n\n // Initialize\n const items: any[] = [];\n let errorMessage: string | undefined = undefined;\n\n // Show processing message\n const mes = this.snackbar.open('Exporting CSV...');\n\n // Replace characters in the file name prefix that cannot be used in file names\n fileNamePrefix = fileNamePrefix.replace(/[/¥\\\\*?:\"<>|@\\s;^.]/g, '_');\n\n // Truncate the file name prefix if it is too long\n const FILE_NAME_PREFIX_MAX_LENGTH = 100;\n if (fileNamePrefix.length > FILE_NAME_PREFIX_MAX_LENGTH) {\n fileNamePrefix = fileNamePrefix.substring(0, FILE_NAME_PREFIX_MAX_LENGTH);\n }\n\n // Generate file name\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const date = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n const datetimeString = `${year}${month}${date}_${hours}${minutes}${seconds}`;\n const csvFileName = `${fileNamePrefix}_${datetimeString}.csv`;\n\n // Fetch items page by page\n let numOfExportedItems = 0;\n for (let pageIndex = 0; pageIndex < CSV_EXPORT_MAX_PAGE_INDEX; pageIndex++) {\n const query: NgxThinAdminListQuery = {\n ...listQuery,\n page: pageIndex,\n perPage: CSV_EXPORT_PAGE_SIZE,\n };\n\n let result: NgxThinAdminListResponse;\n try {\n result = await fetcher(query);\n } catch (error: any) {\n console.error(`exportListAsCsv - Error fetching data:`, error);\n errorMessage = error.message || 'Unknown error';\n break;\n }\n\n // Wait for few seconds\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n if (result.items.length === 0) {\n // No items, exit\n break;\n }\n\n // Add fetched items\n items.push(...result.items);\n numOfExportedItems += result.items.length;\n }\n\n // Determine CSV columns\n const csvColumns: ColumnOption[] = columns\n .filter((column) => {\n if (column.type === 'button') {\n // Exclude columns that are buttons\n return false;\n }\n return true;\n })\n .map((column) => {\n // Get the column key (e.g., \"name\")\n const columnKey: string = column.field;\n // Get the column header string (e.g., \"User Name\")\n let columnHeader: string;\n if (typeof column.header === 'string') {\n columnHeader = column.header;\n } else {\n columnHeader = columnKey;\n }\n // Return column information for csv-stringify\n return {\n key: column.field,\n header: columnHeader,\n };\n })\n .filter((column) => column !== null);\n\n // Convert to CSV\n const csv = csvStringify(items, {\n header: true,\n columns: csvColumns,\n });\n\n // Generate Blob\n let blob: Blob | undefined = undefined;\n if (encoder) {\n const encodedData = encoder(csv);\n if (encodedData) {\n blob = new Blob([encodedData], { type: `text/csv; charset=${mimeCharset}` });\n } else {\n console.error(`exportListAsCsv - Encoding failed for encoder: ${encoderKey}`);\n }\n } else {\n blob = new Blob([csv], { type: `text/csv; charset=${mimeCharset}` });\n }\n\n if (!blob) {\n console.error(`exportListAsCsv - Blob is not created`);\n mes.dismiss();\n this.snackbar.open(`Failed to generate CSV file.`, undefined, {\n duration: 5000,\n });\n return;\n }\n\n // Download as CSV\n const objectUrl = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.download = csvFileName;\n a.href = objectUrl;\n a.click();\n\n // Revoke object URL after download\n URL.revokeObjectURL(objectUrl);\n\n // Dissmiss processing message\n mes.dismiss();\n\n // Show result message\n if (errorMessage) {\n this.snackbar.open(\n `CSV exported up to ${numOfExportedItems} items. but errors occurred: ${errorMessage}`,\n undefined,\n {\n duration: 5000,\n },\n );\n } else {\n this.snackbar.open(`CSV export completed. Exported ${numOfExportedItems} items.`, undefined, {\n duration: 3000,\n });\n }\n }\n}\n","import {\n Component,\n inject,\n Input,\n OnChanges,\n OnInit,\n SimpleChanges,\n TemplateRef,\n ViewChild,\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\nimport { MatButton, MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInput, MatPrefix, MatSuffix } from '@angular/material/input';\nimport { MatFormField } from '@angular/material/select';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport { MtxGridColumn, MtxGridModule } from '@ng-matero/extensions/grid';\nimport {\n NgxThinAdminCategory,\n NgxThinAdminCategorySelectorConfig,\n NgxThinAdminListColumn,\n NgxThinAdminListConfig,\n NgxThinAdminListQuery,\n NgxThinAdminListResponse,\n} from '../interfaces';\nimport { FormsModule } from '@angular/forms';\nimport { PageEvent } from '@angular/material/paginator';\nimport { ChangeDetectorRef } from '@angular/core';\nimport { ListCategorySelector } from './list-category-selector/list-category-selector';\nimport { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';\nimport { MatListOption } from '@angular/material/list';\nimport { CsvExportService } from '../shared/csv-export-service';\nimport { RouterLink } from '@angular/router';\n\n@Component({\n selector: 'ngx-thin-admin-list',\n imports: [\n FormsModule,\n MtxGridModule,\n MatButton,\n MatIcon,\n MatIconButton,\n MatTooltip,\n MatFormField,\n MatInput,\n MatPrefix,\n MatSuffix,\n ListCategorySelector,\n MatMenu,\n MatMenuItem,\n MatMenuTrigger,\n RouterLink,\n ],\n templateUrl: './ngx-thin-admin-list.html',\n styleUrl: './ngx-thin-admin-list.scss',\n})\nexport class NgxThinAdminList implements OnChanges, OnInit {\n /**\n * Config for list\n */\n @Input()\n listConfig?: NgxThinAdminListConfig;\n\n /**\n * Config for category selector. If provided, a category selector will be displayed in the UI.\n */\n @Input()\n categorySelectorConfig?: NgxThinAdminCategorySelectorConfig;\n\n /**\n * Column schema (extended type of MtxGridColumn)\n * @see https://ng-matero.github.io/extensions/components/grid/api\n */\n @Input()\n listColumns?: MtxGridColumn[];\n\n /**\n * Query (Optional)\n */\n @Input() query: NgxThinAdminListQuery = {\n keyword: '',\n page: 0,\n perPage: 10,\n categoryId: undefined,\n };\n\n /**\n * Fetcher function to retrieve list data.\n * This should be provided as part of listConfig.\n */\n private listFetcher?: (\n query: NgxThinAdminListQuery,\n ) => Promise<NgxThinAdminListResponse> | NgxThinAdminListResponse;\n\n /**\n * Internal state for grid\n */\n isLoading = false;\n gridColumns: MtxGridColumn[] = [];\n gridData: any[] = [];\n totalCount: number = 0;\n\n /**\n * Internal state for category list\n */\n categories: NgxThinAdminCategory[] = [];\n selectedCategory?: NgxThinAdminCategory[] = [];\n\n /**\n * Internal subject to trigger keyword change with debounce\n */\n private keywordChanged$ = new Subject<void>();\n ngOnInit(): void {\n this.keywordChanged$.pipe(debounceTime(500)).subscribe(() => {\n this.fetchList();\n });\n }\n\n /**\n * Template for cells\n */\n @ViewChild('cellTplWithLink', { static: true }) cellTplWithLink!: TemplateRef<any>;\n\n /**\n * Services\n */\n private cdr = inject(ChangeDetectorRef);\n csvExportService = inject(CsvExportService);\n\n ngOnChanges(changes: SimpleChanges<NgxThinAdminList>) {\n // Columns\n if (changes.listColumns?.currentValue) {\n this.gridColumns = changes.listColumns.currentValue.map((col: NgxThinAdminListColumn) => {\n if (col.link || col.routerLink) {\n return { ...col, cellTemplate: this.cellTplWithLink };\n }\n return col;\n });\n }\n\n // List - trigger strictly when listFetcher is newly provided or explicitly changed\n if (changes.listConfig?.currentValue?.fetcher !== changes.listConfig?.previousValue?.fetcher) {\n this.listFetcher = changes.listConfig?.currentValue?.fetcher;\n this.fetchList();\n }\n }\n\n async fetchList() {\n if (!this.listFetcher) {\n return;\n } else if (!(this.listFetcher instanceof Function)) {\n throw new Error('listFetcher must be a function');\n }\n\n console.log('Fetching data with query:', this.query);\n this.isLoading = true;\n\n try {\n const result = await Promise.resolve(this.listFetcher(this.query));\n this.gridData = result.items;\n this.totalCount = result.totalCount;\n } catch (e) {\n console.error('Error fetching list data:', e);\n } finally {\n this.isLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n clearFilters() {\n this.query.keyword = '';\n this.query.categoryId = undefined;\n this.selectedCategory = [];\n this.fetchList();\n }\n\n onKeywordInput() {\n this.keywordChanged$.next();\n }\n\n async exportAsCsv(encoderKey: 'utf8' | string) {\n if (!this.listFetcher) {\n return;\n }\n\n // Determine file name prefix\n let fileNamePrefix: string = this.listConfig?.title ? this.listConfig.title : 'exported';\n if (this.selectedCategory && this.selectedCategory[0]?.id) {\n // If a category is selected, include the category label in the file name prefix\n fileNamePrefix += `_${this.selectedCategory[0]?.label}`;\n }\n if (this.query.keyword && this.query.keyword.length > 0) {\n // If a search keyword is entered, include it in the file name prefix\n fileNamePrefix += `_${this.query.keyword}`;\n }\n\n // Execute export\n await this.csvExportService.exportListAsCsv(\n encoderKey,\n fileNamePrefix,\n this.listFetcher,\n {\n categoryId: this.selectedCategory ? this.selectedCategory[0]?.id : undefined,\n keyword: this.query.keyword,\n },\n this.listColumns!,\n );\n }\n\n onPageChange(event: PageEvent) {\n this.query.page = event.pageIndex;\n this.query.perPage = event.pageSize;\n this.fetchList();\n }\n\n onSelectedCategoryChange($event: (NgxThinAdminCategory | undefined)[]) {\n console.log('Selected category changed:', $event);\n const categoryId = $event && $event.length >= 1 && $event[0] ? $event[0].id : undefined;\n this.query.categoryId = categoryId;\n this.fetchList();\n }\n}\n","<!-- 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=\"Reset filters\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n List\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=\"Clear filters\"\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label }}\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 ? 'Search in ' + selectedCategory?.[0]?.label + '...'\n : 'Search...'\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 aria-label=\"Clear search keyword\"\n matTooltip=\"Clear search keyword\"\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=\"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 mat-icon-button [matMenuTriggerFor]=\"csvExportMenu\" matTooltip=\"Export as CSV\">\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>Export {{ totalCount }} items</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","import { Component, TemplateRef, ViewChild, AfterViewInit } from '@angular/core';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatPrefix, MatSuffix } from '@angular/material/input';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport { FieldWrapper, FormlyFieldConfig } from '@ngx-formly/core';\n\n@Component({\n selector: 'lib-formly-mat-prefix-addon-wrapper',\n imports: [MatIconButton, MatIcon, MatSuffix, MatTooltip],\n template: `\n <ng-container #fieldComponent></ng-container>\n\n <ng-template #matSuffix>\n @if (props['addonRight']) {\n @if (props['addonRight']['icon']) {\n <button\n mat-icon-button\n matSuffix\n style=\"margin-right: 1rem;\"\n [matTooltip]=\"props['addonRight']['tooltip'] ?? ''\"\n (click)=\"props['addonRight'].onClick ? addonRightClick($event) : null\"\n type=\"button\"\n >\n <mat-icon>{{ props['addonRight']['icon'] }}</mat-icon>\n </button>\n }\n @if (props['addonRight']['text']) {\n <span>{{ props['addonRight']['text'] }}</span>\n }\n }\n </ng-template>\n `,\n})\nexport class FormlyMatPrefixAddonWrapper extends FieldWrapper implements AfterViewInit {\n @ViewChild('matPrefix', { static: true }) matPrefix!: TemplateRef<any>;\n @ViewChild('matSuffix', { static: true }) matSuffix!: TemplateRef<any>;\n\n ngAfterViewInit() {\n if (this.matPrefix) {\n this.props['prefix'] = this.matPrefix;\n }\n\n if (this.matSuffix) {\n this.props['suffix'] = this.matSuffix;\n }\n }\n\n addonRightClick($event: any) {\n if (this.props['addonRight'].onClick) {\n this.props['addonRight'].onClick(this.to, this, $event);\n }\n }\n\n addonLeftClick($event: any) {\n if (this.props['addonLeft'].onClick) {\n this.props['addonLeft'].onClick(this.to, this, $event);\n }\n }\n}\n\nexport function formlyAddonsExtension(field: FormlyFieldConfig) {\n if (!field.props || (field.wrappers && field.wrappers.indexOf('addons') !== -1)) {\n return;\n }\n\n if (field.props['addonLeft'] || field.props['addonRight']) {\n field.wrappers = [...(field.wrappers || []), 'addons'];\n }\n}\n","export function getErrorMessage(error: any): string {\n if (typeof error === 'string') {\n return error;\n } else if (error instanceof Error) {\n return error.message;\n } else if (error?.error?.message) {\n if (Array.isArray(error.error.message)) {\n return error.error.message[0];\n } else {\n return error.error.message;\n }\n } else {\n return 'An unknown error occurred';\n }\n}\n","import { Component } from '@angular/core';\nimport { FormlyAttributes, FieldType, FieldTypeConfig } from '@ngx-formly/core';\nimport { ReactiveFormsModule, FormControl } from '@angular/forms';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInputModule } from '@angular/material/input';\nimport {\n MatFormField,\n MatLabel,\n MatHint,\n MatSuffix,\n} from '@angular/material/form-field';\n\n@Component({\n selector: 'formly-field-file',\n template: `\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" subscriptSizing=\"dynamic\" style=\"width:100%\">\n <!-- Field label -->\n @if (props.label) {\n <mat-label>{{ props.label }}{{ props.required ? ' *' : '' }}</mat-label>\n }\n \n <!-- Choosed file name -->\n <input matInput type=\"text\" readonly [value]=\"fileName\" [formlyAttributes]=\"field\" (click)=\"fileInput.click()\" />\n\n <!-- File choose button -->\n <button mat-icon-button matSuffix style=\"margin-right: 1rem;\" type=\"button\" (click)=\"fileInput.click()\">\n <mat-icon>attach_file</mat-icon>\n </button>\n\n <!-- Actual file input (hidden) -->\n <input\n type=\"file\"\n #fileInput\n style=\"display: none\"\n [attr.accept]=\"props['accept'] ?? null\"\n (change)=\"onFileChange($event)\"\n />\n\n <!-- Field description -->\n @if (props.description) {\n <mat-hint>{{ props.description }}</mat-hint>\n }\n </mat-form-field>\n `,\n standalone: true,\n imports: [\n ReactiveFormsModule,\n FormlyAttributes,\n MatInputModule,\n MatIcon,\n MatIconButton,\n MatFormField,\n MatLabel,\n MatHint,\n MatSuffix,\n ],\n})\nexport class FormlyFieldFile extends FieldType<FieldTypeConfig> {\n /** 表示用のファイル名 */\n fileName = '';\n\n /** ファイルが選択されたときの処理 */\n onFileChange(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0] ?? null;\n\n // formControl に File オブジェクトをセット\n this.formControl.setValue(file);\n this.formControl.markAsDirty();\n\n // 表示用のファイル名を更新\n this.fileName = file?.name ?? '';\n }\n}\n\n","import {\n ChangeDetectorRef,\n Component,\n inject,\n Input,\n OnChanges,\n SimpleChanges,\n} from '@angular/core';\nimport { FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { MatButton } from '@angular/material/button';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { MatCard, MatCardHeader, MatCardContent } from '@angular/material/card';\nimport { FormlyFieldConfig, FormlyForm, provideFormlyCore } from '@ngx-formly/core';\nimport { withFormlyMaterial } from '@ngx-formly/material';\nimport { NgxThinAdminEditorConfig, NgxThinAdminEditorField } from '../interfaces';\nimport { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';\nimport {\n formlyAddonsExtension,\n FormlyMatPrefixAddonWrapper,\n} from '../shared/formly/mat-prefix-addon-wrapper/mat-prefix-addon-wrapper';\nimport { MatProgressBar } from '@angular/material/progress-bar';\nimport { getErrorMessage } from '../shared/error-handler';\nimport { FormlyFieldFile } from '../shared/formly/file-input/file-type.component';\n\n@Component({\n selector: 'ngx-thin-admin-editor',\n imports: [\n ReactiveFormsModule,\n FormlyForm,\n MatButton,\n MatProgressBar,\n MatCard,\n MatCardHeader,\n MatCardContent,\n ],\n providers: [\n provideFormlyCore(withFormlyMaterial()),\n provideFormlyCore({\n wrappers: [\n {\n name: 'addons',\n component: FormlyMatPrefixAddonWrapper,\n },\n ],\n extensions: [{ name: 'addons', extension: { onPopulate: formlyAddonsExtension } }],\n types: [\n {\n name: 'file',\n component: FormlyFieldFile,\n },\n ],\n }),\n {\n // Apply default appearance and other settings to all Material form fields in this component\n provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,\n useValue: {\n appearance: 'outline',\n floatLabel: 'always',\n subscriptSizing: 'dynamic',\n },\n },\n ],\n templateUrl: './ngx-thin-admin-editor.html',\n styleUrl: './ngx-thin-admin-editor.scss',\n})\nexport class NgxThinAdminEditor implements OnChanges {\n /**\n * Config for editor\n */\n @Input()\n editorConfig?: NgxThinAdminEditorConfig;\n\n /**\n * Fields for formly form\n */\n @Input()\n editorFields?: NgxThinAdminEditorField[];\n\n /**\n * Id of the item being edited.\n */\n @Input()\n itemId?: string;\n\n /**\n * Internal state for form\n */\n isSaving = false;\n isLoading = false;\n form = new FormGroup({});\n data: any = {};\n formData: any = {};\n\n /**\n * Services\n */\n private snackbar = inject(MatSnackBar);\n private cdr = inject(ChangeDetectorRef);\n\n ngOnChanges(changes: SimpleChanges<NgxThinAdminEditor>) {\n // Fetcher\n if (\n changes.editorConfig &&\n changes.editorConfig.currentValue?.fetcher !== changes.editorConfig.previousValue?.fetcher\n ) {\n this.fetchItem();\n } else if (changes.itemId && changes.itemId.currentValue !== changes.itemId.previousValue) {\n this.fetchItem();\n }\n\n // Fields\n if (changes.editorFields?.currentValue) {\n this.editorFields = changes.editorFields.currentValue.map((col: NgxThinAdminEditorField) => {\n return this.overwriteFieldProps(col);\n });\n }\n }\n\n overwriteFieldProps(field: NgxThinAdminEditorField) {\n if (!field.props) {\n field.props = {};\n }\n\n // requiredOnCreate\n if (field.props.requiredOnCreate) {\n if (this.itemId === undefined) {\n field.props.required = true;\n } else {\n field.props.required = false;\n }\n }\n\n // disabledOnUpdate\n if (field.props.disabledOnUpdate) {\n if (this.itemId !== undefined) {\n //formControl.disable();\n field.props.disabled = true;\n } else {\n //formControl.enable();\n field.props.disabled = false;\n }\n }\n\n return field;\n }\n\n async fetchItem() {\n if (!this.editorConfig?.fetcher) {\n return;\n } else if (!this.itemId) {\n this.data = {};\n return;\n }\n\n // Set loading state\n this.isLoading = true;\n this.cdr.markForCheck();\n\n // Call the fetcher function to get the item data\n try {\n let res = await this.editorConfig.fetcher(this.itemId);\n\n if (res instanceof Response) {\n if (!res.ok) {\n const data = await res.json();\n throw new Error(\n data.error ?? data.message ?? `Failed to fetch data: ${res.status} ${res.statusText}`,\n );\n }\n res = await res.json();\n }\n\n this.data = { ...res };\n this.formData = { ...res };\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(`Error: ${errorMessage}`, undefined, {\n duration: 3000,\n });\n\n // Reset loading state\n this.isLoading = false;\n this.cdr.markForCheck();\n return;\n }\n\n this.isLoading = false;\n this.cdr.markForCheck();\n }\n\n async save() {\n if (this.form.status === 'INVALID') {\n this.snackbar.open('Error: Invalid input', undefined, {\n duration: 3000,\n });\n\n // Mark field to show validation errors\n Object.keys(this.form.controls).forEach((key) => {\n const control = this.form.get(key);\n control?.markAsTouched();\n });\n\n return;\n }\n\n if (!this.editorConfig?.saver) {\n this.snackbar.open('Error: No saver function provided', undefined, {\n duration: 3000,\n });\n return;\n }\n\n // Disable the form and save button to prevent multiple submissions\n this.form.disable();\n this.isSaving = true;\n\n // Call the saver function\n let result: any;\n try {\n let res: any = await this.editorConfig?.saver?.(this.formData, this.itemId);\n\n if (res instanceof Response) {\n if (!res.ok) {\n const data = await res.json();\n throw new Error(\n data.error ?? data.message ?? `Failed to save data: ${res.status} ${res.statusText}`,\n );\n }\n res = await res.json();\n }\n\n result = res;\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(`Error: ${errorMessage}`, undefined, {\n duration: 3000,\n });\n\n // Re-enable the form and save button\n this.form.enable();\n this.isSaving = false;\n\n return;\n }\n\n // Show success message\n this.snackbar.open('Data saved successfully', undefined, {\n duration: 3000,\n });\n\n // Update form data with the result from the saver (e.g., to get generated ID)\n this.data = { ...result };\n this.formData = { ...result };\n\n // Re-enable the form and save button\n this.form.enable();\n for (const field of this.editorFields ?? []) {\n this.overwriteFieldProps(field);\n }\n this.isSaving = false;\n }\n}\n","<mat-card>\n <mat-card-header>\n <h3>\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n 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 Edit <span style=\"color: #aaaaaa\">-</span>\n ID:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n Edit\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\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 Create\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\n <!---->\n }\n </h3>\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading) {\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n } @else {\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <formly-form\n [form]=\"form\"\n [fields]=\"$any(editorFields) ?? []\"\n [model]=\"formData\"\n ></formly-form>\n\n @if (editorConfig?.saver) {\n <!-- Submit button -->\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem); float: right\"\n >\n @if (itemId !== undefined) {\n Save Changes\n } @else {\n Create\n }\n </button>\n <!---->\n }\n </form>\n }\n </mat-card-content>\n</mat-card>\n","/*\n * Public API Surface of ngx-thin-admin\n */\n\nexport * from './lib/ngx-thin-admin-list/ngx-thin-admin-list';\nexport * from './lib/ngx-thin-admin-editor/ngx-thin-admin-editor';\nexport * from './lib/interfaces';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1","i2","i3","csvStringify","MatFormField","MatSuffix"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngx-thin-admin.mjs","sources":["../../../projects/ngx-thin-admin/src/lib/i18n.ts","../../../projects/ngx-thin-admin/src/lib/shared/category-editor-dialog/category-editor-dialog.ts","../../../projects/ngx-thin-admin/src/lib/shared/category-editor-dialog/category-editor-dialog.html","../../../projects/ngx-thin-admin/src/lib/shared/confirm-dialog/confirm-dialog.ts","../../../projects/ngx-thin-admin/src/lib/shared/confirm-dialog/confirm-dialog.html","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/list-category-selector/list-category-selector.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/list-category-selector/list-category-selector.html","../../../projects/ngx-thin-admin/src/lib/shared/csv-export-service.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/ngx-thin-admin-list.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-list/ngx-thin-admin-list.html","../../../projects/ngx-thin-admin/src/lib/shared/formly/mat-prefix-addon-wrapper/mat-prefix-addon-wrapper.ts","../../../projects/ngx-thin-admin/src/lib/shared/error-handler.ts","../../../projects/ngx-thin-admin/src/lib/shared/formly/file-input/file-type.component.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-editor/ngx-thin-admin-editor.ts","../../../projects/ngx-thin-admin/src/lib/ngx-thin-admin-editor/ngx-thin-admin-editor.html","../../../projects/ngx-thin-admin/src/public-api.ts","../../../projects/ngx-thin-admin/src/ngx-thin-admin.ts"],"sourcesContent":["import { InjectionToken, Provider } from '@angular/core';\n\nexport type NgxThinAdminLocale = 'en' | 'ja';\n\nexport type NgxThinAdminI18nKey =\n | 'common.cancel'\n | 'common.ok'\n | 'common.save'\n | 'common.create'\n | 'common.edit'\n | 'common.delete'\n | 'list.defaultTitle'\n | 'list.clearFilters'\n | 'list.searchDefaultPlaceholder'\n | 'list.searchInCategoryPlaceholder'\n | 'list.clearSearchKeyword'\n | 'list.refresh'\n | 'list.exportAsCsv'\n | 'list.exportedFileName'\n | 'list.exportItems'\n | 'editor.idLabel'\n | 'editor.saveChanges'\n | 'editor.errorInvalidInput'\n | 'editor.errorNoSaver'\n | 'editor.successSaved'\n | 'category.defaultSingular'\n | 'category.defaultPlural'\n | 'category.all'\n | 'category.editorDialogTitleForCreate'\n | 'category.editorDialogTitleForEdit'\n | 'category.deletionDialogTitle'\n | 'category.deletionDialogMessage'\n | 'category.errorCouldNotCreate'\n | 'category.errorFailedUpdate'\n | 'category.errorFailedDelete'\n | 'category.errorCouldNotSave'\n | 'csv.exporting'\n | 'csv.exportCompleted'\n | 'csv.exportCompletedWithErrors'\n | 'csv.errorGenerateFailed';\n\nexport type NgxThinAdminI18nParams = Record<string, string | number | undefined>;\nexport type NgxThinAdminTranslate = (\n key: NgxThinAdminI18nKey,\n params?: NgxThinAdminI18nParams,\n) => string;\n\nexport interface NgxThinAdminI18nConfig {\n locale?: NgxThinAdminLocale;\n messages?: Partial<Record<NgxThinAdminI18nKey, string>>;\n translate?: NgxThinAdminTranslate;\n}\n\nconst messagesEn: Record<NgxThinAdminI18nKey, string> = {\n 'common.cancel': 'Cancel',\n 'common.ok': 'OK',\n 'common.save': 'Save',\n 'common.create': 'Create',\n 'common.edit': 'Edit',\n 'common.delete': 'Delete',\n 'list.defaultTitle': 'List',\n 'list.clearFilters': 'Clear filters',\n 'list.searchDefaultPlaceholder': 'Search...',\n 'list.searchInCategoryPlaceholder': 'Search in {category}...',\n 'list.clearSearchKeyword': 'Clear search keyword',\n 'list.refresh': 'Refresh',\n 'list.exportAsCsv': 'Export as CSV',\n 'list.exportedFileName': 'exported',\n 'list.exportItems': 'Export {count} items',\n 'editor.idLabel': 'ID',\n 'editor.saveChanges': 'Save Changes',\n 'editor.errorInvalidInput': 'Invalid input',\n 'editor.errorNoSaver': 'No saver function provided',\n 'editor.successSaved': 'Data saved successfully',\n 'category.defaultSingular': 'Category',\n 'category.defaultPlural': 'Categories',\n 'category.all': 'All',\n 'category.editorDialogTitleForCreate': 'Create {categoryType}',\n 'category.editorDialogTitleForEdit': 'Edit {categoryType}',\n 'category.deletionDialogTitle': 'Delete {categoryType}',\n 'category.deletionDialogMessage':\n 'Are you sure you want to delete the {categoryType} \"{label}\"? This action cannot be undone.',\n 'category.errorCouldNotCreate': 'Could not create category',\n 'category.errorFailedUpdate': 'Failed to update category \"{label}\"',\n 'category.errorFailedDelete': 'Failed to delete category \"{label}\"',\n 'category.errorCouldNotSave': 'Could not save category',\n 'csv.exporting': 'Exporting CSV...',\n 'csv.exportCompleted': 'CSV export completed. Exported {count} items.',\n 'csv.exportCompletedWithErrors': 'CSV exported up to {count} items, but errors occurred: {error}',\n 'csv.errorGenerateFailed': 'Failed to generate CSV file.',\n};\n\nconst messagesJa: Record<NgxThinAdminI18nKey, string> = {\n 'common.cancel': 'キャンセル',\n 'common.ok': 'OK',\n 'common.save': '保存',\n 'common.create': '作成',\n 'common.edit': '編集',\n 'common.delete': '削除',\n 'list.defaultTitle': '一覧',\n 'list.clearFilters': 'フィルターをクリア',\n 'list.searchDefaultPlaceholder': '検索...',\n 'list.searchInCategoryPlaceholder': '{category} 内を検索...',\n 'list.clearSearchKeyword': '検索キーワードをクリア',\n 'list.refresh': '再読み込み',\n 'list.exportAsCsv': 'CSV でエクスポート',\n 'list.exportedFileName': 'exported',\n 'list.exportItems': '{count} 件をエクスポート',\n 'editor.idLabel': 'ID',\n 'editor.saveChanges': '変更を保存',\n 'editor.errorInvalidInput': '入力内容が不正です',\n 'editor.errorNoSaver': '保存処理が設定されていません',\n 'editor.successSaved': '保存しました',\n 'category.defaultSingular': 'カテゴリ',\n 'category.defaultPlural': 'カテゴリ',\n 'category.all': 'すべて',\n 'category.editorDialogTitleForCreate': '{categoryType} の作成',\n 'category.editorDialogTitleForEdit': '{categoryType} の編集',\n 'category.deletionDialogTitle': '{categoryType} の削除',\n 'category.deletionDialogMessage':\n '{categoryType} \"{label}\" を削除しますか?この操作は元に戻せません。',\n 'category.errorCouldNotCreate': 'カテゴリを作成できませんでした',\n 'category.errorFailedUpdate': 'カテゴリ \"{label}\" の更新に失敗しました',\n 'category.errorFailedDelete': 'カテゴリ \"{label}\" の削除に失敗しました',\n 'category.errorCouldNotSave': 'カテゴリを保存できませんでした',\n 'csv.exporting': 'CSV をエクスポート中...',\n 'csv.exportCompleted': 'CSV エクスポートが完了しました。{count} 件をエクスポートしました。',\n 'csv.exportCompletedWithErrors':\n '{count} 件までエクスポートしましたが、エラーが発生しました: {error}',\n 'csv.errorGenerateFailed': 'CSV ファイルの生成に失敗しました。',\n};\n\nfunction interpolate(message: string, params?: NgxThinAdminI18nParams): string {\n if (!params) {\n return message;\n }\n\n return message.replace(/\\{(\\w+)\\}/g, (_, key: string) => {\n const value = params[key];\n return value === undefined ? '' : String(value);\n });\n}\n\nfunction createTranslatorFromMessages(\n baseMessages: Record<NgxThinAdminI18nKey, string>,\n overrides?: Partial<Record<NgxThinAdminI18nKey, string>>,\n): NgxThinAdminTranslate {\n const merged = { ...baseMessages, ...overrides };\n return (key: NgxThinAdminI18nKey, params?: NgxThinAdminI18nParams): string => {\n return interpolate(merged[key] ?? messagesEn[key], params);\n };\n}\n\nexport const NGX_THIN_ADMIN_TRANSLATE = new InjectionToken<NgxThinAdminTranslate>(\n 'NGX_THIN_ADMIN_TRANSLATE',\n {\n providedIn: 'root',\n factory: () => createTranslatorFromMessages(messagesEn),\n },\n);\n\nexport function provideNgxThinAdminI18n(config?: NgxThinAdminI18nConfig): Provider {\n return {\n provide: NGX_THIN_ADMIN_TRANSLATE,\n useFactory: () => {\n if (config?.translate) {\n return config.translate;\n }\n\n const locale = config?.locale ?? 'en';\n const base = locale === 'ja' ? messagesJa : messagesEn;\n return createTranslatorFromMessages(base, config?.messages);\n },\n };\n}\n","import { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport {\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n MAT_DIALOG_DATA,\n MatDialogRef,\n} from '@angular/material/dialog';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatInputModule } from '@angular/material/input';\nimport { NgxThinAdminCategory, NgxThinAdminCategorySelectorConfig } from '../../interfaces';\nimport { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminI18nKey } from '../../i18n';\n\nexport interface CategoryEditorDialogData {\n config: NgxThinAdminCategorySelectorConfig;\n editCategory?: NgxThinAdminCategory;\n positiveButtonText?: string;\n cancelButtonText?: string;\n}\n\n@Component({\n selector: 'lib-category-editor-dialog',\n imports: [\n MatFormFieldModule,\n MatInputModule,\n FormsModule,\n MatButtonModule,\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n ],\n templateUrl: './category-editor-dialog.html',\n styleUrl: './category-editor-dialog.scss',\n})\nexport class CategoryEditorDialog {\n readonly dialogRef = inject(MatDialogRef<CategoryEditorDialog>);\n readonly data = inject<CategoryEditorDialogData>(MAT_DIALOG_DATA);\n private readonly translate = inject(NGX_THIN_ADMIN_TRANSLATE);\n\n categoryLabel?: string;\n\n t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string {\n return this.translate(key, params);\n }\n\n save() {\n if (!this.categoryLabel) {\n return;\n }\n\n this.dialogRef.close({\n label: this.categoryLabel,\n });\n }\n}\n","<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","import { Component, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport {\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n MAT_DIALOG_DATA,\n MatDialogRef,\n} from '@angular/material/dialog';\nimport { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminI18nKey } from '../../i18n';\n\nexport interface ConfirmDialogData {\n title?: string;\n message?: string;\n positiveButtonText?: string;\n cancelButtonText?: string;\n}\n\n@Component({\n selector: 'lib-confirm-dialog',\n imports: [\n FormsModule,\n MatButtonModule,\n MatDialogTitle,\n MatDialogContent,\n MatDialogActions,\n MatDialogClose,\n ],\n templateUrl: './confirm-dialog.html',\n styleUrl: './confirm-dialog.scss',\n})\nexport class ConfirmDialog {\n readonly dialogRef = inject(MatDialogRef<ConfirmDialog>);\n readonly data = inject<ConfirmDialogData>(MAT_DIALOG_DATA);\n private readonly translate = inject(NGX_THIN_ADMIN_TRANSLATE);\n\n t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string {\n return this.translate(key, params);\n }\n}\n","<h2 mat-dialog-title>{{ data.title }}</h2>\n<mat-dialog-content>\n {{ data.message }}\n</mat-dialog-content>\n<mat-dialog-actions>\n <button class=\"cancel-btn\" matButton [mat-dialog-close]=\"undefined\">\n {{ data.cancelButtonText || t('common.cancel') }}\n </button>\n <button matButton [mat-dialog-close]=\"true\" cdkFocusInitial>\n {{ data.positiveButtonText || t('common.ok') }}\n </button>\n</mat-dialog-actions>\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n inject,\n Input,\n Output,\n SimpleChanges,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatListOption, MatSelectionList } from '@angular/material/list';\nimport {\n NgxThinAdminCategory,\n NgxThinAdminCategoryListResponse,\n NgxThinAdminCategorySelectorConfig,\n} from '../../interfaces';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatMenu, MatMenuContent, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { MatDialog } from '@angular/material/dialog';\nimport {\n CategoryEditorDialog,\n CategoryEditorDialogData,\n} from '../../shared/category-editor-dialog/category-editor-dialog';\nimport { lastValueFrom, single } from 'rxjs';\nimport { ConfirmDialog, ConfirmDialogData } from '../../shared/confirm-dialog/confirm-dialog';\nimport { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminI18nKey } from '../../i18n';\n\n@Component({\n selector: 'lib-list-category-selector',\n imports: [\n FormsModule,\n MatIcon,\n MatIconButton,\n MatSelectionList,\n MatMenu,\n MatMenuItem,\n MatMenuTrigger,\n MatListOption,\n MatMenuContent,\n ],\n templateUrl: './list-category-selector.html',\n styleUrl: './list-category-selector.scss',\n})\nexport class ListCategorySelector {\n /**\n * Config for the category selector\n */\n @Input() config?: NgxThinAdminCategorySelectorConfig;\n\n /**\n * Selected category. This will be updated when the user selects a category from the list.\n */\n @Input()\n selectedCategory?: (NgxThinAdminCategory | undefined)[];\n\n /**\n * Event emitted when the selected category changes.\n */\n @Output()\n selectedCategoryChange = new EventEmitter<(NgxThinAdminCategory | undefined)[]>();\n\n /**\n * Categories to be displayed in the category selector.\n */\n categories: NgxThinAdminCategory[] = [];\n\n /**\n * Services\n */\n private snackbar = inject(MatSnackBar);\n private dialog = inject(MatDialog);\n private cdr = inject(ChangeDetectorRef);\n private translate = inject(NGX_THIN_ADMIN_TRANSLATE);\n\n t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string {\n return this.translate(key, params);\n }\n\n ngOnChanges(changes: SimpleChanges<ListCategorySelector>) {\n if (\n changes.config &&\n changes.config.currentValue?.fetcher !== changes.config.previousValue?.fetcher\n ) {\n this.fetchCategories();\n }\n }\n\n async fetchCategories() {\n if (!this.config?.fetcher) {\n return;\n } else if (!(this.config.fetcher instanceof Function)) {\n throw new Error('categoryFetcher must be a function');\n }\n\n console.log('Fetching categories');\n try {\n const result = await Promise.resolve(this.config.fetcher());\n console.log(result);\n this.categories = result.categories;\n this.cdr.markForCheck();\n console.log('Fetched categories:', this.categories);\n } catch (e) {\n console.error('Error fetching categories:', e);\n }\n }\n\n async createCategory(categoryLabel: string) {\n if (!this.config?.creator) {\n return;\n }\n\n // Call the category creator function\n try {\n await this.config.creator(categoryLabel);\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? this.t('category.errorCouldNotCreate')}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async updateCategory(category: NgxThinAdminCategory) {\n if (!this.config?.updater) {\n return;\n }\n\n // Call the category updater function\n try {\n await this.config.updater(category);\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? this.t('category.errorFailedUpdate', { label: category.label })}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async deleteCategory(category: NgxThinAdminCategory) {\n if (!this.config?.deleter) {\n return;\n }\n\n // Call the category deleter function\n try {\n await this.config.deleter(category);\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? this.t('category.errorFailedDelete', { label: category.label })}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async openCategoryEditorDialog(editCategory: NgxThinAdminCategory | undefined) {\n // Open a dialog for category creation / editing\n const dialogRef = this.dialog.open(CategoryEditorDialog, {\n width: '400px',\n data: {\n config: this.config!,\n editCategory: editCategory,\n positiveButtonText: editCategory ? this.t('common.save') : this.t('common.create'),\n cancelButtonText: this.t('common.cancel'),\n } satisfies CategoryEditorDialogData,\n });\n const result = await lastValueFrom(dialogRef.afterClosed());\n if (!result || !result.label) {\n return;\n }\n\n // Call the category creator / updater function\n try {\n if (editCategory) {\n await this.updateCategory({ ...editCategory, label: result.label });\n } else {\n await this.createCategory(result.label);\n }\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? this.t('category.errorCouldNotSave')}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n\n async openCategoryDeletionDialog(category: NgxThinAdminCategory) {\n // Open a dialog for category deletion\n const dialogRef = this.dialog.open(ConfirmDialog, {\n width: '400px',\n data: {\n title: this.t('category.deletionDialogTitle', {\n categoryType: this.config?.singularLabel ?? this.t('category.defaultSingular'),\n }),\n message: this.t('category.deletionDialogMessage', {\n categoryType: this.config?.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n }),\n positiveButtonText: this.t('common.delete'),\n cancelButtonText: this.t('common.cancel'),\n } satisfies ConfirmDialogData,\n });\n const result = await lastValueFrom(dialogRef.afterClosed());\n if (!result) {\n return;\n }\n\n // Call the category deleter function\n try {\n await this.deleteCategory(category);\n } catch (e: any) {\n this.snackbar.open(\n `Error: ${e?.message ?? this.t('category.errorFailedDelete', { label: category.label })}`,\n undefined,\n {\n duration: 3000,\n },\n );\n }\n\n // Refresh category list\n this.fetchCategories();\n }\n}\n","<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","import { inject, Injectable } from '@angular/core';\nimport {\n ListFetcher,\n NgxThinAdminListColumn,\n NgxThinAdminListQuery,\n NgxThinAdminListResponse,\n} from '../interfaces';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { ColumnOption, stringify as csvStringify } from 'csv-stringify/browser/esm/sync';\nimport { NGX_THIN_ADMIN_TRANSLATE } from '../i18n';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class CsvExportService {\n private snackbar = inject(MatSnackBar);\n private translate = inject(NGX_THIN_ADMIN_TRANSLATE);\n\n private encoders: {\n key: string;\n label: string;\n mimeCharset: string;\n encoder: ((input: string) => ArrayBuffer | null) | undefined;\n }[] = [\n {\n key: 'utf8',\n label: 'UTF-8',\n mimeCharset: 'UTF-8',\n encoder: undefined,\n },\n ];\n\n constructor() {\n this.loadOptionalEncoders();\n }\n\n private async loadOptionalEncoders() {\n // Optional charset support for Shift_JIS (commonly used in Japan)\n try {\n // @ts-ignore\n const Encoding = (await import('encoding-japanese')) as any;\n this.encoders.push({\n key: 'sjis',\n label: 'Shift_JIS',\n mimeCharset: 'Shift_JIS',\n encoder: (input: string) => {\n const sjisArrayBuffer = Encoding.convert(input, {\n from: 'UNICODE',\n to: 'SJIS',\n type: 'arraybuffer',\n });\n return new Uint8Array(sjisArrayBuffer).buffer;\n },\n });\n } catch (error) {\n console.error(\n 'Shift_JIS encoder is not available. If you need it, please install \"encoding-japanese\" package.',\n error,\n );\n // Do nothing\n }\n }\n\n getAvailableEncoders() {\n return this.encoders.map((encoder) => ({\n key: encoder.key,\n label: encoder.label,\n }));\n }\n\n async exportListAsCsv(\n encoderKey: string,\n fileNamePrefix: string,\n fetcher: ListFetcher,\n listQuery: Omit<NgxThinAdminListQuery, 'page' | 'perPage'>,\n columns: NgxThinAdminListColumn[],\n ) {\n const CSV_EXPORT_MAX_PAGE_INDEX = 1000;\n const CSV_EXPORT_PAGE_SIZE = 25;\n\n console.log('Starting CSV export', listQuery, encoderKey);\n\n // Get encoder\n const encoderInfo = this.encoders.find((e) => e.key === encoderKey);\n if (!encoderInfo) {\n console.error(`exportListAsCsv - Encoder not found for key: ${encoderKey}`);\n return;\n }\n const mimeCharset = encoderInfo.mimeCharset;\n const encoder = encoderInfo.encoder;\n\n // Initialize\n const items: any[] = [];\n let errorMessage: string | undefined = undefined;\n\n // 処理中メッセージを表示\n const mes = this.snackbar.open(this.translate('csv.exporting'));\n\n // Replace characters in the file name prefix that cannot be used in file names\n fileNamePrefix = fileNamePrefix.replace(/[/¥\\\\*?:\"<>|@\\s;^.]/g, '_');\n\n // Truncate the file name prefix if it is too long\n const FILE_NAME_PREFIX_MAX_LENGTH = 100;\n if (fileNamePrefix.length > FILE_NAME_PREFIX_MAX_LENGTH) {\n fileNamePrefix = fileNamePrefix.substring(0, FILE_NAME_PREFIX_MAX_LENGTH);\n }\n\n // Generate file name\n const now = new Date();\n const year = now.getFullYear();\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const date = String(now.getDate()).padStart(2, '0');\n const hours = String(now.getHours()).padStart(2, '0');\n const minutes = String(now.getMinutes()).padStart(2, '0');\n const seconds = String(now.getSeconds()).padStart(2, '0');\n const datetimeString = `${year}${month}${date}_${hours}${minutes}${seconds}`;\n const csvFileName = `${fileNamePrefix}_${datetimeString}.csv`;\n\n // Fetch items page by page\n let numOfExportedItems = 0;\n for (let pageIndex = 0; pageIndex < CSV_EXPORT_MAX_PAGE_INDEX; pageIndex++) {\n const query: NgxThinAdminListQuery = {\n ...listQuery,\n page: pageIndex,\n perPage: CSV_EXPORT_PAGE_SIZE,\n };\n\n let result: NgxThinAdminListResponse;\n try {\n result = await fetcher(query);\n } catch (error: any) {\n console.error(`exportListAsCsv - Error fetching data:`, error);\n errorMessage = error.message || 'Unknown error';\n break;\n }\n\n // Wait for few seconds\n await new Promise((resolve) => setTimeout(resolve, 100));\n\n if (result.items.length === 0) {\n // No items, exit\n break;\n }\n\n // Add fetched items\n items.push(...result.items);\n numOfExportedItems += result.items.length;\n }\n\n // Determine CSV columns\n const csvColumns: ColumnOption[] = columns\n .filter((column) => {\n if (column.type === 'button') {\n // Exclude columns that are buttons\n return false;\n }\n return true;\n })\n .map((column) => {\n // Get the column key (e.g., \"name\")\n const columnKey: string = column.field;\n // Get the column header string (e.g., \"User Name\")\n let columnHeader: string;\n if (typeof column.header === 'string') {\n columnHeader = column.header;\n } else {\n columnHeader = columnKey;\n }\n // Return column information for csv-stringify\n return {\n key: column.field,\n header: columnHeader,\n };\n })\n .filter((column) => column !== null);\n\n // Convert to CSV\n const csv = csvStringify(items, {\n header: true,\n columns: csvColumns,\n });\n\n // Generate Blob\n let blob: Blob | undefined = undefined;\n if (encoder) {\n const encodedData = encoder(csv);\n if (encodedData) {\n blob = new Blob([encodedData], { type: `text/csv; charset=${mimeCharset}` });\n } else {\n console.error(`exportListAsCsv - Encoding failed for encoder: ${encoderKey}`);\n }\n } else {\n blob = new Blob([csv], { type: `text/csv; charset=${mimeCharset}` });\n }\n\n if (!blob) {\n console.error(`exportListAsCsv - Blob is not created`);\n mes.dismiss();\n this.snackbar.open(this.translate('csv.errorGenerateFailed'), undefined, {\n duration: 5000,\n });\n return;\n }\n\n // Download as CSV\n const objectUrl = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.download = csvFileName;\n a.href = objectUrl;\n a.click();\n\n // Revoke object URL after download\n URL.revokeObjectURL(objectUrl);\n\n // Dissmiss processing message\n mes.dismiss();\n\n // 結果メッセージを表示\n if (errorMessage) {\n this.snackbar.open(\n this.translate('csv.exportCompletedWithErrors', {\n count: numOfExportedItems,\n error: errorMessage,\n }),\n undefined,\n {\n duration: 5000,\n },\n );\n } else {\n this.snackbar.open(\n this.translate('csv.exportCompleted', { count: numOfExportedItems }),\n undefined,\n {\n duration: 3000,\n },\n );\n }\n }\n}\n","import {\n Component,\n inject,\n Input,\n OnChanges,\n OnInit,\n SimpleChanges,\n TemplateRef,\n ViewChild,\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { debounceTime } from 'rxjs/operators';\nimport { MatButton, MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInput, MatPrefix, MatSuffix } from '@angular/material/input';\nimport { MatFormField } from '@angular/material/select';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport { MtxGridColumn, MtxGridModule } from '@ng-matero/extensions/grid';\nimport {\n NgxThinAdminCategory,\n NgxThinAdminCategorySelectorConfig,\n NgxThinAdminListColumn,\n NgxThinAdminListConfig,\n NgxThinAdminListQuery,\n NgxThinAdminListResponse,\n} from '../interfaces';\nimport { FormsModule } from '@angular/forms';\nimport { PageEvent } from '@angular/material/paginator';\nimport { ChangeDetectorRef } from '@angular/core';\nimport { ListCategorySelector } from './list-category-selector/list-category-selector';\nimport { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';\nimport { MatListOption } from '@angular/material/list';\nimport { CsvExportService } from '../shared/csv-export-service';\nimport { RouterLink } from '@angular/router';\nimport { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminI18nKey } from '../i18n';\n\n@Component({\n selector: 'ngx-thin-admin-list',\n imports: [\n FormsModule,\n MtxGridModule,\n MatButton,\n MatIcon,\n MatIconButton,\n MatTooltip,\n MatFormField,\n MatInput,\n MatPrefix,\n MatSuffix,\n ListCategorySelector,\n MatMenu,\n MatMenuItem,\n MatMenuTrigger,\n RouterLink,\n ],\n templateUrl: './ngx-thin-admin-list.html',\n styleUrl: './ngx-thin-admin-list.scss',\n})\nexport class NgxThinAdminList implements OnChanges, OnInit {\n /**\n * Config for list\n */\n @Input()\n listConfig?: NgxThinAdminListConfig;\n\n /**\n * Config for category selector. If provided, a category selector will be displayed in the UI.\n */\n @Input()\n categorySelectorConfig?: NgxThinAdminCategorySelectorConfig;\n\n /**\n * Column schema (extended type of MtxGridColumn)\n * @see https://ng-matero.github.io/extensions/components/grid/api\n */\n @Input()\n listColumns?: MtxGridColumn[];\n\n /**\n * Query (Optional)\n */\n @Input() query: NgxThinAdminListQuery = {\n keyword: '',\n page: 0,\n perPage: 10,\n categoryId: undefined,\n };\n\n /**\n * Fetcher function to retrieve list data.\n * This should be provided as part of listConfig.\n */\n private listFetcher?: (\n query: NgxThinAdminListQuery,\n ) => Promise<NgxThinAdminListResponse> | NgxThinAdminListResponse;\n\n /**\n * Internal state for grid\n */\n isLoading = false;\n gridColumns: MtxGridColumn[] = [];\n gridData: any[] = [];\n totalCount: number = 0;\n\n /**\n * Internal state for category list\n */\n categories: NgxThinAdminCategory[] = [];\n selectedCategory?: NgxThinAdminCategory[] = [];\n\n /**\n * Internal subject to trigger keyword change with debounce\n */\n private keywordChanged$ = new Subject<void>();\n ngOnInit(): void {\n this.keywordChanged$.pipe(debounceTime(500)).subscribe(() => {\n this.fetchList();\n });\n }\n\n /**\n * Template for cells\n */\n @ViewChild('cellTplWithLink', { static: true }) cellTplWithLink!: TemplateRef<any>;\n\n /**\n * Services\n */\n private cdr = inject(ChangeDetectorRef);\n private translate = inject(NGX_THIN_ADMIN_TRANSLATE);\n csvExportService = inject(CsvExportService);\n\n t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string {\n return this.translate(key, params);\n }\n\n ngOnChanges(changes: SimpleChanges<NgxThinAdminList>) {\n // Columns\n if (changes.listColumns?.currentValue) {\n this.gridColumns = changes.listColumns.currentValue.map((col: NgxThinAdminListColumn) => {\n if (col.link || col.routerLink) {\n return { ...col, cellTemplate: this.cellTplWithLink };\n }\n return col;\n });\n }\n\n // List - trigger strictly when listFetcher is newly provided or explicitly changed\n if (changes.listConfig?.currentValue?.fetcher !== changes.listConfig?.previousValue?.fetcher) {\n this.listFetcher = changes.listConfig?.currentValue?.fetcher;\n this.fetchList();\n }\n }\n\n async fetchList() {\n if (!this.listFetcher) {\n return;\n } else if (!(this.listFetcher instanceof Function)) {\n throw new Error('listFetcher must be a function');\n }\n\n console.log('Fetching data with query:', this.query);\n this.isLoading = true;\n\n try {\n const result = await Promise.resolve(this.listFetcher(this.query));\n this.gridData = result.items;\n this.totalCount = result.totalCount;\n } catch (e) {\n console.error('Error fetching list data:', e);\n } finally {\n this.isLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n clearFilters() {\n this.query.keyword = '';\n this.query.categoryId = undefined;\n this.selectedCategory = [];\n this.fetchList();\n }\n\n onKeywordInput() {\n this.keywordChanged$.next();\n }\n\n async exportAsCsv(encoderKey: 'utf8' | string) {\n if (!this.listFetcher) {\n return;\n }\n\n // Determine file name prefix\n let fileNamePrefix: string = this.listConfig?.title\n ? this.listConfig.title\n : this.t('list.exportedFileName');\n if (this.selectedCategory && this.selectedCategory[0]?.id) {\n // If a category is selected, include the category label in the file name prefix\n fileNamePrefix += `_${this.selectedCategory[0]?.label}`;\n }\n if (this.query.keyword && this.query.keyword.length > 0) {\n // If a search keyword is entered, include it in the file name prefix\n fileNamePrefix += `_${this.query.keyword}`;\n }\n\n // Execute export\n await this.csvExportService.exportListAsCsv(\n encoderKey,\n fileNamePrefix,\n this.listFetcher,\n {\n categoryId: this.selectedCategory ? this.selectedCategory[0]?.id : undefined,\n keyword: this.query.keyword,\n },\n this.listColumns!,\n );\n }\n\n onPageChange(event: PageEvent) {\n this.query.page = event.pageIndex;\n this.query.perPage = event.pageSize;\n this.fetchList();\n }\n\n onSelectedCategoryChange($event: (NgxThinAdminCategory | undefined)[]) {\n console.log('Selected category changed:', $event);\n const categoryId = $event && $event.length >= 1 && $event[0] ? $event[0].id : undefined;\n this.query.categoryId = categoryId;\n this.fetchList();\n }\n}\n","<!-- 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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\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=\"primary-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label }}\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","import { Component, TemplateRef, ViewChild, AfterViewInit } from '@angular/core';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatPrefix, MatSuffix } from '@angular/material/input';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport { FieldWrapper, FormlyFieldConfig } from '@ngx-formly/core';\n\n@Component({\n selector: 'lib-formly-mat-prefix-addon-wrapper',\n imports: [MatIconButton, MatIcon, MatSuffix, MatTooltip],\n template: `\n <ng-container #fieldComponent></ng-container>\n\n <ng-template #matSuffix>\n @if (props['addonRight']) {\n @if (props['addonRight']['icon']) {\n <button\n mat-icon-button\n matSuffix\n style=\"margin-right: 1rem;\"\n [matTooltip]=\"props['addonRight']['tooltip'] ?? ''\"\n (click)=\"props['addonRight'].onClick ? addonRightClick($event) : null\"\n type=\"button\"\n >\n <mat-icon>{{ props['addonRight']['icon'] }}</mat-icon>\n </button>\n }\n @if (props['addonRight']['text']) {\n <span>{{ props['addonRight']['text'] }}</span>\n }\n }\n </ng-template>\n `,\n})\nexport class FormlyMatPrefixAddonWrapper extends FieldWrapper implements AfterViewInit {\n @ViewChild('matPrefix', { static: true }) matPrefix!: TemplateRef<any>;\n @ViewChild('matSuffix', { static: true }) matSuffix!: TemplateRef<any>;\n\n ngAfterViewInit() {\n if (this.matPrefix) {\n this.props['prefix'] = this.matPrefix;\n }\n\n if (this.matSuffix) {\n this.props['suffix'] = this.matSuffix;\n }\n }\n\n addonRightClick($event: any) {\n if (this.props['addonRight'].onClick) {\n this.props['addonRight'].onClick(this.to, this, $event);\n }\n }\n\n addonLeftClick($event: any) {\n if (this.props['addonLeft'].onClick) {\n this.props['addonLeft'].onClick(this.to, this, $event);\n }\n }\n}\n\nexport function formlyAddonsExtension(field: FormlyFieldConfig) {\n if (!field.props || (field.wrappers && field.wrappers.indexOf('addons') !== -1)) {\n return;\n }\n\n if (field.props['addonLeft'] || field.props['addonRight']) {\n field.wrappers = [...(field.wrappers || []), 'addons'];\n }\n}\n","export function getErrorMessage(error: any): string {\n if (typeof error === 'string') {\n return error;\n } else if (error instanceof Error) {\n return error.message;\n } else if (error?.error?.message) {\n if (Array.isArray(error.error.message)) {\n return error.error.message[0];\n } else {\n return error.error.message;\n }\n } else {\n return 'An unknown error occurred';\n }\n}\n","import { Component } from '@angular/core';\nimport { FormlyAttributes, FieldType, FieldTypeConfig } from '@ngx-formly/core';\nimport { ReactiveFormsModule, FormControl } from '@angular/forms';\nimport { MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatInputModule } from '@angular/material/input';\nimport {\n MatFormField,\n MatLabel,\n MatHint,\n MatSuffix,\n} from '@angular/material/form-field';\n\n@Component({\n selector: 'formly-field-file',\n template: `\n <mat-form-field appearance=\"outline\" floatLabel=\"always\" subscriptSizing=\"dynamic\" style=\"width:100%\">\n <!-- Field label -->\n @if (props.label) {\n <mat-label>{{ props.label }}{{ props.required ? ' *' : '' }}</mat-label>\n }\n \n <!-- Choosed file name -->\n <input matInput type=\"text\" readonly [value]=\"fileName\" [formlyAttributes]=\"field\" (click)=\"fileInput.click()\" />\n\n <!-- File choose button -->\n <button mat-icon-button matSuffix style=\"margin-right: 1rem;\" type=\"button\" (click)=\"fileInput.click()\">\n <mat-icon>attach_file</mat-icon>\n </button>\n\n <!-- Actual file input (hidden) -->\n <input\n type=\"file\"\n #fileInput\n style=\"display: none\"\n [attr.accept]=\"props['accept'] ?? null\"\n (change)=\"onFileChange($event)\"\n />\n\n <!-- Field description -->\n @if (props.description) {\n <mat-hint>{{ props.description }}</mat-hint>\n }\n </mat-form-field>\n `,\n standalone: true,\n imports: [\n ReactiveFormsModule,\n FormlyAttributes,\n MatInputModule,\n MatIcon,\n MatIconButton,\n MatFormField,\n MatLabel,\n MatHint,\n MatSuffix,\n ],\n})\nexport class FormlyFieldFile extends FieldType<FieldTypeConfig> {\n /** 表示用のファイル名 */\n fileName = '';\n\n /** ファイルが選択されたときの処理 */\n onFileChange(event: Event): void {\n const input = event.target as HTMLInputElement;\n const file = input.files?.[0] ?? null;\n\n // formControl に File オブジェクトをセット\n this.formControl.setValue(file);\n this.formControl.markAsDirty();\n\n // 表示用のファイル名を更新\n this.fileName = file?.name ?? '';\n }\n}\n\n","import {\n ChangeDetectorRef,\n Component,\n inject,\n Input,\n OnChanges,\n SimpleChanges,\n} from '@angular/core';\nimport { FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { MatButton } from '@angular/material/button';\nimport { MatSnackBar } from '@angular/material/snack-bar';\nimport { MatCard, MatCardHeader, MatCardContent } from '@angular/material/card';\nimport { FormlyFieldConfig, FormlyForm, provideFormlyCore } from '@ngx-formly/core';\nimport { withFormlyMaterial } from '@ngx-formly/material';\nimport { NgxThinAdminEditorConfig, NgxThinAdminEditorField } from '../interfaces';\nimport { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';\nimport {\n formlyAddonsExtension,\n FormlyMatPrefixAddonWrapper,\n} from '../shared/formly/mat-prefix-addon-wrapper/mat-prefix-addon-wrapper';\nimport { MatProgressBar } from '@angular/material/progress-bar';\nimport { getErrorMessage } from '../shared/error-handler';\nimport { FormlyFieldFile } from '../shared/formly/file-input/file-type.component';\nimport { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminI18nKey } from '../i18n';\n\n@Component({\n selector: 'ngx-thin-admin-editor',\n imports: [\n ReactiveFormsModule,\n FormlyForm,\n MatButton,\n MatProgressBar,\n MatCard,\n MatCardHeader,\n MatCardContent,\n ],\n providers: [\n provideFormlyCore(withFormlyMaterial()),\n provideFormlyCore({\n wrappers: [\n {\n name: 'addons',\n component: FormlyMatPrefixAddonWrapper,\n },\n ],\n extensions: [{ name: 'addons', extension: { onPopulate: formlyAddonsExtension } }],\n types: [\n {\n name: 'file',\n component: FormlyFieldFile,\n },\n ],\n }),\n {\n // Apply default appearance and other settings to all Material form fields in this component\n provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,\n useValue: {\n appearance: 'outline',\n floatLabel: 'always',\n subscriptSizing: 'dynamic',\n },\n },\n ],\n templateUrl: './ngx-thin-admin-editor.html',\n styleUrl: './ngx-thin-admin-editor.scss',\n})\nexport class NgxThinAdminEditor implements OnChanges {\n /**\n * Config for editor\n */\n @Input()\n editorConfig?: NgxThinAdminEditorConfig;\n\n /**\n * Fields for formly form\n */\n @Input()\n editorFields?: NgxThinAdminEditorField[];\n\n /**\n * Id of the item being edited.\n */\n @Input()\n itemId?: string;\n\n /**\n * Internal state for form\n */\n isSaving = false;\n isLoading = false;\n form = new FormGroup({});\n data: any = {};\n formData: any = {};\n\n /**\n * Services\n */\n private snackbar = inject(MatSnackBar);\n private cdr = inject(ChangeDetectorRef);\n private translate = inject(NGX_THIN_ADMIN_TRANSLATE);\n\n t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string {\n return this.translate(key, params);\n }\n\n ngOnChanges(changes: SimpleChanges<NgxThinAdminEditor>) {\n // Fetcher\n if (\n changes.editorConfig &&\n changes.editorConfig.currentValue?.fetcher !== changes.editorConfig.previousValue?.fetcher\n ) {\n this.fetchItem();\n } else if (changes.itemId && changes.itemId.currentValue !== changes.itemId.previousValue) {\n this.fetchItem();\n }\n\n // Fields\n if (changes.editorFields?.currentValue) {\n this.editorFields = changes.editorFields.currentValue.map((col: NgxThinAdminEditorField) => {\n return this.overwriteFieldProps(col);\n });\n }\n }\n\n overwriteFieldProps(field: NgxThinAdminEditorField) {\n if (!field.props) {\n field.props = {};\n }\n\n // requiredOnCreate\n if (field.props.requiredOnCreate) {\n if (this.itemId === undefined) {\n field.props.required = true;\n } else {\n field.props.required = false;\n }\n }\n\n // disabledOnUpdate\n if (field.props.disabledOnUpdate) {\n if (this.itemId !== undefined) {\n //formControl.disable();\n field.props.disabled = true;\n } else {\n //formControl.enable();\n field.props.disabled = false;\n }\n }\n\n return field;\n }\n\n async fetchItem() {\n if (!this.editorConfig?.fetcher) {\n return;\n } else if (!this.itemId) {\n this.data = {};\n return;\n }\n\n // Set loading state\n this.isLoading = true;\n this.cdr.markForCheck();\n\n // Call the fetcher function to get the item data\n try {\n let res = await this.editorConfig.fetcher(this.itemId);\n\n if (res instanceof Response) {\n if (!res.ok) {\n const data = await res.json();\n throw new Error(\n data.error ?? data.message ?? `Failed to fetch data: ${res.status} ${res.statusText}`,\n );\n }\n res = await res.json();\n }\n\n this.data = { ...res };\n this.formData = { ...res };\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(`Error: ${errorMessage}`, undefined, {\n duration: 3000,\n });\n\n // Reset loading state\n this.isLoading = false;\n this.cdr.markForCheck();\n return;\n }\n\n this.isLoading = false;\n this.cdr.markForCheck();\n }\n\n async save() {\n if (this.form.status === 'INVALID') {\n this.snackbar.open(`Error: ${this.t('editor.errorInvalidInput')}`, undefined, {\n duration: 3000,\n });\n\n // Mark field to show validation errors\n Object.keys(this.form.controls).forEach((key) => {\n const control = this.form.get(key);\n control?.markAsTouched();\n });\n\n return;\n }\n\n if (!this.editorConfig?.saver) {\n this.snackbar.open(`Error: ${this.t('editor.errorNoSaver')}`, undefined, {\n duration: 3000,\n });\n return;\n }\n\n // Disable the form and save button to prevent multiple submissions\n this.form.disable();\n this.isSaving = true;\n\n // Call the saver function\n let result: any;\n try {\n let res: any = await this.editorConfig.saver(this.formData, this.itemId);\n\n if (res instanceof Response) {\n if (!res.ok) {\n const data = await res.json();\n throw new Error(\n data.error ?? data.message ?? `Failed to save data: ${res.status} ${res.statusText}`,\n );\n }\n res = await res.json();\n }\n\n result = res;\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(`Error: ${errorMessage}`, undefined, {\n duration: 3000,\n });\n\n // Re-enable the form and save button\n this.form.enable();\n this.isSaving = false;\n\n return;\n }\n\n // Show success message\n this.snackbar.open(this.t('editor.successSaved'), undefined, {\n duration: 3000,\n });\n\n // Update form data with the result from the saver (e.g., to get generated ID)\n this.data = { ...result };\n this.formData = { ...result };\n\n // Re-enable the form and save button\n this.form.enable();\n for (const field of this.editorFields ?? []) {\n this.overwriteFieldProps(field);\n }\n this.isSaving = false;\n }\n}\n","<mat-card>\n <mat-card-header>\n <h3>\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('common.edit') }}\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\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('common.create') }}\n @if (editorConfig?.singularLabel) {\n {{ editorConfig?.singularLabel }}\n }\n <!---->\n }\n </h3>\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\"></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 @if (editorConfig?.saver) {\n <!-- Submit button -->\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem); float: right\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n <!---->\n }\n </form>\n }\n </mat-card-content>\n</mat-card>\n","/*\n * Public API Surface of ngx-thin-admin\n */\n\nexport * from './lib/ngx-thin-admin-list/ngx-thin-admin-list';\nexport * from './lib/ngx-thin-admin-editor/ngx-thin-admin-editor';\nexport * from './lib/interfaces';\nexport * from './lib/i18n';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1","i2","i3","csvStringify","MatFormField","MatSuffix"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { OnChanges, OnInit, TemplateRef, SimpleChanges } from '@angular/core';
|
|
2
|
+
import { InjectionToken, Provider, OnChanges, OnInit, TemplateRef, SimpleChanges } from '@angular/core';
|
|
3
3
|
import { MtxGridColumn } from '@ng-matero/extensions/grid';
|
|
4
4
|
import { FormlyFieldConfig, FormlyFieldProps } from '@ngx-formly/core';
|
|
5
5
|
import { PageEvent } from '@angular/material/paginator';
|
|
@@ -182,6 +182,7 @@ interface NgxThinAdminCategoryListResponse {
|
|
|
182
182
|
|
|
183
183
|
declare class CsvExportService {
|
|
184
184
|
private snackbar;
|
|
185
|
+
private translate;
|
|
185
186
|
private encoders;
|
|
186
187
|
constructor();
|
|
187
188
|
private loadOptionalEncoders;
|
|
@@ -194,6 +195,18 @@ declare class CsvExportService {
|
|
|
194
195
|
static ɵprov: i0.ɵɵInjectableDeclaration<CsvExportService>;
|
|
195
196
|
}
|
|
196
197
|
|
|
198
|
+
type NgxThinAdminLocale = 'en' | 'ja';
|
|
199
|
+
type NgxThinAdminI18nKey = 'common.cancel' | 'common.ok' | 'common.save' | 'common.create' | 'common.edit' | 'common.delete' | 'list.defaultTitle' | 'list.clearFilters' | 'list.searchDefaultPlaceholder' | 'list.searchInCategoryPlaceholder' | 'list.clearSearchKeyword' | 'list.refresh' | 'list.exportAsCsv' | 'list.exportedFileName' | 'list.exportItems' | 'editor.idLabel' | 'editor.saveChanges' | 'editor.errorInvalidInput' | 'editor.errorNoSaver' | 'editor.successSaved' | 'category.defaultSingular' | 'category.defaultPlural' | 'category.all' | 'category.editorDialogTitleForCreate' | 'category.editorDialogTitleForEdit' | 'category.deletionDialogTitle' | 'category.deletionDialogMessage' | 'category.errorCouldNotCreate' | 'category.errorFailedUpdate' | 'category.errorFailedDelete' | 'category.errorCouldNotSave' | 'csv.exporting' | 'csv.exportCompleted' | 'csv.exportCompletedWithErrors' | 'csv.errorGenerateFailed';
|
|
200
|
+
type NgxThinAdminI18nParams = Record<string, string | number | undefined>;
|
|
201
|
+
type NgxThinAdminTranslate = (key: NgxThinAdminI18nKey, params?: NgxThinAdminI18nParams) => string;
|
|
202
|
+
interface NgxThinAdminI18nConfig {
|
|
203
|
+
locale?: NgxThinAdminLocale;
|
|
204
|
+
messages?: Partial<Record<NgxThinAdminI18nKey, string>>;
|
|
205
|
+
translate?: NgxThinAdminTranslate;
|
|
206
|
+
}
|
|
207
|
+
declare const NGX_THIN_ADMIN_TRANSLATE: InjectionToken<NgxThinAdminTranslate>;
|
|
208
|
+
declare function provideNgxThinAdminI18n(config?: NgxThinAdminI18nConfig): Provider;
|
|
209
|
+
|
|
197
210
|
declare class NgxThinAdminList implements OnChanges, OnInit {
|
|
198
211
|
/**
|
|
199
212
|
* Config for list
|
|
@@ -242,7 +255,9 @@ declare class NgxThinAdminList implements OnChanges, OnInit {
|
|
|
242
255
|
* Services
|
|
243
256
|
*/
|
|
244
257
|
private cdr;
|
|
258
|
+
private translate;
|
|
245
259
|
csvExportService: CsvExportService;
|
|
260
|
+
t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string;
|
|
246
261
|
ngOnChanges(changes: SimpleChanges<NgxThinAdminList>): void;
|
|
247
262
|
fetchList(): Promise<void>;
|
|
248
263
|
clearFilters(): void;
|
|
@@ -280,6 +295,8 @@ declare class NgxThinAdminEditor implements OnChanges {
|
|
|
280
295
|
*/
|
|
281
296
|
private snackbar;
|
|
282
297
|
private cdr;
|
|
298
|
+
private translate;
|
|
299
|
+
t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string;
|
|
283
300
|
ngOnChanges(changes: SimpleChanges<NgxThinAdminEditor>): void;
|
|
284
301
|
overwriteFieldProps(field: NgxThinAdminEditorField): NgxThinAdminEditorField;
|
|
285
302
|
fetchItem(): Promise<void>;
|
|
@@ -288,5 +305,5 @@ declare class NgxThinAdminEditor implements OnChanges {
|
|
|
288
305
|
static ɵcmp: i0.ɵɵComponentDeclaration<NgxThinAdminEditor, "ngx-thin-admin-editor", never, { "editorConfig": { "alias": "editorConfig"; "required": false; }; "editorFields": { "alias": "editorFields"; "required": false; }; "itemId": { "alias": "itemId"; "required": false; }; }, {}, never, never, true, never>;
|
|
289
306
|
}
|
|
290
307
|
|
|
291
|
-
export { NgxThinAdminEditor, NgxThinAdminList };
|
|
292
|
-
export type { ListFetcher, NgxThinAdminCategory, NgxThinAdminCategoryListResponse, NgxThinAdminCategorySelectorConfig, NgxThinAdminEditorConfig, NgxThinAdminEditorField, NgxThinAdminFieldConfig, NgxThinAdminFieldProps, NgxThinAdminListColumn, NgxThinAdminListConfig, NgxThinAdminListCreateButtonConfig, NgxThinAdminListCsvExportButtonConfig, NgxThinAdminListQuery, NgxThinAdminListResponse };
|
|
308
|
+
export { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminEditor, NgxThinAdminList, provideNgxThinAdminI18n };
|
|
309
|
+
export type { ListFetcher, NgxThinAdminCategory, NgxThinAdminCategoryListResponse, NgxThinAdminCategorySelectorConfig, NgxThinAdminEditorConfig, NgxThinAdminEditorField, NgxThinAdminFieldConfig, NgxThinAdminFieldProps, NgxThinAdminI18nConfig, NgxThinAdminI18nKey, NgxThinAdminI18nParams, NgxThinAdminListColumn, NgxThinAdminListConfig, NgxThinAdminListCreateButtonConfig, NgxThinAdminListCsvExportButtonConfig, NgxThinAdminListQuery, NgxThinAdminListResponse, NgxThinAdminLocale, NgxThinAdminTranslate };
|