ngx-thin-admin 0.0.0-alpha.3 → 0.0.0-alpha.4

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.
@@ -33,6 +33,7 @@ const messagesEn = {
33
33
  'common.create': 'Create',
34
34
  'common.edit': 'Edit',
35
35
  'common.delete': 'Delete',
36
+ 'common.back': 'Back',
36
37
  'list.defaultTitle': 'List',
37
38
  'list.clearFilters': 'Clear filters',
38
39
  'list.searchDefaultPlaceholder': 'Search...',
@@ -49,6 +50,7 @@ const messagesEn = {
49
50
  'editor.errorInvalidInput': 'Invalid input',
50
51
  'editor.errorNoSaver': 'No saver function provided',
51
52
  'editor.successSaved': 'Data saved successfully',
53
+ 'editor.backToList': 'To List',
52
54
  'category.defaultSingular': 'Category',
53
55
  'category.defaultPlural': 'Categories',
54
56
  'category.all': 'All',
@@ -80,6 +82,7 @@ const messagesJa = {
80
82
  'common.create': '作成',
81
83
  'common.edit': '編集',
82
84
  'common.delete': '削除',
85
+ 'common.back': '戻る',
83
86
  'list.defaultTitle': '一覧',
84
87
  'list.clearFilters': 'フィルターをクリア',
85
88
  'list.searchDefaultPlaceholder': '検索...',
@@ -96,6 +99,7 @@ const messagesJa = {
96
99
  'editor.errorInvalidInput': '入力内容が不正です',
97
100
  'editor.errorNoSaver': '保存処理が設定されていません',
98
101
  'editor.successSaved': '保存しました',
102
+ 'editor.backToList': '一覧へ',
99
103
  'category.defaultSingular': 'カテゴリ',
100
104
  'category.defaultPlural': 'カテゴリ',
101
105
  'category.all': 'すべて',
@@ -845,7 +849,7 @@ class NgxThinAdminList {
845
849
  this.fetchList();
846
850
  }
847
851
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminList, deps: [], target: i0.ɵɵFactoryTarget.Component });
848
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: NgxThinAdminList, isStandalone: true, selector: "ngx-thin-admin-list", inputs: { listConfig: "listConfig", categorySelectorConfig: "categorySelectorConfig", itemDeleterConfig: "itemDeleterConfig", listColumns: "listColumns", query: "query" }, viewQueries: [{ propertyName: "cellTplWithLink", first: true, predicate: ["cellTplWithLink"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Category Selector -->\n@if (categorySelectorConfig) {\n <lib-list-category-selector\n [config]=\"categorySelectorConfig\"\n [(selectedCategory)]=\"selectedCategory\"\n (selectedCategoryChange)=\"onSelectedCategoryChange($event)\"\n ></lib-list-category-selector>\n}\n<!---->\n\n<!-- Toolbar Template -->\n<ng-template #toolbarTpl>\n <div class=\"custom-toolbar\">\n <!-- List Title -->\n <span class=\"list-title\">\n @if (listConfig?.title; as listTitle) {\n @if (query.keyword || query.categoryId) {\n <!-- Title (with link for reset filter) -->\n <a\n href=\"javascript:void(0)\"\n (click)=\"query.keyword = ''; query.categoryId = undefined; this.fetchList()\"\n [matTooltip]=\"t('list.clearFilters')\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n {{ t('list.defaultTitle') }}\n <!---->\n }\n\n @if (query.categoryId && selectedCategory?.[0]; as categoryLabel) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Category -->\n {{ categoryLabel.label }}\n <!---->\n }\n\n @if (query.keyword) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Keyword -->\n \"{{ query.keyword }}\"\n <!---->\n }\n </span>\n <!---->\n\n @if (query.keyword || query.categoryId) {\n <span style=\"width: 8px\"></span>\n <!-- Clear Filters Button -->\n <button\n mat-icon-button\n class=\"clear-filters-button\"\n [matTooltip]=\"t('list.clearFilters')\"\n (click)=\"clearFilters()\"\n >\n <mat-icon>filter_alt_off</mat-icon>\n </button>\n <!---->\n }\n\n <span style=\"flex: 1\"></span>\n\n <!-- Create Button -->\n @if (listConfig?.createButton; as createBtn) {\n @if ($any(createBtn).routerLink; as routerLinkUrl) {\n <!-- Create Button with Router Link -->\n <a\n [routerLink]=\"routerLinkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).link; as linkUrl) {\n <!-- Create Button with Link -->\n <a\n [href]=\"linkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).click; as handler) {\n <!-- Create Button with Handler -->\n <button\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </button>\n }\n }\n <!---->\n\n <span style=\"width: 30px\"></span>\n\n <!-- Search Field -->\n <mat-form-field class=\"search-keyword xs-input\" appearance=\"outline\">\n <mat-icon matPrefix>search</mat-icon>\n <input\n matInput\n [placeholder]=\"\n selectedCategory?.[0]?.label\n ? t('list.searchInCategoryPlaceholder', { category: selectedCategory?.[0]?.label })\n : t('list.searchDefaultPlaceholder')\n \"\n [(ngModel)]=\"query.keyword\"\n (keyup)=\"onKeywordInput()\"\n style=\"padding-top: 3px\"\n />\n\n <!-- Search clear button -->\n <button\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"t('list.clearSearchKeyword')\"\n [matTooltip]=\"t('list.clearSearchKeyword')\"\n (click)=\"query.keyword = ''; this.fetchList()\"\n [style.visibility]=\"query.keyword ? 'visible' : 'hidden'\"\n >\n <mat-icon>highlight_off</mat-icon>\n </button>\n <!---->\n </mat-form-field>\n <!---->\n\n <span style=\"width: 8px\"></span>\n\n <!-- Refresh Button -->\n <button mat-icon-button [matTooltip]=\"t('list.refresh')\" (click)=\"fetchList()\">\n <mat-icon>refresh</mat-icon>\n </button>\n <!---->\n\n <span style=\"width: 5px\"></span>\n\n <!-- CSV Export Button -->\n <button\n mat-icon-button\n [matMenuTriggerFor]=\"csvExportMenu\"\n [matTooltip]=\"t('list.exportAsCsv')\"\n >\n <mat-icon>download</mat-icon>\n </button>\n <!---->\n\n <!-- CSV Export Menu -->\n <mat-menu #csvExportMenu=\"matMenu\">\n @for (encoder of csvExportService.getAvailableEncoders(); track encoder.key) {\n <!-- Export with specific charset -->\n <p style=\"color: #333; font-size: 0.8rem; margin: 1rem 0.75rem 1rem 0.7rem\">\n CSV ({{ encoder.label }})\n </p>\n <button mat-menu-item (click)=\"exportAsCsv(encoder.key)\">\n <mat-icon>download</mat-icon>\n <span>{{ t('list.exportItems', { count: totalCount }) }}</span>\n </button>\n <!---->\n }\n </mat-menu>\n <!---->\n </div>\n</ng-template>\n<!---->\n\n<!-- List (Grid) -->\n<mtx-grid\n [data]=\"gridData\"\n [columns]=\"gridColumns\"\n [showToolbar]=\"true\"\n [toolbarTemplate]=\"toolbarTpl\"\n [length]=\"totalCount\"\n [loading]=\"isLoading\"\n [pageOnFront]=\"false\"\n [pageIndex]=\"query.page\"\n [pageSize]=\"query.perPage\"\n [pageSizeOptions]=\"listConfig?.pageSizes ?? [10, 25, 50, 100]\"\n columnMenuButtonType=\"icon\"\n columnMenuButtonClass=\"column-menu-button\"\n columnMenuButtonIcon=\"view_column\"\n (page)=\"onPageChange($event)\"\n></mtx-grid>\n<!---->\n\n<!-- Cell Template with Link -->\n<ng-template #cellTplWithLink let-row let-index=\"index\" let-col=\"colDef\">\n @if (col.link) {\n <a [href]=\"col.link(row)\">\n {{ row[col.field] }}\n </a>\n } @else if (col.routerLink) {\n <a [routerLink]=\"col.routerLink(row)\">\n {{ row[col.field] }}\n </a>\n } @else {\n {{ row[col.field] }}\n }\n</ng-template>\n<!---->\n", styles: [":host{display:flex;gap:1rem;padding:1rem;box-sizing:border-box}lib-list-category-selector{display:block;width:200px;background-color:#fcfcfc;border-radius:9px;padding:.5rem;box-sizing:border-box}lib-list-category-selector .category-list{max-height:300px;overflow-y:auto}::ng-deep .mtx-grid-toolbar{display:block;background-color:#fcfcfc;border-top-left-radius:9px;border-top-right-radius:9px;margin-bottom:1px}::ng-deep .mtx-grid-toolbar .custom-toolbar{display:flex;align-items:center;justify-content:space-between;height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title{font-size:1rem;line-height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a{color:var(--mat-theme-primary)}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a:hover{text-decoration:underline}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title .list-title-separator{color:#aaa;vertical-align:middle;margin:auto .2rem 4px}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button{color:var(--mat-sys-on-primary-container);min-width:32px;padding:0;vertical-align:middle}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button mat-icon{vertical-align:middle;margin-bottom:3px}::ng-deep .mtx-grid-toolbar .custom-toolbar .create-item-button{text-decoration:none!important}::ng-deep .mtx-grid-toolbar .custom-toolbar .search-keyword{width:15rem;--mat-form-field-container-height: 18.5px;--mat-form-field-container-text-line-height: 18.5px;--mat-form-field-container-vertical-padding: 8.5px;--mat-form-field-outlined-container-shape: 28px;--mat-form-field-subscript-text-line-height: 0px}::ng-deep .mtx-grid-toolbar .custom-toolbar button{color:var(--mat-sys-on-primary-container)}::ng-deep .mtx-grid-toolbar ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mtx-grid-toolbar ::ng-deep mtx-grid-column-menu button[mat-icon-button]{color:var(--mat-sys-on-primary-container);margin-right:.5rem}::ng-deep .mtx-grid-main{background-color:#fcfcfc}table{width:100%}::ng-deep table thead,::ng-deep table tbody{background-color:#fcfcfc!important}::ng-deep .mtx-grid-footer,::ng-deep .mat-mdc-paginator{display:block;background-color:#fcfcfc!important;border-bottom-left-radius:9px!important;border-bottom-right-radius:9px!important}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MtxGridModule }, { kind: "component", type: i2$2.MtxGrid, selector: "mtx-grid", inputs: ["displayedColumns", "columns", "data", "length", "loading", "trackBy", "columnResizable", "emptyValuePlaceholder", "pageOnFront", "showPaginator", "pageDisabled", "showFirstLastButtons", "pageIndex", "pageSize", "pageSizeOptions", "hidePageSize", "paginationTemplate", "sortOnFront", "sortActive", "sortDirection", "sortDisableClear", "sortDisabled", "sortStart", "rowHover", "rowStriped", "expandable", "expansionTemplate", "multiSelectable", "multiSelectionWithClick", "rowSelectable", "hideRowSelectionCheckbox", "disableRowClickSelection", "rowSelectionFormatter", "rowClassFormatter", "rowSelected", "cellSelectable", "showToolbar", "toolbarTitle", "toolbarTemplate", "columnHideable", "columnHideableChecked", "columnSortable", "columnPinnable", "columnPinOptions", "showColumnMenuButton", "columnMenuButtonText", "columnMenuButtonType", "columnMenuButtonColor", "columnMenuButtonClass", "columnMenuButtonIcon", "columnMenuButtonFontIcon", "columnMenuButtonSvgIcon", "showColumnMenuHeader", "columnMenuHeaderText", "columnMenuHeaderTemplate", "showColumnMenuFooter", "columnMenuFooterText", "columnMenuFooterTemplate", "noResultText", "noResultTemplate", "headerTemplate", "headerExtraTemplate", "cellTemplate", "useContentRowTemplate", "useContentHeaderRowTemplate", "useContentFooterRowTemplate", "showSummary", "summaryTemplate", "showSidebar", "sidebarTemplate", "showStatusbar", "statusbarTemplate"], outputs: ["page", "sortChange", "rowClick", "rowContextMenu", "expansionChange", "rowSelectedChange", "cellSelectedChange", "columnChange"], exportAs: ["mtxGrid"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: ListCategorySelector, selector: "lib-list-category-selector", inputs: ["config", "selectedCategory"], outputs: ["selectedCategoryChange"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
852
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: NgxThinAdminList, isStandalone: true, selector: "ngx-thin-admin-list", inputs: { listConfig: "listConfig", categorySelectorConfig: "categorySelectorConfig", itemDeleterConfig: "itemDeleterConfig", listColumns: "listColumns", query: "query" }, viewQueries: [{ propertyName: "cellTplWithLink", first: true, predicate: ["cellTplWithLink"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Category Selector -->\n@if (categorySelectorConfig) {\n <lib-list-category-selector\n [config]=\"categorySelectorConfig\"\n [(selectedCategory)]=\"selectedCategory\"\n (selectedCategoryChange)=\"onSelectedCategoryChange($event)\"\n ></lib-list-category-selector>\n}\n<!---->\n\n<!-- Toolbar Template -->\n<ng-template #toolbarTpl>\n <div class=\"custom-toolbar\">\n <!-- List Title -->\n <span class=\"list-title\">\n @if (listConfig?.title; as listTitle) {\n @if (query.keyword || query.categoryId) {\n <!-- Title (with link for reset filter) -->\n <a\n href=\"javascript:void(0)\"\n (click)=\"query.keyword = ''; query.categoryId = undefined; this.fetchList()\"\n [matTooltip]=\"t('list.clearFilters')\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n {{ t('list.defaultTitle') }}\n <!---->\n }\n\n @if (query.categoryId && selectedCategory?.[0]; as categoryLabel) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Category -->\n {{ categoryLabel.label }}\n <!---->\n }\n\n @if (query.keyword) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Keyword -->\n \"{{ query.keyword }}\"\n <!---->\n }\n </span>\n <!---->\n\n @if (query.keyword || query.categoryId) {\n <span style=\"width: 8px\"></span>\n <!-- Clear Filters Button -->\n <button\n mat-icon-button\n class=\"clear-filters-button\"\n [matTooltip]=\"t('list.clearFilters')\"\n (click)=\"clearFilters()\"\n >\n <mat-icon>filter_alt_off</mat-icon>\n </button>\n <!---->\n }\n\n <span style=\"flex: 1\"></span>\n\n <!-- Create Button -->\n @if (listConfig?.createButton; as createBtn) {\n @if ($any(createBtn).routerLink; as routerLinkUrl) {\n <!-- Create Button with Router Link -->\n <a\n [routerLink]=\"routerLinkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).link; as linkUrl) {\n <!-- Create Button with Link -->\n <a\n [href]=\"linkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).click; as handler) {\n <!-- Create Button with Handler -->\n <button\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </button>\n }\n }\n <!---->\n\n <span style=\"width: 30px\"></span>\n\n <!-- Search Field -->\n <mat-form-field class=\"search-keyword xs-input\" appearance=\"outline\">\n <mat-icon matPrefix>search</mat-icon>\n <input\n matInput\n [placeholder]=\"\n selectedCategory?.[0]?.label\n ? t('list.searchInCategoryPlaceholder', { category: selectedCategory?.[0]?.label })\n : t('list.searchDefaultPlaceholder')\n \"\n [(ngModel)]=\"query.keyword\"\n (keyup)=\"onKeywordInput()\"\n style=\"padding-top: 3px\"\n />\n\n <!-- Search clear button -->\n <button\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"t('list.clearSearchKeyword')\"\n [matTooltip]=\"t('list.clearSearchKeyword')\"\n (click)=\"query.keyword = ''; this.fetchList()\"\n [style.visibility]=\"query.keyword ? 'visible' : 'hidden'\"\n >\n <mat-icon>highlight_off</mat-icon>\n </button>\n <!---->\n </mat-form-field>\n <!---->\n\n <span style=\"width: 8px\"></span>\n\n <!-- Refresh Button -->\n <button mat-icon-button [matTooltip]=\"t('list.refresh')\" (click)=\"fetchList()\">\n <mat-icon>refresh</mat-icon>\n </button>\n <!---->\n\n <span style=\"width: 5px\"></span>\n\n <!-- CSV Export Button -->\n <button\n mat-icon-button\n [matMenuTriggerFor]=\"csvExportMenu\"\n [matTooltip]=\"t('list.exportAsCsv')\"\n >\n <mat-icon>download</mat-icon>\n </button>\n <!---->\n\n <!-- CSV Export Menu -->\n <mat-menu #csvExportMenu=\"matMenu\">\n @for (encoder of csvExportService.getAvailableEncoders(); track encoder.key) {\n <!-- Export with specific charset -->\n <p style=\"color: #333; font-size: 0.8rem; margin: 1rem 0.75rem 1rem 0.7rem\">\n CSV ({{ encoder.label }})\n </p>\n <button mat-menu-item (click)=\"exportAsCsv(encoder.key)\">\n <mat-icon>download</mat-icon>\n <span>{{ t('list.exportItems', { count: totalCount }) }}</span>\n </button>\n <!---->\n }\n </mat-menu>\n <!---->\n </div>\n</ng-template>\n<!---->\n\n<!-- List (Grid) -->\n<mtx-grid\n [data]=\"gridData\"\n [columns]=\"gridColumns\"\n [showToolbar]=\"true\"\n [toolbarTemplate]=\"toolbarTpl\"\n [length]=\"totalCount\"\n [loading]=\"isLoading\"\n [pageOnFront]=\"false\"\n [pageIndex]=\"query.page\"\n [pageSize]=\"query.perPage\"\n [pageSizeOptions]=\"listConfig?.pageSizes ?? [10, 25, 50, 100]\"\n columnMenuButtonType=\"icon\"\n columnMenuButtonClass=\"column-menu-button\"\n columnMenuButtonIcon=\"view_column\"\n (page)=\"onPageChange($event)\"\n></mtx-grid>\n<!---->\n\n<!-- Cell Template with Link -->\n<ng-template #cellTplWithLink let-row let-index=\"index\" let-col=\"colDef\">\n @if (col.link) {\n <a [href]=\"col.link(row)\">\n {{ row[col.field] }}\n </a>\n } @else if (col.routerLink) {\n <a [routerLink]=\"col.routerLink(row)\">\n {{ row[col.field] }}\n </a>\n } @else {\n {{ row[col.field] }}\n }\n</ng-template>\n<!---->\n", styles: [":host{display:flex;gap:1rem;padding:1rem;box-sizing:border-box}lib-list-category-selector{display:block;width:200px;background-color:#fcfcfc;border-radius:9px;padding:.5rem;box-sizing:border-box}lib-list-category-selector .category-list{max-height:300px;overflow-y:auto}::ng-deep .mtx-grid-toolbar{display:block;background-color:#fcfcfc;border-top-left-radius:9px;border-top-right-radius:9px;margin-bottom:1px}::ng-deep .mtx-grid-toolbar .custom-toolbar{display:flex;align-items:center;justify-content:space-between;height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title{font-size:1rem;line-height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a{color:var(--mat-theme-primary)}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a:hover{text-decoration:underline}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title .list-title-separator{color:#aaa;vertical-align:middle;margin:auto .2rem 4px}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button{color:var(--mat-sys-on-primary-container);min-width:32px;padding:0;vertical-align:middle}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button mat-icon{vertical-align:middle;margin-bottom:3px}::ng-deep .mtx-grid-toolbar .custom-toolbar .create-item-button{text-decoration:none!important}::ng-deep .mtx-grid-toolbar .custom-toolbar .search-keyword{width:15rem;--mat-form-field-container-height: 18.5px;--mat-form-field-container-text-line-height: 18.5px;--mat-form-field-container-vertical-padding: 8.5px;--mat-form-field-outlined-container-shape: 28px;--mat-form-field-subscript-text-line-height: 0px}::ng-deep .mtx-grid-toolbar .custom-toolbar button{color:var(--mat-sys-on-primary-container)}::ng-deep .mtx-grid-toolbar ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mtx-grid-toolbar ::ng-deep mtx-grid-column-menu button[mat-icon-button]{color:var(--mat-sys-on-primary-container);margin-right:.5rem}::ng-deep .mtx-grid-main{background-color:#fcfcfc}table{width:100%}::ng-deep table thead,::ng-deep table tbody{background-color:#fcfcfc!important}::ng-deep .mtx-grid-footer,::ng-deep .mat-mdc-paginator{display:block;background-color:#fcfcfc!important;border-bottom-left-radius:9px!important;border-bottom-right-radius:9px!important}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MtxGridModule }, { kind: "component", type: i2$2.MtxGrid, selector: "mtx-grid", inputs: ["displayedColumns", "columns", "data", "length", "loading", "trackBy", "columnResizable", "emptyValuePlaceholder", "pageOnFront", "showPaginator", "pageDisabled", "showFirstLastButtons", "pageIndex", "pageSize", "pageSizeOptions", "hidePageSize", "paginationTemplate", "sortOnFront", "sortActive", "sortDirection", "sortDisableClear", "sortDisabled", "sortStart", "rowHover", "rowStriped", "expandable", "expansionTemplate", "multiSelectable", "multiSelectionWithClick", "rowSelectable", "hideRowSelectionCheckbox", "disableRowClickSelection", "rowSelectionFormatter", "rowClassFormatter", "rowSelected", "cellSelectable", "showToolbar", "toolbarTitle", "toolbarTemplate", "columnHideable", "columnHideableChecked", "columnSortable", "columnPinnable", "columnPinOptions", "showColumnMenuButton", "columnMenuButtonText", "columnMenuButtonType", "columnMenuButtonColor", "columnMenuButtonClass", "columnMenuButtonIcon", "columnMenuButtonFontIcon", "columnMenuButtonSvgIcon", "showColumnMenuHeader", "columnMenuHeaderText", "columnMenuHeaderTemplate", "showColumnMenuFooter", "columnMenuFooterText", "columnMenuFooterTemplate", "noResultText", "noResultTemplate", "headerTemplate", "headerExtraTemplate", "cellTemplate", "useContentRowTemplate", "useContentHeaderRowTemplate", "useContentFooterRowTemplate", "showSummary", "summaryTemplate", "showSidebar", "sidebarTemplate", "showStatusbar", "statusbarTemplate"], outputs: ["page", "sortChange", "rowClick", "rowContextMenu", "expansionChange", "rowSelectedChange", "cellSelectedChange", "columnChange"], exportAs: ["mtxGrid"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: ListCategorySelector, selector: "lib-list-category-selector", inputs: ["config", "selectedCategory"], outputs: ["selectedCategoryChange"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] });
849
853
  }
850
854
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminList, decorators: [{
851
855
  type: Component,
@@ -865,7 +869,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
865
869
  MatMenuItem,
866
870
  MatMenuTrigger,
867
871
  RouterLink,
868
- ], template: "<!-- Category Selector -->\n@if (categorySelectorConfig) {\n <lib-list-category-selector\n [config]=\"categorySelectorConfig\"\n [(selectedCategory)]=\"selectedCategory\"\n (selectedCategoryChange)=\"onSelectedCategoryChange($event)\"\n ></lib-list-category-selector>\n}\n<!---->\n\n<!-- Toolbar Template -->\n<ng-template #toolbarTpl>\n <div class=\"custom-toolbar\">\n <!-- List Title -->\n <span class=\"list-title\">\n @if (listConfig?.title; as listTitle) {\n @if (query.keyword || query.categoryId) {\n <!-- Title (with link for reset filter) -->\n <a\n href=\"javascript:void(0)\"\n (click)=\"query.keyword = ''; query.categoryId = undefined; this.fetchList()\"\n [matTooltip]=\"t('list.clearFilters')\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n {{ t('list.defaultTitle') }}\n <!---->\n }\n\n @if (query.categoryId && selectedCategory?.[0]; as categoryLabel) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Category -->\n {{ categoryLabel.label }}\n <!---->\n }\n\n @if (query.keyword) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Keyword -->\n \"{{ query.keyword }}\"\n <!---->\n }\n </span>\n <!---->\n\n @if (query.keyword || query.categoryId) {\n <span style=\"width: 8px\"></span>\n <!-- Clear Filters Button -->\n <button\n mat-icon-button\n class=\"clear-filters-button\"\n [matTooltip]=\"t('list.clearFilters')\"\n (click)=\"clearFilters()\"\n >\n <mat-icon>filter_alt_off</mat-icon>\n </button>\n <!---->\n }\n\n <span style=\"flex: 1\"></span>\n\n <!-- Create Button -->\n @if (listConfig?.createButton; as createBtn) {\n @if ($any(createBtn).routerLink; as routerLinkUrl) {\n <!-- Create Button with Router Link -->\n <a\n [routerLink]=\"routerLinkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).link; as linkUrl) {\n <!-- Create Button with Link -->\n <a\n [href]=\"linkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).click; as handler) {\n <!-- Create Button with Handler -->\n <button\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </button>\n }\n }\n <!---->\n\n <span style=\"width: 30px\"></span>\n\n <!-- Search Field -->\n <mat-form-field class=\"search-keyword xs-input\" appearance=\"outline\">\n <mat-icon matPrefix>search</mat-icon>\n <input\n matInput\n [placeholder]=\"\n selectedCategory?.[0]?.label\n ? t('list.searchInCategoryPlaceholder', { category: selectedCategory?.[0]?.label })\n : t('list.searchDefaultPlaceholder')\n \"\n [(ngModel)]=\"query.keyword\"\n (keyup)=\"onKeywordInput()\"\n style=\"padding-top: 3px\"\n />\n\n <!-- Search clear button -->\n <button\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"t('list.clearSearchKeyword')\"\n [matTooltip]=\"t('list.clearSearchKeyword')\"\n (click)=\"query.keyword = ''; this.fetchList()\"\n [style.visibility]=\"query.keyword ? 'visible' : 'hidden'\"\n >\n <mat-icon>highlight_off</mat-icon>\n </button>\n <!---->\n </mat-form-field>\n <!---->\n\n <span style=\"width: 8px\"></span>\n\n <!-- Refresh Button -->\n <button mat-icon-button [matTooltip]=\"t('list.refresh')\" (click)=\"fetchList()\">\n <mat-icon>refresh</mat-icon>\n </button>\n <!---->\n\n <span style=\"width: 5px\"></span>\n\n <!-- CSV Export Button -->\n <button\n mat-icon-button\n [matMenuTriggerFor]=\"csvExportMenu\"\n [matTooltip]=\"t('list.exportAsCsv')\"\n >\n <mat-icon>download</mat-icon>\n </button>\n <!---->\n\n <!-- CSV Export Menu -->\n <mat-menu #csvExportMenu=\"matMenu\">\n @for (encoder of csvExportService.getAvailableEncoders(); track encoder.key) {\n <!-- Export with specific charset -->\n <p style=\"color: #333; font-size: 0.8rem; margin: 1rem 0.75rem 1rem 0.7rem\">\n CSV ({{ encoder.label }})\n </p>\n <button mat-menu-item (click)=\"exportAsCsv(encoder.key)\">\n <mat-icon>download</mat-icon>\n <span>{{ t('list.exportItems', { count: totalCount }) }}</span>\n </button>\n <!---->\n }\n </mat-menu>\n <!---->\n </div>\n</ng-template>\n<!---->\n\n<!-- List (Grid) -->\n<mtx-grid\n [data]=\"gridData\"\n [columns]=\"gridColumns\"\n [showToolbar]=\"true\"\n [toolbarTemplate]=\"toolbarTpl\"\n [length]=\"totalCount\"\n [loading]=\"isLoading\"\n [pageOnFront]=\"false\"\n [pageIndex]=\"query.page\"\n [pageSize]=\"query.perPage\"\n [pageSizeOptions]=\"listConfig?.pageSizes ?? [10, 25, 50, 100]\"\n columnMenuButtonType=\"icon\"\n columnMenuButtonClass=\"column-menu-button\"\n columnMenuButtonIcon=\"view_column\"\n (page)=\"onPageChange($event)\"\n></mtx-grid>\n<!---->\n\n<!-- Cell Template with Link -->\n<ng-template #cellTplWithLink let-row let-index=\"index\" let-col=\"colDef\">\n @if (col.link) {\n <a [href]=\"col.link(row)\">\n {{ row[col.field] }}\n </a>\n } @else if (col.routerLink) {\n <a [routerLink]=\"col.routerLink(row)\">\n {{ row[col.field] }}\n </a>\n } @else {\n {{ row[col.field] }}\n }\n</ng-template>\n<!---->\n", styles: [":host{display:flex;gap:1rem;padding:1rem;box-sizing:border-box}lib-list-category-selector{display:block;width:200px;background-color:#fcfcfc;border-radius:9px;padding:.5rem;box-sizing:border-box}lib-list-category-selector .category-list{max-height:300px;overflow-y:auto}::ng-deep .mtx-grid-toolbar{display:block;background-color:#fcfcfc;border-top-left-radius:9px;border-top-right-radius:9px;margin-bottom:1px}::ng-deep .mtx-grid-toolbar .custom-toolbar{display:flex;align-items:center;justify-content:space-between;height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title{font-size:1rem;line-height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a{color:var(--mat-theme-primary)}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a:hover{text-decoration:underline}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title .list-title-separator{color:#aaa;vertical-align:middle;margin:auto .2rem 4px}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button{color:var(--mat-sys-on-primary-container);min-width:32px;padding:0;vertical-align:middle}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button mat-icon{vertical-align:middle;margin-bottom:3px}::ng-deep .mtx-grid-toolbar .custom-toolbar .create-item-button{text-decoration:none!important}::ng-deep .mtx-grid-toolbar .custom-toolbar .search-keyword{width:15rem;--mat-form-field-container-height: 18.5px;--mat-form-field-container-text-line-height: 18.5px;--mat-form-field-container-vertical-padding: 8.5px;--mat-form-field-outlined-container-shape: 28px;--mat-form-field-subscript-text-line-height: 0px}::ng-deep .mtx-grid-toolbar .custom-toolbar button{color:var(--mat-sys-on-primary-container)}::ng-deep .mtx-grid-toolbar ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mtx-grid-toolbar ::ng-deep mtx-grid-column-menu button[mat-icon-button]{color:var(--mat-sys-on-primary-container);margin-right:.5rem}::ng-deep .mtx-grid-main{background-color:#fcfcfc}table{width:100%}::ng-deep table thead,::ng-deep table tbody{background-color:#fcfcfc!important}::ng-deep .mtx-grid-footer,::ng-deep .mat-mdc-paginator{display:block;background-color:#fcfcfc!important;border-bottom-left-radius:9px!important;border-bottom-right-radius:9px!important}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"] }]
872
+ ], template: "<!-- Category Selector -->\n@if (categorySelectorConfig) {\n <lib-list-category-selector\n [config]=\"categorySelectorConfig\"\n [(selectedCategory)]=\"selectedCategory\"\n (selectedCategoryChange)=\"onSelectedCategoryChange($event)\"\n ></lib-list-category-selector>\n}\n<!---->\n\n<!-- Toolbar Template -->\n<ng-template #toolbarTpl>\n <div class=\"custom-toolbar\">\n <!-- List Title -->\n <span class=\"list-title\">\n @if (listConfig?.title; as listTitle) {\n @if (query.keyword || query.categoryId) {\n <!-- Title (with link for reset filter) -->\n <a\n href=\"javascript:void(0)\"\n (click)=\"query.keyword = ''; query.categoryId = undefined; this.fetchList()\"\n [matTooltip]=\"t('list.clearFilters')\"\n >{{ listTitle }}</a\n >\n <!---->\n } @else {\n <!-- Title -->\n {{ listTitle }}\n <!---->\n }\n } @else {\n <!-- Default Title -->\n {{ t('list.defaultTitle') }}\n <!---->\n }\n\n @if (query.categoryId && selectedCategory?.[0]; as categoryLabel) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Category -->\n {{ categoryLabel.label }}\n <!---->\n }\n\n @if (query.keyword) {\n <span class=\"material-icons list-title-separator\"> keyboard_arrow_right </span>\n <!-- Keyword -->\n \"{{ query.keyword }}\"\n <!---->\n }\n </span>\n <!---->\n\n @if (query.keyword || query.categoryId) {\n <span style=\"width: 8px\"></span>\n <!-- Clear Filters Button -->\n <button\n mat-icon-button\n class=\"clear-filters-button\"\n [matTooltip]=\"t('list.clearFilters')\"\n (click)=\"clearFilters()\"\n >\n <mat-icon>filter_alt_off</mat-icon>\n </button>\n <!---->\n }\n\n <span style=\"flex: 1\"></span>\n\n <!-- Create Button -->\n @if (listConfig?.createButton; as createBtn) {\n @if ($any(createBtn).routerLink; as routerLinkUrl) {\n <!-- Create Button with Router Link -->\n <a\n [routerLink]=\"routerLinkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).link; as linkUrl) {\n <!-- Create Button with Link -->\n <a\n [href]=\"linkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).click; as handler) {\n <!-- Create Button with Handler -->\n <button\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </button>\n }\n }\n <!---->\n\n <span style=\"width: 30px\"></span>\n\n <!-- Search Field -->\n <mat-form-field class=\"search-keyword xs-input\" appearance=\"outline\">\n <mat-icon matPrefix>search</mat-icon>\n <input\n matInput\n [placeholder]=\"\n selectedCategory?.[0]?.label\n ? t('list.searchInCategoryPlaceholder', { category: selectedCategory?.[0]?.label })\n : t('list.searchDefaultPlaceholder')\n \"\n [(ngModel)]=\"query.keyword\"\n (keyup)=\"onKeywordInput()\"\n style=\"padding-top: 3px\"\n />\n\n <!-- Search clear button -->\n <button\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"t('list.clearSearchKeyword')\"\n [matTooltip]=\"t('list.clearSearchKeyword')\"\n (click)=\"query.keyword = ''; this.fetchList()\"\n [style.visibility]=\"query.keyword ? 'visible' : 'hidden'\"\n >\n <mat-icon>highlight_off</mat-icon>\n </button>\n <!---->\n </mat-form-field>\n <!---->\n\n <span style=\"width: 8px\"></span>\n\n <!-- Refresh Button -->\n <button mat-icon-button [matTooltip]=\"t('list.refresh')\" (click)=\"fetchList()\">\n <mat-icon>refresh</mat-icon>\n </button>\n <!---->\n\n <span style=\"width: 5px\"></span>\n\n <!-- CSV Export Button -->\n <button\n mat-icon-button\n [matMenuTriggerFor]=\"csvExportMenu\"\n [matTooltip]=\"t('list.exportAsCsv')\"\n >\n <mat-icon>download</mat-icon>\n </button>\n <!---->\n\n <!-- CSV Export Menu -->\n <mat-menu #csvExportMenu=\"matMenu\">\n @for (encoder of csvExportService.getAvailableEncoders(); track encoder.key) {\n <!-- Export with specific charset -->\n <p style=\"color: #333; font-size: 0.8rem; margin: 1rem 0.75rem 1rem 0.7rem\">\n CSV ({{ encoder.label }})\n </p>\n <button mat-menu-item (click)=\"exportAsCsv(encoder.key)\">\n <mat-icon>download</mat-icon>\n <span>{{ t('list.exportItems', { count: totalCount }) }}</span>\n </button>\n <!---->\n }\n </mat-menu>\n <!---->\n </div>\n</ng-template>\n<!---->\n\n<!-- List (Grid) -->\n<mtx-grid\n [data]=\"gridData\"\n [columns]=\"gridColumns\"\n [showToolbar]=\"true\"\n [toolbarTemplate]=\"toolbarTpl\"\n [length]=\"totalCount\"\n [loading]=\"isLoading\"\n [pageOnFront]=\"false\"\n [pageIndex]=\"query.page\"\n [pageSize]=\"query.perPage\"\n [pageSizeOptions]=\"listConfig?.pageSizes ?? [10, 25, 50, 100]\"\n columnMenuButtonType=\"icon\"\n columnMenuButtonClass=\"column-menu-button\"\n columnMenuButtonIcon=\"view_column\"\n (page)=\"onPageChange($event)\"\n></mtx-grid>\n<!---->\n\n<!-- Cell Template with Link -->\n<ng-template #cellTplWithLink let-row let-index=\"index\" let-col=\"colDef\">\n @if (col.link) {\n <a [href]=\"col.link(row)\">\n {{ row[col.field] }}\n </a>\n } @else if (col.routerLink) {\n <a [routerLink]=\"col.routerLink(row)\">\n {{ row[col.field] }}\n </a>\n } @else {\n {{ row[col.field] }}\n }\n</ng-template>\n<!---->\n", styles: [":host{display:flex;gap:1rem;padding:1rem;box-sizing:border-box}lib-list-category-selector{display:block;width:200px;background-color:#fcfcfc;border-radius:9px;padding:.5rem;box-sizing:border-box}lib-list-category-selector .category-list{max-height:300px;overflow-y:auto}::ng-deep .mtx-grid-toolbar{display:block;background-color:#fcfcfc;border-top-left-radius:9px;border-top-right-radius:9px;margin-bottom:1px}::ng-deep .mtx-grid-toolbar .custom-toolbar{display:flex;align-items:center;justify-content:space-between;height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title{font-size:1rem;line-height:37px}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a{color:var(--mat-theme-primary)}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title a:hover{text-decoration:underline}::ng-deep .mtx-grid-toolbar .custom-toolbar .list-title .list-title-separator{color:#aaa;vertical-align:middle;margin:auto .2rem 4px}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button{color:var(--mat-sys-on-primary-container);min-width:32px;padding:0;vertical-align:middle}::ng-deep .mtx-grid-toolbar .custom-toolbar .clear-filters-button mat-icon{vertical-align:middle;margin-bottom:3px}::ng-deep .mtx-grid-toolbar .custom-toolbar .create-item-button{text-decoration:none!important}::ng-deep .mtx-grid-toolbar .custom-toolbar .search-keyword{width:15rem;--mat-form-field-container-height: 18.5px;--mat-form-field-container-text-line-height: 18.5px;--mat-form-field-container-vertical-padding: 8.5px;--mat-form-field-outlined-container-shape: 28px;--mat-form-field-subscript-text-line-height: 0px}::ng-deep .mtx-grid-toolbar .custom-toolbar button{color:var(--mat-sys-on-primary-container)}::ng-deep .mtx-grid-toolbar ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mtx-grid-toolbar ::ng-deep mtx-grid-column-menu button[mat-icon-button]{color:var(--mat-sys-on-primary-container);margin-right:.5rem}::ng-deep .mtx-grid-main{background-color:#fcfcfc}table{width:100%}::ng-deep table thead,::ng-deep table tbody{background-color:#fcfcfc!important}::ng-deep .mtx-grid-footer,::ng-deep .mat-mdc-paginator{display:block;background-color:#fcfcfc!important;border-bottom-left-radius:9px!important;border-bottom-right-radius:9px!important}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"] }]
869
873
  }], propDecorators: { listConfig: [{
870
874
  type: Input
871
875
  }], categorySelectorConfig: [{
@@ -1091,6 +1095,10 @@ class NgxThinAdminEditor {
1091
1095
  form = new FormGroup({});
1092
1096
  data = {};
1093
1097
  formData = {};
1098
+ /**
1099
+ * For history back
1100
+ */
1101
+ windowHistory = window.history;
1094
1102
  /**
1095
1103
  * Services
1096
1104
  */
@@ -1248,7 +1256,9 @@ class NgxThinAdminEditor {
1248
1256
  }
1249
1257
  // Get the label and ID to query in the confirmation dialog
1250
1258
  const id = this.itemId;
1251
- const label = this.editorConfig?.labelFieldKey ? this.data[this.editorConfig.labelFieldKey] : id;
1259
+ const label = this.editorConfig?.labelFieldKey
1260
+ ? this.data[this.editorConfig.labelFieldKey]
1261
+ : id;
1252
1262
  const itemType = this.editorItemType;
1253
1263
  // Open the confirmation dialog
1254
1264
  const dialogRef = this.dialog.open(ConfirmDialog, {
@@ -1315,7 +1325,7 @@ class NgxThinAdminEditor {
1315
1325
  subscriptSizing: 'dynamic',
1316
1326
  },
1317
1327
  },
1318
- ], 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') }} &nbsp; <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') }} &nbsp; <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n </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 <!-- Button Area -->\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-top: 0.5rem\">\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n", styles: [":host{max-width:600px;display:block;margin:0 auto}mat-card{padding:2rem}mat-card-header h3{font-size:1.2rem;font-weight:400}mat-card-header .editor-item-label{margin-left:1rem}mat-card-header .editor-header-sub{color:#555;margin-left:.85rem;font-size:.9rem;font-style:italic}form{margin-top:2rem}form ::ng-deep .mat-mdc-form-field-subscript-wrapper{margin-bottom:14px!important}\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" }] });
1328
+ ], usesOnChanges: true, ngImport: i0, template: "<mat-card>\n <mat-card-header style=\"position: relative\">\n <!-- Back button -->\n @if (editorConfig?.backButton) {\n @if ($any(editorConfig?.backButton).historyBack && windowHistory.length > 1) {\n <button mat-button (click)=\"windowHistory.back()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n } @else if ($any(editorConfig?.backButton).routerLink; as backButtonLink) {\n <a [routerLink]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).link; as backButtonLink) {\n <a [href]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).click; as handler) {\n <button mat-button (click)=\"handler()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n }\n }\n <!---->\n\n <!-- Editor title -->\n <h3 style=\"margin: 0\" [style.margin-top]=\"editorConfig?.backButton ? '1rem' : '0'\">\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n {{ t('common.edit') }} &nbsp; <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') }} &nbsp; <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n <!---->\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\" style=\"margin-top: 1rem\"></mat-progress-bar>\n }\n\n @if (!isLoading) {\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <formly-form\n [form]=\"form\"\n [fields]=\"$any(editorFields) ?? []\"\n [model]=\"formData\"\n ></formly-form>\n\n <!-- Button Area -->\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-top: 0.5rem;\n \"\n >\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n", styles: [":host{max-width:600px;display:block;margin:0 auto}mat-card{padding:2rem}mat-card-header h3{font-size:1.2rem;font-weight:400}mat-card-header .editor-item-label{margin-left:1rem}mat-card-header .editor-header-sub{color:#555;margin-left:.85rem;font-size:.9rem;font-style:italic}form{margin-top:2rem}form ::ng-deep .mat-mdc-form-field-subscript-wrapper{margin-bottom:14px!important}.back-link{display:flex;position:absolute;top:-1.5rem;left:-1rem;align-items:center;gap:.3rem;font-size:.8rem}.back-link mat-icon{height:.8rem;width:.8rem;font-size:.8rem}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: 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: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "component", type: MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }] });
1319
1329
  }
1320
1330
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: NgxThinAdminEditor, decorators: [{
1321
1331
  type: Component,
@@ -1323,6 +1333,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
1323
1333
  ReactiveFormsModule,
1324
1334
  FormlyForm,
1325
1335
  MatButton,
1336
+ MatIconButton,
1337
+ MatIcon,
1338
+ MatTooltip,
1339
+ RouterLink,
1326
1340
  MatProgressBar,
1327
1341
  MatCard,
1328
1342
  MatCardHeader,
@@ -1353,7 +1367,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
1353
1367
  subscriptSizing: 'dynamic',
1354
1368
  },
1355
1369
  },
1356
- ], 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') }} &nbsp; <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') }} &nbsp; <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n </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 <!-- Button Area -->\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-top: 0.5rem\">\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n", styles: [":host{max-width:600px;display:block;margin:0 auto}mat-card{padding:2rem}mat-card-header h3{font-size:1.2rem;font-weight:400}mat-card-header .editor-item-label{margin-left:1rem}mat-card-header .editor-header-sub{color:#555;margin-left:.85rem;font-size:.9rem;font-style:italic}form{margin-top:2rem}form ::ng-deep .mat-mdc-form-field-subscript-wrapper{margin-bottom:14px!important}\n"] }]
1370
+ ], template: "<mat-card>\n <mat-card-header style=\"position: relative\">\n <!-- Back button -->\n @if (editorConfig?.backButton) {\n @if ($any(editorConfig?.backButton).historyBack && windowHistory.length > 1) {\n <button mat-button (click)=\"windowHistory.back()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n } @else if ($any(editorConfig?.backButton).routerLink; as backButtonLink) {\n <a [routerLink]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).link; as backButtonLink) {\n <a [href]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).click; as handler) {\n <button mat-button (click)=\"handler()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n }\n }\n <!---->\n\n <!-- Editor title -->\n <h3 style=\"margin: 0\" [style.margin-top]=\"editorConfig?.backButton ? '1rem' : '0'\">\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n {{ t('common.edit') }} &nbsp; <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') }} &nbsp; <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n <!---->\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\" style=\"margin-top: 1rem\"></mat-progress-bar>\n }\n\n @if (!isLoading) {\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <formly-form\n [form]=\"form\"\n [fields]=\"$any(editorFields) ?? []\"\n [model]=\"formData\"\n ></formly-form>\n\n <!-- Button Area -->\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-top: 0.5rem;\n \"\n >\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n", styles: [":host{max-width:600px;display:block;margin:0 auto}mat-card{padding:2rem}mat-card-header h3{font-size:1.2rem;font-weight:400}mat-card-header .editor-item-label{margin-left:1rem}mat-card-header .editor-header-sub{color:#555;margin-left:.85rem;font-size:.9rem;font-style:italic}form{margin-top:2rem}form ::ng-deep .mat-mdc-form-field-subscript-wrapper{margin-bottom:14px!important}.back-link{display:flex;position:absolute;top:-1.5rem;left:-1rem;align-items:center;gap:.3rem;font-size:.8rem}.back-link mat-icon{height:.8rem;width:.8rem;font-size:.8rem}a,::ng-deep table a,::ng-deep table a:visited{color:var(--mat-sys-on-primary-container);text-decoration:none}a:hover,::ng-deep table a:hover,::ng-deep table a:visited:hover{text-decoration:underline}\n"] }]
1357
1371
  }], propDecorators: { editorConfig: [{
1358
1372
  type: Input
1359
1373
  }], editorFields: [{
@@ -1 +1 @@
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/shared/error-handler.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/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.titleForCreate'\n | 'editor.titleForEdit'\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 | 'category.successCreated'\n | 'category.successUpdated'\n | 'category.successDeleted'\n | 'item.defaultSingular'\n | 'item.deletionDialogTitle'\n | 'item.deletionDialogMessage'\n | 'item.errorFailedDelete'\n | 'item.successDeleted'\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.titleForCreate': 'Create {itemType}',\n 'editor.titleForEdit': 'Edit {itemType}',\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 {categoryType}',\n 'category.errorFailedUpdate': 'Failed to update {categoryType} \"{label}\"',\n 'category.errorFailedDelete': 'Failed to delete {categoryType} \"{label}\"',\n 'category.errorCouldNotSave': 'Could not save {categoryType}',\n 'category.successCreated': '{categoryType} \"{label}\" has been created successfully',\n 'category.successUpdated': '{categoryType} \"{label}\" has been updated successfully',\n 'category.successDeleted': '{categoryType} \"{label}\" has been deleted successfully',\n 'item.defaultSingular': 'Item',\n 'item.deletionDialogTitle': 'Delete {itemType}',\n 'item.deletionDialogMessage':\n 'Are you sure you want to delete \"{label}\" ({id})? This action cannot be undone.',\n 'item.errorFailedDelete': 'Failed to delete \"{label}\"',\n 'item.successDeleted': '\"{label}\" has been deleted successfully',\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.titleForCreate': '{itemType} の作成',\n 'editor.titleForEdit': '{itemType} の編集',\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': '{categoryType} を作成できませんでした',\n 'category.errorFailedUpdate': '{categoryType} \"{label}\" の更新に失敗しました',\n 'category.errorFailedDelete': '{categoryType} \"{label}\" の削除に失敗しました',\n 'category.errorCouldNotSave': '{categoryType} を保存できませんでした',\n 'category.successCreated': '{categoryType} \"{label}\" を作成しました',\n 'category.successUpdated': '{categoryType} \"{label}\" を更新しました',\n 'category.successDeleted': '{categoryType} \"{label}\" を削除しました',\n 'item.defaultSingular': '項目',\n 'item.deletionDialogTitle': '{itemType} の削除',\n 'item.deletionDialogMessage': '\"{label}\" ({id}) を削除しますか?この操作は元に戻せません。',\n 'item.errorFailedDelete': '\"{label}\" の削除に失敗しました',\n 'item.successDeleted': '\"{label}\" を削除しました',\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', { categoryType: this.config.singularLabel ?? this.t('category.defaultSingular') })}`,\n undefined,\n {\n duration: 3000,\n },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(\n this.t('category.successCreated', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: categoryLabel,\n }),\n undefined,\n {\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: ${\n e?.message ??\n this.t('category.errorFailedUpdate', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n })\n }`,\n undefined,\n {\n duration: 3000,\n },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(\n this.t('category.successUpdated', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n }),\n undefined,\n {\n duration: 3000,\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: ${\n e?.message ??\n this.t('category.errorFailedDelete', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n })\n }`,\n undefined,\n {\n duration: 3000,\n },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(\n this.t('category.successDeleted', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n }),\n undefined,\n {\n duration: 3000,\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: ${\n e?.message ??\n this.t('category.errorCouldNotSave', {\n categoryType: this.config!.singularLabel ?? this.t('category.defaultSingular'),\n })\n }`,\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: ${\n e?.message ??\n this.t('category.errorFailedDelete', {\n categoryType: this.config?.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n })\n }`,\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') }}&nbsp;\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 }}&nbsp;\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","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 {\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 { MatSnackBar } from '@angular/material/snack-bar';\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 NgxThinAdminItemDeleterConfig,\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';\nimport { MatDialog } from '@angular/material/dialog';\nimport { ConfirmDialog, ConfirmDialogData } from '../shared/confirm-dialog/confirm-dialog';\nimport { lastValueFrom } from 'rxjs';\nimport { getErrorMessage } from '../shared/error-handler';\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 * Config for item deleter (If provided, item deletion feature is enabled)\n * It works by calling openItemDeletionDialog(row) from the click handler of the column definition.\n */\n @Input()\n itemDeleterConfig?: NgxThinAdminItemDeleterConfig;\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 private snackbar = inject(MatSnackBar);\n csvExportService = inject(CsvExportService);\n private dialog = inject(MatDialog);\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 async openItemDeletionDialog(item: any) {\n if (!this.itemDeleterConfig?.deleter) {\n return;\n }\n\n // Get the label and ID to query in the confirmation dialog\n const idKey = this.listConfig?.idFieldKey;\n const labelKey = this.listConfig?.labelFieldKey;\n const id = idKey ? item[idKey] : (item.id ?? JSON.stringify(item));\n const label = labelKey ? item[labelKey] : id;\n const itemType = this.listConfig?.singularLabel || this.t('item.defaultSingular');\n\n // Open the confirmation dialog\n const dialogRef = this.dialog.open(ConfirmDialog, {\n width: '400px',\n data: {\n title: this.t('item.deletionDialogTitle', { itemType }),\n message: this.t('item.deletionDialogMessage', { label, id }),\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 // Execute delete process\n await this.deleteItem(id, label);\n }\n\n async deleteItem(id: string, label: string) {\n if (!this.itemDeleterConfig?.deleter) {\n return;\n }\n\n try {\n await this.itemDeleterConfig.deleter(id);\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(\n `Error: ${errorMessage || this.t('item.errorFailedDelete', { label })}`,\n undefined,\n { duration: 3000 },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(this.t('item.successDeleted', { label }), undefined, {\n duration: 3000,\n });\n\n // Refresh the list after deletion\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=\"create-item-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=\"create-item-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=\"create-item-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","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, NgxThinAdminItemDeleterConfig } 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';\nimport { MatDialog } from '@angular/material/dialog';\nimport { ConfirmDialog, ConfirmDialogData } from '../shared/confirm-dialog/confirm-dialog';\nimport { lastValueFrom } from 'rxjs';\nimport { Router } from '@angular/router';\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 * Config for item deleter\n */\n @Input()\n itemDeleterConfig?: NgxThinAdminItemDeleterConfig;\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 private dialog = inject(MatDialog);\n private router = inject(Router);\n\n t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string {\n return this.translate(key, params);\n }\n\n get editorItemType(): string {\n return this.editorConfig?.singularLabel || this.t('item.defaultSingular');\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 async openDeletionDialog() {\n if (!this.itemDeleterConfig?.deleter || this.itemId === undefined) {\n return;\n }\n\n // Get the label and ID to query in the confirmation dialog\n const id = this.itemId;\n const label = this.editorConfig?.labelFieldKey ? this.data[this.editorConfig.labelFieldKey] : id;\n const itemType = this.editorItemType;\n\n // Open the confirmation dialog\n const dialogRef = this.dialog.open(ConfirmDialog, {\n width: '400px',\n data: {\n title: this.t('item.deletionDialogTitle', { itemType }),\n message: this.t('item.deletionDialogMessage', { label, id }),\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 // Execute delete process\n await this.deleteItem(id, label);\n }\n\n async deleteItem(id: string, label: string) {\n if (!this.itemDeleterConfig?.deleter) {\n return;\n }\n\n try {\n await this.itemDeleterConfig.deleter(id);\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(\n `Error: ${errorMessage || this.t('item.errorFailedDelete', { label })}`,\n undefined,\n { duration: 3000 },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(this.t('item.successDeleted', { label }), undefined, {\n duration: 3000,\n });\n\n // Subsequence routing\n if (this.itemDeleterConfig.afterDeleteNavigateTo) {\n this.router.navigate([this.itemDeleterConfig.afterDeleteNavigateTo]);\n }\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') }} &nbsp; <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') }} &nbsp; <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n </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 <!-- Button Area -->\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-top: 0.5rem\">\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n","/*\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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"}
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/shared/error-handler.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/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 | 'common.back'\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.titleForCreate'\n | 'editor.titleForEdit'\n | 'editor.idLabel'\n | 'editor.saveChanges'\n | 'editor.errorInvalidInput'\n | 'editor.errorNoSaver'\n | 'editor.successSaved'\n | 'editor.backToList'\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 | 'category.successCreated'\n | 'category.successUpdated'\n | 'category.successDeleted'\n | 'item.defaultSingular'\n | 'item.deletionDialogTitle'\n | 'item.deletionDialogMessage'\n | 'item.errorFailedDelete'\n | 'item.successDeleted'\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 'common.back': 'Back',\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.titleForCreate': 'Create {itemType}',\n 'editor.titleForEdit': 'Edit {itemType}',\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 'editor.backToList': 'To List',\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 {categoryType}',\n 'category.errorFailedUpdate': 'Failed to update {categoryType} \"{label}\"',\n 'category.errorFailedDelete': 'Failed to delete {categoryType} \"{label}\"',\n 'category.errorCouldNotSave': 'Could not save {categoryType}',\n 'category.successCreated': '{categoryType} \"{label}\" has been created successfully',\n 'category.successUpdated': '{categoryType} \"{label}\" has been updated successfully',\n 'category.successDeleted': '{categoryType} \"{label}\" has been deleted successfully',\n 'item.defaultSingular': 'Item',\n 'item.deletionDialogTitle': 'Delete {itemType}',\n 'item.deletionDialogMessage':\n 'Are you sure you want to delete \"{label}\" ({id})? This action cannot be undone.',\n 'item.errorFailedDelete': 'Failed to delete \"{label}\"',\n 'item.successDeleted': '\"{label}\" has been deleted successfully',\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 'common.back': '戻る',\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.titleForCreate': '{itemType} の作成',\n 'editor.titleForEdit': '{itemType} の編集',\n 'editor.idLabel': 'ID',\n 'editor.saveChanges': '変更を保存',\n 'editor.errorInvalidInput': '入力内容が不正です',\n 'editor.errorNoSaver': '保存処理が設定されていません',\n 'editor.successSaved': '保存しました',\n 'editor.backToList': '一覧へ',\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': '{categoryType} を作成できませんでした',\n 'category.errorFailedUpdate': '{categoryType} \"{label}\" の更新に失敗しました',\n 'category.errorFailedDelete': '{categoryType} \"{label}\" の削除に失敗しました',\n 'category.errorCouldNotSave': '{categoryType} を保存できませんでした',\n 'category.successCreated': '{categoryType} \"{label}\" を作成しました',\n 'category.successUpdated': '{categoryType} \"{label}\" を更新しました',\n 'category.successDeleted': '{categoryType} \"{label}\" を削除しました',\n 'item.defaultSingular': '項目',\n 'item.deletionDialogTitle': '{itemType} の削除',\n 'item.deletionDialogMessage': '\"{label}\" ({id}) を削除しますか?この操作は元に戻せません。',\n 'item.errorFailedDelete': '\"{label}\" の削除に失敗しました',\n 'item.successDeleted': '\"{label}\" を削除しました',\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', { categoryType: this.config.singularLabel ?? this.t('category.defaultSingular') })}`,\n undefined,\n {\n duration: 3000,\n },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(\n this.t('category.successCreated', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: categoryLabel,\n }),\n undefined,\n {\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: ${\n e?.message ??\n this.t('category.errorFailedUpdate', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n })\n }`,\n undefined,\n {\n duration: 3000,\n },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(\n this.t('category.successUpdated', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n }),\n undefined,\n {\n duration: 3000,\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: ${\n e?.message ??\n this.t('category.errorFailedDelete', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n })\n }`,\n undefined,\n {\n duration: 3000,\n },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(\n this.t('category.successDeleted', {\n categoryType: this.config.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n }),\n undefined,\n {\n duration: 3000,\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: ${\n e?.message ??\n this.t('category.errorCouldNotSave', {\n categoryType: this.config!.singularLabel ?? this.t('category.defaultSingular'),\n })\n }`,\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: ${\n e?.message ??\n this.t('category.errorFailedDelete', {\n categoryType: this.config?.singularLabel ?? this.t('category.defaultSingular'),\n label: category.label,\n })\n }`,\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') }}&nbsp;\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 }}&nbsp;\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","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 {\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 { MatSnackBar } from '@angular/material/snack-bar';\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 NgxThinAdminItemDeleterConfig,\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';\nimport { MatDialog } from '@angular/material/dialog';\nimport { ConfirmDialog, ConfirmDialogData } from '../shared/confirm-dialog/confirm-dialog';\nimport { lastValueFrom } from 'rxjs';\nimport { getErrorMessage } from '../shared/error-handler';\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 * Config for item deleter (If provided, item deletion feature is enabled)\n * It works by calling openItemDeletionDialog(row) from the click handler of the column definition.\n */\n @Input()\n itemDeleterConfig?: NgxThinAdminItemDeleterConfig;\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 private snackbar = inject(MatSnackBar);\n csvExportService = inject(CsvExportService);\n private dialog = inject(MatDialog);\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 async openItemDeletionDialog(item: any) {\n if (!this.itemDeleterConfig?.deleter) {\n return;\n }\n\n // Get the label and ID to query in the confirmation dialog\n const idKey = this.listConfig?.idFieldKey;\n const labelKey = this.listConfig?.labelFieldKey;\n const id = idKey ? item[idKey] : (item.id ?? JSON.stringify(item));\n const label = labelKey ? item[labelKey] : id;\n const itemType = this.listConfig?.singularLabel || this.t('item.defaultSingular');\n\n // Open the confirmation dialog\n const dialogRef = this.dialog.open(ConfirmDialog, {\n width: '400px',\n data: {\n title: this.t('item.deletionDialogTitle', { itemType }),\n message: this.t('item.deletionDialogMessage', { label, id }),\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 // Execute delete process\n await this.deleteItem(id, label);\n }\n\n async deleteItem(id: string, label: string) {\n if (!this.itemDeleterConfig?.deleter) {\n return;\n }\n\n try {\n await this.itemDeleterConfig.deleter(id);\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(\n `Error: ${errorMessage || this.t('item.errorFailedDelete', { label })}`,\n undefined,\n { duration: 3000 },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(this.t('item.successDeleted', { label }), undefined, {\n duration: 3000,\n });\n\n // Refresh the list after deletion\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=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).link; as linkUrl) {\n <!-- Create Button with Link -->\n <a\n [href]=\"linkUrl\"\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n >\n {{ createBtn.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </a>\n } @else if ($any(createBtn).click; as handler) {\n <!-- Create Button with Handler -->\n <button\n mat-flat-button\n class=\"create-item-button\"\n style=\"color: white; transform: translateY(-1px)\"\n (click)=\"handler()\"\n >\n {{ createBtn?.label ?? t('common.create') }}\n <mat-icon style=\"margin-bottom: 1px\">add</mat-icon>\n </button>\n }\n }\n <!---->\n\n <span style=\"width: 30px\"></span>\n\n <!-- Search Field -->\n <mat-form-field class=\"search-keyword xs-input\" appearance=\"outline\">\n <mat-icon matPrefix>search</mat-icon>\n <input\n matInput\n [placeholder]=\"\n selectedCategory?.[0]?.label\n ? t('list.searchInCategoryPlaceholder', { category: selectedCategory?.[0]?.label })\n : t('list.searchDefaultPlaceholder')\n \"\n [(ngModel)]=\"query.keyword\"\n (keyup)=\"onKeywordInput()\"\n style=\"padding-top: 3px\"\n />\n\n <!-- Search clear button -->\n <button\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"t('list.clearSearchKeyword')\"\n [matTooltip]=\"t('list.clearSearchKeyword')\"\n (click)=\"query.keyword = ''; this.fetchList()\"\n [style.visibility]=\"query.keyword ? 'visible' : 'hidden'\"\n >\n <mat-icon>highlight_off</mat-icon>\n </button>\n <!---->\n </mat-form-field>\n <!---->\n\n <span style=\"width: 8px\"></span>\n\n <!-- Refresh Button -->\n <button mat-icon-button [matTooltip]=\"t('list.refresh')\" (click)=\"fetchList()\">\n <mat-icon>refresh</mat-icon>\n </button>\n <!---->\n\n <span style=\"width: 5px\"></span>\n\n <!-- CSV Export Button -->\n <button\n mat-icon-button\n [matMenuTriggerFor]=\"csvExportMenu\"\n [matTooltip]=\"t('list.exportAsCsv')\"\n >\n <mat-icon>download</mat-icon>\n </button>\n <!---->\n\n <!-- CSV Export Menu -->\n <mat-menu #csvExportMenu=\"matMenu\">\n @for (encoder of csvExportService.getAvailableEncoders(); track encoder.key) {\n <!-- Export with specific charset -->\n <p style=\"color: #333; font-size: 0.8rem; margin: 1rem 0.75rem 1rem 0.7rem\">\n CSV ({{ encoder.label }})\n </p>\n <button mat-menu-item (click)=\"exportAsCsv(encoder.key)\">\n <mat-icon>download</mat-icon>\n <span>{{ t('list.exportItems', { count: totalCount }) }}</span>\n </button>\n <!---->\n }\n </mat-menu>\n <!---->\n </div>\n</ng-template>\n<!---->\n\n<!-- List (Grid) -->\n<mtx-grid\n [data]=\"gridData\"\n [columns]=\"gridColumns\"\n [showToolbar]=\"true\"\n [toolbarTemplate]=\"toolbarTpl\"\n [length]=\"totalCount\"\n [loading]=\"isLoading\"\n [pageOnFront]=\"false\"\n [pageIndex]=\"query.page\"\n [pageSize]=\"query.perPage\"\n [pageSizeOptions]=\"listConfig?.pageSizes ?? [10, 25, 50, 100]\"\n columnMenuButtonType=\"icon\"\n columnMenuButtonClass=\"column-menu-button\"\n columnMenuButtonIcon=\"view_column\"\n (page)=\"onPageChange($event)\"\n></mtx-grid>\n<!---->\n\n<!-- Cell Template with Link -->\n<ng-template #cellTplWithLink let-row let-index=\"index\" let-col=\"colDef\">\n @if (col.link) {\n <a [href]=\"col.link(row)\">\n {{ row[col.field] }}\n </a>\n } @else if (col.routerLink) {\n <a [routerLink]=\"col.routerLink(row)\">\n {{ row[col.field] }}\n </a>\n } @else {\n {{ row[col.field] }}\n }\n</ng-template>\n<!---->\n","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","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, MatIconButton } from '@angular/material/button';\nimport { MatIcon } from '@angular/material/icon';\nimport { MatTooltip } from '@angular/material/tooltip';\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 {\n NgxThinAdminEditorConfig,\n NgxThinAdminEditorField,\n NgxThinAdminItemDeleterConfig,\n} 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';\nimport { MatDialog } from '@angular/material/dialog';\nimport { ConfirmDialog, ConfirmDialogData } from '../shared/confirm-dialog/confirm-dialog';\nimport { lastValueFrom } from 'rxjs';\nimport { Router, RouterLink } from '@angular/router';\n\n@Component({\n selector: 'ngx-thin-admin-editor',\n imports: [\n ReactiveFormsModule,\n FormlyForm,\n MatButton,\n MatIconButton,\n MatIcon,\n MatTooltip,\n RouterLink,\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 * Config for item deleter\n */\n @Input()\n itemDeleterConfig?: NgxThinAdminItemDeleterConfig;\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 * For history back\n */\n windowHistory = window.history;\n\n /**\n * Services\n */\n private snackbar = inject(MatSnackBar);\n private cdr = inject(ChangeDetectorRef);\n private translate = inject(NGX_THIN_ADMIN_TRANSLATE);\n private dialog = inject(MatDialog);\n private router = inject(Router);\n\n t(key: NgxThinAdminI18nKey, params?: Record<string, string | number | undefined>): string {\n return this.translate(key, params);\n }\n\n get editorItemType(): string {\n return this.editorConfig?.singularLabel || this.t('item.defaultSingular');\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 async openDeletionDialog() {\n if (!this.itemDeleterConfig?.deleter || this.itemId === undefined) {\n return;\n }\n\n // Get the label and ID to query in the confirmation dialog\n const id = this.itemId;\n const label = this.editorConfig?.labelFieldKey\n ? this.data[this.editorConfig.labelFieldKey]\n : id;\n const itemType = this.editorItemType;\n\n // Open the confirmation dialog\n const dialogRef = this.dialog.open(ConfirmDialog, {\n width: '400px',\n data: {\n title: this.t('item.deletionDialogTitle', { itemType }),\n message: this.t('item.deletionDialogMessage', { label, id }),\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 // Execute delete process\n await this.deleteItem(id, label);\n }\n\n async deleteItem(id: string, label: string) {\n if (!this.itemDeleterConfig?.deleter) {\n return;\n }\n\n try {\n await this.itemDeleterConfig.deleter(id);\n } catch (e: any) {\n const errorMessage = getErrorMessage(e);\n this.snackbar.open(\n `Error: ${errorMessage || this.t('item.errorFailedDelete', { label })}`,\n undefined,\n { duration: 3000 },\n );\n return;\n }\n\n // Show success message\n this.snackbar.open(this.t('item.successDeleted', { label }), undefined, {\n duration: 3000,\n });\n\n // Subsequence routing\n if (this.itemDeleterConfig.afterDeleteNavigateTo) {\n this.router.navigate([this.itemDeleterConfig.afterDeleteNavigateTo]);\n }\n }\n}\n","<mat-card>\n <mat-card-header style=\"position: relative\">\n <!-- Back button -->\n @if (editorConfig?.backButton) {\n @if ($any(editorConfig?.backButton).historyBack && windowHistory.length > 1) {\n <button mat-button (click)=\"windowHistory.back()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n } @else if ($any(editorConfig?.backButton).routerLink; as backButtonLink) {\n <a [routerLink]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).link; as backButtonLink) {\n <a [href]=\"backButtonLink\" mat-button class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </a>\n } @else if ($any(editorConfig?.backButton).click; as handler) {\n <button mat-button (click)=\"handler()\" class=\"back-link\">\n <mat-icon>arrow_back_ios_new</mat-icon>\n {{ editorConfig?.backButton?.label ?? t('editor.backToList') }}\n </button>\n }\n }\n <!---->\n\n <!-- Editor title -->\n <h3 style=\"margin: 0\" [style.margin-top]=\"editorConfig?.backButton ? '1rem' : '0'\">\n @if (itemId !== undefined && $any(data); as editItem) {\n @if (editorConfig?.labelFieldKey && editItem[editorConfig!.labelFieldKey!]) {\n <!-- e.g., \"Edit - Taro (taro) \" -->\n {{ t('common.edit') }} &nbsp; <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') }} &nbsp; <span style=\"color: #aaaaaa\">-</span>\n {{ t('editor.idLabel') }}:\n <span class=\"editor-item-label\">{{ editItem.id }}</span>\n <!---->\n } @else {\n <!-- e.g., \"Edit Account (123)\" -->\n {{ t('editor.titleForEdit', { itemType: editorItemType }) }}\n @if (editorConfig?.idFieldKey && editItem[editorConfig!.idFieldKey!]) {\n <small class=\"editor-header-sub\">{{ editItem[editorConfig!.idFieldKey!] }}</small>\n }\n <!---->\n }\n } @else {\n <!-- Create Account -->\n {{ t('editor.titleForCreate', { itemType: editorItemType }) }}\n <!---->\n }\n </h3>\n <!---->\n </mat-card-header>\n\n <mat-card-content>\n @if (isLoading || isSaving) {\n <mat-progress-bar mode=\"indeterminate\" style=\"margin-top: 1rem\"></mat-progress-bar>\n }\n\n @if (!isLoading) {\n <form [formGroup]=\"form\" (ngSubmit)=\"save()\">\n <formly-form\n [form]=\"form\"\n [fields]=\"$any(editorFields) ?? []\"\n [model]=\"formData\"\n ></formly-form>\n\n <!-- Button Area -->\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-top: 0.5rem;\n \"\n >\n <!-- Delete button (visible only in edit mode and if itemDeleterConfig is provided) -->\n @if (itemDeleterConfig?.deleter && itemId !== undefined) {\n <button\n type=\"button\"\n mat-stroked-button\n color=\"warn\"\n (click)=\"openDeletionDialog()\"\n [disabled]=\"isLoading || isSaving\"\n >\n {{ t('common.delete') }}\n </button>\n } @else {\n <span></span>\n }\n <!---->\n\n <!-- Submit button (visible only if saver is provided) -->\n @if (editorConfig?.saver) {\n <button\n type=\"submit\"\n mat-flat-button\n style=\"color: white; transform: translateY(-0.3rem)\"\n >\n @if (itemId !== undefined) {\n {{ t('editor.saveChanges') }}\n } @else {\n {{ t('common.create') }}\n }\n </button>\n }\n <!---->\n </div>\n <!---->\n </form>\n }\n </mat-card-content>\n</mat-card>\n","/*\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,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-thin-admin",
3
- "version": "0.0.0-alpha.3",
3
+ "version": "0.0.0-alpha.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/mugifly/ngx-thin-admin/tree/main/projects/ngx-thin-admin"
@@ -39,7 +39,27 @@ interface NgxThinAdminEditorConfig {
39
39
  * @returns The created/updated item data
40
40
  */
41
41
  saver?: (data: any, id?: string) => Promise<any> | any;
42
+ /**
43
+ * Optional config for back button
44
+ */
45
+ backButton?: NgxThinAdminEditorBackButtonConfig;
42
46
  }
47
+ type NgxThinAdminEditorBackButtonConfig = {
48
+ label?: string;
49
+ historyBack: true;
50
+ } | {
51
+ label?: string;
52
+ click: () => void;
53
+ historyBack?: boolean;
54
+ } | {
55
+ label?: string;
56
+ link: string;
57
+ historyBack?: boolean;
58
+ } | {
59
+ label?: string;
60
+ routerLink: string;
61
+ historyBack?: boolean;
62
+ };
43
63
  /**
44
64
  * Columns for editor (extended type of FormlyFieldConfig)
45
65
  */
@@ -157,13 +177,13 @@ interface NgxThinAdminCategorySelectorConfig {
157
177
  deleter?: (category: NgxThinAdminCategory) => Promise<void> | void;
158
178
  }
159
179
  type NgxThinAdminListCreateButtonConfig = {
160
- label: string;
180
+ label?: string;
161
181
  click: () => void;
162
182
  } | {
163
- label: string;
183
+ label?: string;
164
184
  link: string;
165
185
  } | {
166
- label: string;
186
+ label?: string;
167
187
  routerLink: string;
168
188
  };
169
189
  interface NgxThinAdminListCsvExportButtonConfig {
@@ -224,7 +244,7 @@ declare class CsvExportService {
224
244
  }
225
245
 
226
246
  type NgxThinAdminLocale = 'en' | 'ja';
227
- 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.titleForCreate' | 'editor.titleForEdit' | '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' | 'category.successCreated' | 'category.successUpdated' | 'category.successDeleted' | 'item.defaultSingular' | 'item.deletionDialogTitle' | 'item.deletionDialogMessage' | 'item.errorFailedDelete' | 'item.successDeleted' | 'csv.exporting' | 'csv.exportCompleted' | 'csv.exportCompletedWithErrors' | 'csv.errorGenerateFailed';
247
+ type NgxThinAdminI18nKey = 'common.cancel' | 'common.ok' | 'common.save' | 'common.create' | 'common.edit' | 'common.delete' | 'common.back' | 'list.defaultTitle' | 'list.clearFilters' | 'list.searchDefaultPlaceholder' | 'list.searchInCategoryPlaceholder' | 'list.clearSearchKeyword' | 'list.refresh' | 'list.exportAsCsv' | 'list.exportedFileName' | 'list.exportItems' | 'editor.titleForCreate' | 'editor.titleForEdit' | 'editor.idLabel' | 'editor.saveChanges' | 'editor.errorInvalidInput' | 'editor.errorNoSaver' | 'editor.successSaved' | 'editor.backToList' | 'category.defaultSingular' | 'category.defaultPlural' | 'category.all' | 'category.editorDialogTitleForCreate' | 'category.editorDialogTitleForEdit' | 'category.deletionDialogTitle' | 'category.deletionDialogMessage' | 'category.errorCouldNotCreate' | 'category.errorFailedUpdate' | 'category.errorFailedDelete' | 'category.errorCouldNotSave' | 'category.successCreated' | 'category.successUpdated' | 'category.successDeleted' | 'item.defaultSingular' | 'item.deletionDialogTitle' | 'item.deletionDialogMessage' | 'item.errorFailedDelete' | 'item.successDeleted' | 'csv.exporting' | 'csv.exportCompleted' | 'csv.exportCompletedWithErrors' | 'csv.errorGenerateFailed';
228
248
  type NgxThinAdminI18nParams = Record<string, string | number | undefined>;
229
249
  type NgxThinAdminTranslate = (key: NgxThinAdminI18nKey, params?: NgxThinAdminI18nParams) => string;
230
250
  interface NgxThinAdminI18nConfig {
@@ -331,6 +351,10 @@ declare class NgxThinAdminEditor implements OnChanges {
331
351
  form: FormGroup<{}>;
332
352
  data: any;
333
353
  formData: any;
354
+ /**
355
+ * For history back
356
+ */
357
+ windowHistory: History;
334
358
  /**
335
359
  * Services
336
360
  */
@@ -352,4 +376,4 @@ declare class NgxThinAdminEditor implements OnChanges {
352
376
  }
353
377
 
354
378
  export { NGX_THIN_ADMIN_TRANSLATE, NgxThinAdminEditor, NgxThinAdminList, provideNgxThinAdminI18n };
355
- export type { ListFetcher, NgxThinAdminCategory, NgxThinAdminCategoryListResponse, NgxThinAdminCategorySelectorConfig, NgxThinAdminEditorConfig, NgxThinAdminEditorField, NgxThinAdminFieldConfig, NgxThinAdminFieldProps, NgxThinAdminI18nConfig, NgxThinAdminI18nKey, NgxThinAdminI18nParams, NgxThinAdminItemDeleterConfig, NgxThinAdminListColumn, NgxThinAdminListConfig, NgxThinAdminListCreateButtonConfig, NgxThinAdminListCsvExportButtonConfig, NgxThinAdminListQuery, NgxThinAdminListResponse, NgxThinAdminLocale, NgxThinAdminTranslate };
379
+ export type { ListFetcher, NgxThinAdminCategory, NgxThinAdminCategoryListResponse, NgxThinAdminCategorySelectorConfig, NgxThinAdminEditorBackButtonConfig, NgxThinAdminEditorConfig, NgxThinAdminEditorField, NgxThinAdminFieldConfig, NgxThinAdminFieldProps, NgxThinAdminI18nConfig, NgxThinAdminI18nKey, NgxThinAdminI18nParams, NgxThinAdminItemDeleterConfig, NgxThinAdminListColumn, NgxThinAdminListConfig, NgxThinAdminListCreateButtonConfig, NgxThinAdminListCsvExportButtonConfig, NgxThinAdminListQuery, NgxThinAdminListResponse, NgxThinAdminLocale, NgxThinAdminTranslate };