@flusys/ng-storage 3.0.1 → 4.0.0-lts

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.
Files changed (23) hide show
  1. package/README.md +12 -6
  2. package/fesm2022/{flusys-ng-storage-file-manager-form.component-CXVB9G-f.mjs → flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs} +67 -74
  3. package/fesm2022/flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs.map +1 -0
  4. package/fesm2022/{flusys-ng-storage-file-manager-list.component-0O_b4EjN.mjs → flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs} +66 -74
  5. package/fesm2022/flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-storage-folder-form.component-BTQGEqNu.mjs → flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs} +25 -34
  7. package/fesm2022/flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs.map +1 -0
  8. package/fesm2022/{flusys-ng-storage-folder-list.component-B8GoIh6Z.mjs → flusys-ng-storage-folder-list.component-B2Q41I1g.mjs} +34 -39
  9. package/fesm2022/flusys-ng-storage-folder-list.component-B2Q41I1g.mjs.map +1 -0
  10. package/fesm2022/{flusys-ng-storage-storage-config-form.component-CorNWrmF.mjs → flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs} +87 -85
  11. package/fesm2022/flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs.map +1 -0
  12. package/fesm2022/{flusys-ng-storage-storage-config-list.component-YXzz3Tvo.mjs → flusys-ng-storage-storage-config-list.component-DBH_qf9o.mjs} +36 -35
  13. package/fesm2022/flusys-ng-storage-storage-config-list.component-DBH_qf9o.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-storage.mjs +490 -151
  15. package/fesm2022/flusys-ng-storage.mjs.map +1 -1
  16. package/package.json +7 -5
  17. package/types/flusys-ng-storage.d.ts +56 -36
  18. package/fesm2022/flusys-ng-storage-file-manager-form.component-CXVB9G-f.mjs.map +0 -1
  19. package/fesm2022/flusys-ng-storage-file-manager-list.component-0O_b4EjN.mjs.map +0 -1
  20. package/fesm2022/flusys-ng-storage-folder-form.component-BTQGEqNu.mjs.map +0 -1
  21. package/fesm2022/flusys-ng-storage-folder-list.component-B8GoIh6Z.mjs.map +0 -1
  22. package/fesm2022/flusys-ng-storage-storage-config-form.component-CorNWrmF.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-storage-storage-config-list.component-YXzz3Tvo.mjs.map +0 -1
@@ -1,35 +1,29 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { FILE_PERMISSIONS, AngularModule, PrimeModule, HasPermissionDirective } from '@flusys/ng-shared';
2
+ import { inject, signal, Component } from '@angular/core';
3
+ import { TranslateService } from '@flusys/ng-localization';
4
+ import { FILE_PERMISSIONS, AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe } from '@flusys/ng-shared';
4
5
  import { firstValueFrom } from 'rxjs';
5
- import { BaseStorageListPage, FileManagerApiService, getFileIcon, getProviderLabel, getProviderSeverity } from './flusys-ng-storage.mjs';
6
+ import { BaseStorageListPage, FileManagerApiService, getFileIcon, getProviderLabelKey, getProviderSeverity } from './flusys-ng-storage.mjs';
6
7
  import * as i1 from 'primeng/button';
7
8
  import * as i2 from 'primeng/table';
8
9
  import * as i3 from 'primeng/tag';
9
10
  import * as i4 from 'primeng/tooltip';
10
11
  import * as i5 from '@angular/common';
11
12
 
12
- /**
13
- * File Manager List Component
14
- * Displays all files with company filter (if enabled)
15
- */
16
13
  class FileManagerListComponent extends BaseStorageListPage {
17
- // Permission constants for template
18
14
  FILE_PERMISSIONS = FILE_PERMISSIONS;
19
15
  fileService = inject(FileManagerApiService);
20
- /** Files list alias for template compatibility */
16
+ translateService = inject(TranslateService);
21
17
  files = this.items;
22
- /** ID of file currently being viewed (null when not viewing) */
23
18
  viewingFileId = signal(null, ...(ngDevMode ? [{ debugName: "viewingFileId" }] : []));
24
- /** Utility functions exposed to template */
25
19
  getFileIcon = getFileIcon;
26
- getProviderLabel = getProviderLabel;
20
+ getProviderLabelKey = getProviderLabelKey;
27
21
  getProviderSeverity = getProviderSeverity;
28
22
  getResourceRoute() {
29
23
  return '/storage/files';
30
24
  }
31
25
  getDeleteConfirmMessage(file) {
32
- return `Are you sure you want to delete "${file.name}"?`;
26
+ return this.translateService.translate('storage.delete.confirm.named', { name: file.name });
33
27
  }
34
28
  async loadData() {
35
29
  this.isLoading.set(true);
@@ -46,7 +40,7 @@ class FileManagerListComponent extends BaseStorageListPage {
46
40
  }
47
41
  }
48
42
  catch {
49
- this.showError('Failed to load files.');
43
+ this.showError(this.translateService.translate('storage.error.load.failed'));
50
44
  }
51
45
  finally {
52
46
  this.isLoading.set(false);
@@ -59,16 +53,15 @@ class FileManagerListComponent extends BaseStorageListPage {
59
53
  this.viewingFileId.set(file.id);
60
54
  try {
61
55
  const response = await firstValueFrom(this.fileService.getFiles([file.id]));
62
- // Response type is ISingleResponse<IFilesResponseDto[]>
63
56
  if (response.success && response.data?.length && response.data[0].url) {
64
57
  window.open(response.data[0].url, '_blank');
65
58
  }
66
59
  else {
67
- this.showError('File URL is not available.');
60
+ this.showError(this.translateService.translate('storage.file.url.not.available'));
68
61
  }
69
62
  }
70
63
  catch {
71
- this.showError('Failed to get file URL.');
64
+ this.showError(this.translateService.translate('storage.file.get.url.failed'));
72
65
  }
73
66
  finally {
74
67
  this.viewingFileId.set(null);
@@ -76,39 +69,39 @@ class FileManagerListComponent extends BaseStorageListPage {
76
69
  }
77
70
  onSoftDelete(file) {
78
71
  this.confirmationService.confirm({
79
- message: `Move "${file.name}" to trash? You can recover it later.`,
80
- header: 'Move to Trash',
72
+ message: this.translateService.translate('storage.delete.move.to.trash.confirm', { name: file.name }),
73
+ header: this.translateService.translate('storage.delete.move.to.trash'),
81
74
  icon: 'pi pi-trash',
82
- acceptLabel: 'Move to Trash',
75
+ acceptLabel: this.translateService.translate('storage.delete.move.to.trash'),
83
76
  acceptButtonStyleClass: 'p-button-warning',
84
77
  accept: async () => {
85
78
  try {
86
79
  await this.fileService.deleteAsync({ id: file.id, type: 'delete' });
87
- this.showSuccess('File moved to trash successfully.');
80
+ this.showSuccess(this.translateService.translate('storage.delete.trash.success'));
88
81
  this.loadData();
89
82
  }
90
83
  catch {
91
- this.showError('Failed to move file to trash.');
84
+ this.showError(this.translateService.translate('storage.delete.trash.failed'));
92
85
  }
93
86
  },
94
87
  });
95
88
  }
96
89
  onPermanentDelete(file) {
97
90
  this.confirmationService.confirm({
98
- message: `Permanently delete "${file.name}"? This action CANNOT be undone and will delete the file from storage.`,
99
- header: 'Permanent Delete',
91
+ message: this.translateService.translate('storage.delete.permanent.delete.confirm', { name: file.name }),
92
+ header: this.translateService.translate('storage.delete.permanent.delete'),
100
93
  icon: 'pi pi-exclamation-triangle',
101
- acceptLabel: 'Delete Permanently',
102
- rejectLabel: 'Cancel',
94
+ acceptLabel: this.translateService.translate('storage.delete.permanent.delete.button'),
95
+ rejectLabel: this.translateService.translate('shared.cancel'),
103
96
  acceptButtonStyleClass: 'p-button-danger',
104
97
  accept: async () => {
105
98
  try {
106
99
  await this.fileService.deleteAsync({ id: file.id, type: 'permanent' });
107
- this.showSuccess('File permanently deleted.');
100
+ this.showSuccess(this.translateService.translate('storage.delete.permanent.success'));
108
101
  this.loadData();
109
102
  }
110
103
  catch {
111
- this.showError('Failed to permanently delete file.');
104
+ this.showError(this.translateService.translate('storage.delete.permanent.failed'));
112
105
  }
113
106
  },
114
107
  });
@@ -118,14 +111,14 @@ class FileManagerListComponent extends BaseStorageListPage {
118
111
  <div class="card">
119
112
  <div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4">
120
113
  <div>
121
- <h3 class="text-lg sm:text-xl font-semibold">File Manager</h3>
114
+ <h3 class="text-lg sm:text-xl font-semibold">{{ 'storage.file.manager.title' | translate }}</h3>
122
115
  @if (showCompanyInfo()) {
123
116
  <p class="text-sm text-muted-color mt-1">
124
- Company: {{ currentCompanyName() }}
117
+ {{ 'storage.company' | translate }}: {{ currentCompanyName() }}
125
118
  </p>
126
119
  }
127
120
  </div>
128
- <p-button *hasPermission="FILE_PERMISSIONS.CREATE" label="Upload File" icon="pi pi-upload" (onClick)="onUpload()" styleClass="w-full sm:w-auto" />
121
+ <p-button *hasPermission="FILE_PERMISSIONS.CREATE" [label]="'storage.button.upload.file' | translate" icon="pi pi-upload" (onClick)="onUpload()" styleClass="w-full sm:w-auto" />
129
122
  </div>
130
123
 
131
124
  <div class="overflow-x-auto">
@@ -143,14 +136,14 @@ class FileManagerListComponent extends BaseStorageListPage {
143
136
  >
144
137
  <ng-template #header>
145
138
  <tr>
146
- <th>Name</th>
147
- <th class="hidden lg:table-cell">Type</th>
148
- <th>Size</th>
149
- <th>Location</th>
150
- <th class="hidden xl:table-cell">Config</th>
151
- <th>Private</th>
152
- <th class="hidden md:table-cell">Created</th>
153
- <th class="w-[120px]">Actions</th>
139
+ <th>{{ 'storage.table.name' | translate }}</th>
140
+ <th class="hidden lg:table-cell">{{ 'storage.table.type' | translate }}</th>
141
+ <th>{{ 'storage.table.size' | translate }}</th>
142
+ <th>{{ 'storage.table.location' | translate }}</th>
143
+ <th class="hidden xl:table-cell">{{ 'storage.table.config' | translate }}</th>
144
+ <th>{{ 'storage.table.private' | translate }}</th>
145
+ <th class="hidden md:table-cell">{{ 'storage.table.created' | translate }}</th>
146
+ <th class="w-[120px]">{{ 'storage.table.actions' | translate }}</th>
154
147
  </tr>
155
148
  </ng-template>
156
149
  <ng-template #body let-file>
@@ -164,25 +157,25 @@ class FileManagerListComponent extends BaseStorageListPage {
164
157
  <td class="hidden lg:table-cell">
165
158
  <span class="text-sm text-muted-color">{{ file.contentType }}</span>
166
159
  </td>
167
- <td>{{ file.size }} KB</td>
160
+ <td>{{ file.size }} {{ 'storage.unit.kb' | translate }}</td>
168
161
  <td>
169
- <p-tag [value]="getProviderLabel(file.location)" [severity]="getProviderSeverity(file.location)" />
162
+ <p-tag [value]="getProviderLabelKey(file.location) | translate" [severity]="getProviderSeverity(file.location)" />
170
163
  </td>
171
164
  <td class="hidden xl:table-cell">{{ file.providerName || '-' }}</td>
172
165
  <td>
173
166
  @if (file.isPrivate) {
174
- <p-tag value="Private" severity="warn" />
167
+ <p-tag [value]="'storage.private' | translate" severity="warn" />
175
168
  } @else {
176
- <p-tag value="Public" severity="success" />
169
+ <p-tag [value]="'storage.public' | translate" severity="success" />
177
170
  }
178
171
  </td>
179
172
  <td class="hidden md:table-cell">{{ file.createdAt | date: 'short' }}</td>
180
173
  <td>
181
174
  <div class="flex gap-1">
182
- <p-button *hasPermission="FILE_PERMISSIONS.READ" icon="pi pi-eye" [text]="true" severity="secondary" size="small" [loading]="viewingFileId() === file.id" [disabled]="viewingFileId() === file.id" (onClick)="onView(file)" pTooltip="View" tooltipPosition="top" />
183
- <p-button *hasPermission="FILE_PERMISSIONS.UPDATE" icon="pi pi-pencil" [text]="true" severity="secondary" size="small" (onClick)="onEdit(file.id)" pTooltip="Edit" tooltipPosition="top" />
184
- <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-trash" [text]="true" severity="warn" size="small" (onClick)="onSoftDelete(file)" pTooltip="Trash" tooltipPosition="top" />
185
- <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-times-circle" [text]="true" severity="danger" size="small" (onClick)="onPermanentDelete(file)" pTooltip="Delete" tooltipPosition="top" />
175
+ <p-button *hasPermission="FILE_PERMISSIONS.READ" icon="pi pi-eye" [text]="true" severity="secondary" size="small" [loading]="viewingFileId() === file.id" [disabled]="viewingFileId() === file.id" (onClick)="onView(file)" [pTooltip]="'storage.tooltip.view' | translate" tooltipPosition="top" />
176
+ <p-button *hasPermission="FILE_PERMISSIONS.UPDATE" icon="pi pi-pencil" [text]="true" severity="secondary" size="small" (onClick)="onEdit(file.id)" [pTooltip]="'storage.tooltip.edit' | translate" tooltipPosition="top" />
177
+ <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-trash" [text]="true" severity="warn" size="small" (onClick)="onSoftDelete(file)" [pTooltip]="'storage.tooltip.trash' | translate" tooltipPosition="top" />
178
+ <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-times-circle" [text]="true" severity="danger" size="small" (onClick)="onPermanentDelete(file)" [pTooltip]="'storage.tooltip.delete' | translate" tooltipPosition="top" />
186
179
  </div>
187
180
  </td>
188
181
  </tr>
@@ -191,9 +184,9 @@ class FileManagerListComponent extends BaseStorageListPage {
191
184
  <tr>
192
185
  <td colspan="8" class="text-center py-4 text-muted-color">
193
186
  @if (showCompanyInfo()) {
194
- No files found in current company
187
+ {{ 'storage.empty.files.in.company' | translate }}
195
188
  } @else {
196
- No files found
189
+ {{ 'storage.empty.files' | translate }}
197
190
  }
198
191
  </td>
199
192
  </tr>
@@ -201,26 +194,25 @@ class FileManagerListComponent extends BaseStorageListPage {
201
194
  </p-table>
202
195
  </div>
203
196
  </div>
204
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "component", type: i3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: i4.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { kind: "pipe", type: i5.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
197
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "component", type: i3.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: i4.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
205
198
  }
206
199
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileManagerListComponent, decorators: [{
207
200
  type: Component,
208
201
  args: [{
209
202
  selector: 'lib-file-manager-list',
210
- changeDetection: ChangeDetectionStrategy.OnPush,
211
- imports: [AngularModule, PrimeModule, HasPermissionDirective],
203
+ imports: [AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe],
212
204
  template: `
213
205
  <div class="card">
214
206
  <div class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4">
215
207
  <div>
216
- <h3 class="text-lg sm:text-xl font-semibold">File Manager</h3>
208
+ <h3 class="text-lg sm:text-xl font-semibold">{{ 'storage.file.manager.title' | translate }}</h3>
217
209
  @if (showCompanyInfo()) {
218
210
  <p class="text-sm text-muted-color mt-1">
219
- Company: {{ currentCompanyName() }}
211
+ {{ 'storage.company' | translate }}: {{ currentCompanyName() }}
220
212
  </p>
221
213
  }
222
214
  </div>
223
- <p-button *hasPermission="FILE_PERMISSIONS.CREATE" label="Upload File" icon="pi pi-upload" (onClick)="onUpload()" styleClass="w-full sm:w-auto" />
215
+ <p-button *hasPermission="FILE_PERMISSIONS.CREATE" [label]="'storage.button.upload.file' | translate" icon="pi pi-upload" (onClick)="onUpload()" styleClass="w-full sm:w-auto" />
224
216
  </div>
225
217
 
226
218
  <div class="overflow-x-auto">
@@ -238,14 +230,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
238
230
  >
239
231
  <ng-template #header>
240
232
  <tr>
241
- <th>Name</th>
242
- <th class="hidden lg:table-cell">Type</th>
243
- <th>Size</th>
244
- <th>Location</th>
245
- <th class="hidden xl:table-cell">Config</th>
246
- <th>Private</th>
247
- <th class="hidden md:table-cell">Created</th>
248
- <th class="w-[120px]">Actions</th>
233
+ <th>{{ 'storage.table.name' | translate }}</th>
234
+ <th class="hidden lg:table-cell">{{ 'storage.table.type' | translate }}</th>
235
+ <th>{{ 'storage.table.size' | translate }}</th>
236
+ <th>{{ 'storage.table.location' | translate }}</th>
237
+ <th class="hidden xl:table-cell">{{ 'storage.table.config' | translate }}</th>
238
+ <th>{{ 'storage.table.private' | translate }}</th>
239
+ <th class="hidden md:table-cell">{{ 'storage.table.created' | translate }}</th>
240
+ <th class="w-[120px]">{{ 'storage.table.actions' | translate }}</th>
249
241
  </tr>
250
242
  </ng-template>
251
243
  <ng-template #body let-file>
@@ -259,25 +251,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
259
251
  <td class="hidden lg:table-cell">
260
252
  <span class="text-sm text-muted-color">{{ file.contentType }}</span>
261
253
  </td>
262
- <td>{{ file.size }} KB</td>
254
+ <td>{{ file.size }} {{ 'storage.unit.kb' | translate }}</td>
263
255
  <td>
264
- <p-tag [value]="getProviderLabel(file.location)" [severity]="getProviderSeverity(file.location)" />
256
+ <p-tag [value]="getProviderLabelKey(file.location) | translate" [severity]="getProviderSeverity(file.location)" />
265
257
  </td>
266
258
  <td class="hidden xl:table-cell">{{ file.providerName || '-' }}</td>
267
259
  <td>
268
260
  @if (file.isPrivate) {
269
- <p-tag value="Private" severity="warn" />
261
+ <p-tag [value]="'storage.private' | translate" severity="warn" />
270
262
  } @else {
271
- <p-tag value="Public" severity="success" />
263
+ <p-tag [value]="'storage.public' | translate" severity="success" />
272
264
  }
273
265
  </td>
274
266
  <td class="hidden md:table-cell">{{ file.createdAt | date: 'short' }}</td>
275
267
  <td>
276
268
  <div class="flex gap-1">
277
- <p-button *hasPermission="FILE_PERMISSIONS.READ" icon="pi pi-eye" [text]="true" severity="secondary" size="small" [loading]="viewingFileId() === file.id" [disabled]="viewingFileId() === file.id" (onClick)="onView(file)" pTooltip="View" tooltipPosition="top" />
278
- <p-button *hasPermission="FILE_PERMISSIONS.UPDATE" icon="pi pi-pencil" [text]="true" severity="secondary" size="small" (onClick)="onEdit(file.id)" pTooltip="Edit" tooltipPosition="top" />
279
- <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-trash" [text]="true" severity="warn" size="small" (onClick)="onSoftDelete(file)" pTooltip="Trash" tooltipPosition="top" />
280
- <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-times-circle" [text]="true" severity="danger" size="small" (onClick)="onPermanentDelete(file)" pTooltip="Delete" tooltipPosition="top" />
269
+ <p-button *hasPermission="FILE_PERMISSIONS.READ" icon="pi pi-eye" [text]="true" severity="secondary" size="small" [loading]="viewingFileId() === file.id" [disabled]="viewingFileId() === file.id" (onClick)="onView(file)" [pTooltip]="'storage.tooltip.view' | translate" tooltipPosition="top" />
270
+ <p-button *hasPermission="FILE_PERMISSIONS.UPDATE" icon="pi pi-pencil" [text]="true" severity="secondary" size="small" (onClick)="onEdit(file.id)" [pTooltip]="'storage.tooltip.edit' | translate" tooltipPosition="top" />
271
+ <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-trash" [text]="true" severity="warn" size="small" (onClick)="onSoftDelete(file)" [pTooltip]="'storage.tooltip.trash' | translate" tooltipPosition="top" />
272
+ <p-button *hasPermission="FILE_PERMISSIONS.DELETE" icon="pi pi-times-circle" [text]="true" severity="danger" size="small" (onClick)="onPermanentDelete(file)" [pTooltip]="'storage.tooltip.delete' | translate" tooltipPosition="top" />
281
273
  </div>
282
274
  </td>
283
275
  </tr>
@@ -286,9 +278,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
286
278
  <tr>
287
279
  <td colspan="8" class="text-center py-4 text-muted-color">
288
280
  @if (showCompanyInfo()) {
289
- No files found in current company
281
+ {{ 'storage.empty.files.in.company' | translate }}
290
282
  } @else {
291
- No files found
283
+ {{ 'storage.empty.files' | translate }}
292
284
  }
293
285
  </td>
294
286
  </tr>
@@ -301,4 +293,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
301
293
  }] });
302
294
 
303
295
  export { FileManagerListComponent };
304
- //# sourceMappingURL=flusys-ng-storage-file-manager-list.component-0O_b4EjN.mjs.map
296
+ //# sourceMappingURL=flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs","sources":["../../../projects/ng-storage/pages/file-manager/file-manager-list.component.ts"],"sourcesContent":["import { Component, inject, signal } from '@angular/core';\nimport { TranslateService } from '@flusys/ng-localization';\nimport { AngularModule, FILE_PERMISSIONS, HasPermissionDirective, PrimeModule, TranslatePipe } from '@flusys/ng-shared';\nimport { firstValueFrom } from 'rxjs';\nimport { IFileManager } from '../../interfaces/file-manager.interface';\nimport { FileManagerApiService } from '../../services/file-manager-api.service';\nimport { BaseStorageListPage } from '../../utils/base-storage-page';\nimport { getFileIcon, getProviderLabelKey, getProviderSeverity } from '../../utils/storage-utils';\n\n@Component({\n selector: 'lib-file-manager-list',\n imports: [AngularModule, PrimeModule, HasPermissionDirective, TranslatePipe],\n template: `\n <div class=\"card\">\n <div class=\"flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4\">\n <div>\n <h3 class=\"text-lg sm:text-xl font-semibold\">{{ 'storage.file.manager.title' | translate }}</h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n {{ 'storage.company' | translate }}: {{ currentCompanyName() }}\n </p>\n }\n </div>\n <p-button *hasPermission=\"FILE_PERMISSIONS.CREATE\" [label]=\"'storage.button.upload.file' | translate\" icon=\"pi pi-upload\" (onClick)=\"onUpload()\" styleClass=\"w-full sm:w-auto\" />\n </div>\n\n <div class=\"overflow-x-auto\">\n <p-table\n [value]=\"files()\"\n [loading]=\"isLoading()\"\n [paginator]=\"totalRecords() > 0\"\n [rows]=\"pageSize()\"\n [totalRecords]=\"totalRecords()\"\n [lazy]=\"true\"\n (onLazyLoad)=\"onPageChange($event)\"\n [rowsPerPageOptions]=\"[10, 25, 50]\"\n [scrollable]=\"true\"\n styleClass=\"p-datatable-sm\"\n >\n <ng-template #header>\n <tr>\n <th>{{ 'storage.table.name' | translate }}</th>\n <th class=\"hidden lg:table-cell\">{{ 'storage.table.type' | translate }}</th>\n <th>{{ 'storage.table.size' | translate }}</th>\n <th>{{ 'storage.table.location' | translate }}</th>\n <th class=\"hidden xl:table-cell\">{{ 'storage.table.config' | translate }}</th>\n <th>{{ 'storage.table.private' | translate }}</th>\n <th class=\"hidden md:table-cell\">{{ 'storage.table.created' | translate }}</th>\n <th class=\"w-[120px]\">{{ 'storage.table.actions' | translate }}</th>\n </tr>\n </ng-template>\n <ng-template #body let-file>\n <tr>\n <td>\n <div class=\"flex items-center gap-2\">\n <i [class]=\"getFileIcon(file.contentType)\"></i>\n <span class=\"truncate max-w-32 sm:max-w-none\">{{ file.name }}</span>\n </div>\n </td>\n <td class=\"hidden lg:table-cell\">\n <span class=\"text-sm text-muted-color\">{{ file.contentType }}</span>\n </td>\n <td>{{ file.size }} {{ 'storage.unit.kb' | translate }}</td>\n <td>\n <p-tag [value]=\"getProviderLabelKey(file.location) | translate\" [severity]=\"getProviderSeverity(file.location)\" />\n </td>\n <td class=\"hidden xl:table-cell\">{{ file.providerName || '-' }}</td>\n <td>\n @if (file.isPrivate) {\n <p-tag [value]=\"'storage.private' | translate\" severity=\"warn\" />\n } @else {\n <p-tag [value]=\"'storage.public' | translate\" severity=\"success\" />\n }\n </td>\n <td class=\"hidden md:table-cell\">{{ file.createdAt | date: 'short' }}</td>\n <td>\n <div class=\"flex gap-1\">\n <p-button *hasPermission=\"FILE_PERMISSIONS.READ\" icon=\"pi pi-eye\" [text]=\"true\" severity=\"secondary\" size=\"small\" [loading]=\"viewingFileId() === file.id\" [disabled]=\"viewingFileId() === file.id\" (onClick)=\"onView(file)\" [pTooltip]=\"'storage.tooltip.view' | translate\" tooltipPosition=\"top\" />\n <p-button *hasPermission=\"FILE_PERMISSIONS.UPDATE\" icon=\"pi pi-pencil\" [text]=\"true\" severity=\"secondary\" size=\"small\" (onClick)=\"onEdit(file.id)\" [pTooltip]=\"'storage.tooltip.edit' | translate\" tooltipPosition=\"top\" />\n <p-button *hasPermission=\"FILE_PERMISSIONS.DELETE\" icon=\"pi pi-trash\" [text]=\"true\" severity=\"warn\" size=\"small\" (onClick)=\"onSoftDelete(file)\" [pTooltip]=\"'storage.tooltip.trash' | translate\" tooltipPosition=\"top\" />\n <p-button *hasPermission=\"FILE_PERMISSIONS.DELETE\" icon=\"pi pi-times-circle\" [text]=\"true\" severity=\"danger\" size=\"small\" (onClick)=\"onPermanentDelete(file)\" [pTooltip]=\"'storage.tooltip.delete' | translate\" tooltipPosition=\"top\" />\n </div>\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"8\" class=\"text-center py-4 text-muted-color\">\n @if (showCompanyInfo()) {\n {{ 'storage.empty.files.in.company' | translate }}\n } @else {\n {{ 'storage.empty.files' | translate }}\n }\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n </div>\n `,\n})\nexport class FileManagerListComponent extends BaseStorageListPage<IFileManager> {\n readonly FILE_PERMISSIONS = FILE_PERMISSIONS;\n\n private readonly fileService = inject(FileManagerApiService);\n private readonly translateService = inject(TranslateService);\n\n readonly files = this.items;\n readonly viewingFileId = signal<string | null>(null);\n\n readonly getFileIcon = getFileIcon;\n readonly getProviderLabelKey = getProviderLabelKey;\n readonly getProviderSeverity = getProviderSeverity;\n\n getResourceRoute(): string {\n return '/storage/files';\n }\n\n override getDeleteConfirmMessage(file: IFileManager): string {\n return this.translateService.translate('storage.delete.confirm.named', { name: file.name });\n }\n\n async loadData(): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(\n this.fileService.getAll('', {\n pagination: this.getPaginationParams(),\n filter: {},\n select: [],\n sort: {},\n }),\n );\n\n if (response.success) {\n this.items.set(response.data ?? []);\n this.total.set(response.meta?.total ?? 0);\n }\n } catch {\n this.showError(this.translateService.translate('storage.error.load.failed'));\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onUpload(): void {\n this.navigateTo(['/storage/files/new']);\n }\n\n async onView(file: IFileManager): Promise<void> {\n this.viewingFileId.set(file.id);\n try {\n const response = await firstValueFrom(this.fileService.getFiles([file.id]));\n\n if (response.success && response.data?.length && response.data[0].url) {\n window.open(response.data[0].url, '_blank');\n } else {\n this.showError(this.translateService.translate('storage.file.url.not.available'));\n }\n } catch {\n this.showError(this.translateService.translate('storage.file.get.url.failed'));\n } finally {\n this.viewingFileId.set(null);\n }\n }\n\n onSoftDelete(file: IFileManager): void {\n this.confirmationService.confirm({\n message: this.translateService.translate('storage.delete.move.to.trash.confirm', { name: file.name }),\n header: this.translateService.translate('storage.delete.move.to.trash'),\n icon: 'pi pi-trash',\n acceptLabel: this.translateService.translate('storage.delete.move.to.trash'),\n acceptButtonStyleClass: 'p-button-warning',\n accept: async () => {\n try {\n await this.fileService.deleteAsync({ id: file.id, type: 'delete' });\n this.showSuccess(this.translateService.translate('storage.delete.trash.success'));\n this.loadData();\n } catch {\n this.showError(this.translateService.translate('storage.delete.trash.failed'));\n }\n },\n });\n }\n\n onPermanentDelete(file: IFileManager): void {\n this.confirmationService.confirm({\n message: this.translateService.translate('storage.delete.permanent.delete.confirm', { name: file.name }),\n header: this.translateService.translate('storage.delete.permanent.delete'),\n icon: 'pi pi-exclamation-triangle',\n acceptLabel: this.translateService.translate('storage.delete.permanent.delete.button'),\n rejectLabel: this.translateService.translate('shared.cancel'),\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n try {\n await this.fileService.deleteAsync({ id: file.id, type: 'permanent' });\n this.showSuccess(this.translateService.translate('storage.delete.permanent.success'));\n this.loadData();\n } catch {\n this.showError(this.translateService.translate('storage.delete.permanent.failed'));\n }\n },\n });\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,42 +1,33 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
2
+ import { inject, signal, computed, effect, Component } from '@angular/core';
3
3
  import { toSignal } from '@angular/core/rxjs-interop';
4
4
  import { form, required, FormField } from '@angular/forms/signals';
5
5
  import { ActivatedRoute } from '@angular/router';
6
- import { AngularModule, PrimeModule } from '@flusys/ng-shared';
6
+ import { TranslateService } from '@flusys/ng-localization';
7
+ import { AngularModule, PrimeModule, TranslatePipe } from '@flusys/ng-shared';
7
8
  import { BaseStoragePage, FolderApiService } from './flusys-ng-storage.mjs';
8
9
  import * as i1 from '@angular/forms';
9
10
  import * as i1$1 from 'primeng/button';
10
11
  import * as i3 from 'primeng/inputtext';
11
12
 
12
- /**
13
- * Folder Form Component
14
- * Create and edit folders
15
- */
16
13
  class FolderFormComponent extends BaseStoragePage {
17
14
  route = inject(ActivatedRoute);
18
15
  folderService = inject(FolderApiService);
19
- // Route params as signal
16
+ translateService = inject(TranslateService);
20
17
  routeParams = toSignal(this.route.paramMap);
21
18
  initialized = false;
22
- /** Existing folder for edit mode */
23
19
  existingFolder = signal(null, ...(ngDevMode ? [{ debugName: "existingFolder" }] : []));
24
- /** Check if in edit mode */
25
20
  isEditMode = computed(() => !!this.existingFolder(), ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
26
- /** Form model */
27
21
  formModel = signal({
28
22
  id: '',
29
23
  name: '',
30
24
  }, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
31
- /** Form with validation */
32
25
  folderForm = form(this.formModel, (f) => {
33
- required(f.name, { message: 'Folder name is required' });
26
+ required(f.name, { message: this.translateService.translate('storage.validation.folder.name.required') });
34
27
  });
35
- /** Check if form is valid */
36
28
  isFormValid = computed(() => this.formModel().name.trim().length > 0, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
37
29
  constructor() {
38
30
  super();
39
- // Effect to handle route-based initialization
40
31
  effect(() => {
41
32
  const params = this.routeParams();
42
33
  if (!params || this.initialized)
@@ -59,7 +50,7 @@ class FolderFormComponent extends BaseStoragePage {
59
50
  }
60
51
  }
61
52
  catch {
62
- this.showError('Failed to load folder.');
53
+ this.showError(this.translateService.translate('storage.folder.load.failed'));
63
54
  this.navigateTo(['/storage/folders']);
64
55
  }
65
56
  finally {
@@ -74,16 +65,17 @@ class FolderFormComponent extends BaseStoragePage {
74
65
  const formValue = this.formModel();
75
66
  if (this.isEditMode()) {
76
67
  await this.folderService.updateAsync({ id: formValue.id, name: formValue.name });
77
- this.showSuccess('Folder updated successfully.');
68
+ this.showSuccess(this.translateService.translate('storage.folder.update.success'));
78
69
  }
79
70
  else {
80
71
  await this.folderService.insertAsync({ name: formValue.name });
81
- this.showSuccess('Folder created successfully.');
72
+ this.showSuccess(this.translateService.translate('storage.folder.create.success'));
82
73
  }
83
74
  this.navigateTo(['/storage/folders']);
84
75
  }
85
76
  catch {
86
- this.showError(`Failed to ${this.isEditMode() ? 'update' : 'create'} folder.`);
77
+ const action = this.isEditMode() ? 'update' : 'create';
78
+ this.showError(this.translateService.translate(`storage.folder.${action}.failed`));
87
79
  }
88
80
  finally {
89
81
  this.isLoading.set(false);
@@ -96,54 +88,53 @@ class FolderFormComponent extends BaseStoragePage {
96
88
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: FolderFormComponent, isStandalone: true, selector: "lib-folder-form", usesInheritance: true, ngImport: i0, template: `
97
89
  <div class="card">
98
90
  <div class="mb-4">
99
- <h3 class="text-lg sm:text-xl font-semibold">{{ isEditMode() ? 'Edit Folder' : 'New Folder' }}</h3>
91
+ <h3 class="text-lg sm:text-xl font-semibold">{{ (isEditMode() ? 'storage.folder.edit.folder' : 'storage.folder.new.folder') | translate }}</h3>
100
92
  @if (showCompanyInfo()) {
101
- <p class="text-sm text-muted-color mt-1">Company: {{ currentCompanyName() }}</p>
93
+ <p class="text-sm text-muted-color mt-1">{{ 'storage.company' | translate }}: {{ currentCompanyName() }}</p>
102
94
  }
103
95
  </div>
104
96
 
105
97
  <form (ngSubmit)="onSubmit()">
106
98
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
107
99
  <div class="field">
108
- <label for="name" class="block font-medium mb-2 text-sm sm:text-base">Folder Name *</label>
109
- <input pInputText id="name" [formField]="folderForm.name" placeholder="Enter folder name" class="w-full" />
100
+ <label for="name" class="block font-medium mb-2 text-sm sm:text-base">{{ 'storage.folder.name.required' | translate }}</label>
101
+ <input pInputText id="name" [formField]="folderForm.name" [placeholder]="'storage.folder.name.placeholder' | translate" class="w-full" />
110
102
  </div>
111
103
  </div>
112
104
 
113
105
  <div class="flex justify-end gap-2 mt-4">
114
- <p-button label="Cancel" severity="secondary" [outlined]="true" (onClick)="onCancel()" />
115
- <p-button type="submit" [label]="isEditMode() ? 'Update' : 'Create'" [loading]="isLoading()" [disabled]="!isFormValid() || isLoading()" />
106
+ <p-button [label]="'shared.cancel' | translate" severity="secondary" [outlined]="true" (onClick)="onCancel()" />
107
+ <p-button type="submit" [label]="(isEditMode() ? 'shared.update' : 'shared.create') | translate" [loading]="isLoading()" [disabled]="!isFormValid() || isLoading()" />
116
108
  </div>
117
109
  </form>
118
110
  </div>
119
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { 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.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
111
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { 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.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1$1.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
120
112
  }
121
113
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FolderFormComponent, decorators: [{
122
114
  type: Component,
123
115
  args: [{
124
116
  selector: 'lib-folder-form',
125
- changeDetection: ChangeDetectionStrategy.OnPush,
126
- imports: [AngularModule, PrimeModule, FormField],
117
+ imports: [AngularModule, PrimeModule, FormField, TranslatePipe],
127
118
  template: `
128
119
  <div class="card">
129
120
  <div class="mb-4">
130
- <h3 class="text-lg sm:text-xl font-semibold">{{ isEditMode() ? 'Edit Folder' : 'New Folder' }}</h3>
121
+ <h3 class="text-lg sm:text-xl font-semibold">{{ (isEditMode() ? 'storage.folder.edit.folder' : 'storage.folder.new.folder') | translate }}</h3>
131
122
  @if (showCompanyInfo()) {
132
- <p class="text-sm text-muted-color mt-1">Company: {{ currentCompanyName() }}</p>
123
+ <p class="text-sm text-muted-color mt-1">{{ 'storage.company' | translate }}: {{ currentCompanyName() }}</p>
133
124
  }
134
125
  </div>
135
126
 
136
127
  <form (ngSubmit)="onSubmit()">
137
128
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
138
129
  <div class="field">
139
- <label for="name" class="block font-medium mb-2 text-sm sm:text-base">Folder Name *</label>
140
- <input pInputText id="name" [formField]="folderForm.name" placeholder="Enter folder name" class="w-full" />
130
+ <label for="name" class="block font-medium mb-2 text-sm sm:text-base">{{ 'storage.folder.name.required' | translate }}</label>
131
+ <input pInputText id="name" [formField]="folderForm.name" [placeholder]="'storage.folder.name.placeholder' | translate" class="w-full" />
141
132
  </div>
142
133
  </div>
143
134
 
144
135
  <div class="flex justify-end gap-2 mt-4">
145
- <p-button label="Cancel" severity="secondary" [outlined]="true" (onClick)="onCancel()" />
146
- <p-button type="submit" [label]="isEditMode() ? 'Update' : 'Create'" [loading]="isLoading()" [disabled]="!isFormValid() || isLoading()" />
136
+ <p-button [label]="'shared.cancel' | translate" severity="secondary" [outlined]="true" (onClick)="onCancel()" />
137
+ <p-button type="submit" [label]="(isEditMode() ? 'shared.update' : 'shared.create') | translate" [loading]="isLoading()" [disabled]="!isFormValid() || isLoading()" />
147
138
  </div>
148
139
  </form>
149
140
  </div>
@@ -152,4 +143,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
152
143
  }], ctorParameters: () => [] });
153
144
 
154
145
  export { FolderFormComponent };
155
- //# sourceMappingURL=flusys-ng-storage-folder-form.component-BTQGEqNu.mjs.map
146
+ //# sourceMappingURL=flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs","sources":["../../../projects/ng-storage/pages/folder/folder-form.component.ts"],"sourcesContent":["import { Component, computed, effect, inject, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute } from '@angular/router';\nimport { TranslateService } from '@flusys/ng-localization';\nimport { AngularModule, PrimeModule, TranslatePipe } from '@flusys/ng-shared';\nimport { IFolder } from '../../interfaces/folder.interface';\nimport { FolderApiService } from '../../services/folder-api.service';\nimport { BaseStoragePage } from '../../utils/base-storage-page';\n\ninterface IFolderFormModel {\n id: string;\n name: string;\n}\n\n@Component({\n selector: 'lib-folder-form',\n imports: [AngularModule, PrimeModule, FormField, TranslatePipe],\n template: `\n <div class=\"card\">\n <div class=\"mb-4\">\n <h3 class=\"text-lg sm:text-xl font-semibold\">{{ (isEditMode() ? 'storage.folder.edit.folder' : 'storage.folder.new.folder') | translate }}</h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">{{ 'storage.company' | translate }}: {{ currentCompanyName() }}</p>\n }\n </div>\n\n <form (ngSubmit)=\"onSubmit()\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"field\">\n <label for=\"name\" class=\"block font-medium mb-2 text-sm sm:text-base\">{{ 'storage.folder.name.required' | translate }}</label>\n <input pInputText id=\"name\" [formField]=\"folderForm.name\" [placeholder]=\"'storage.folder.name.placeholder' | translate\" class=\"w-full\" />\n </div>\n </div>\n\n <div class=\"flex justify-end gap-2 mt-4\">\n <p-button [label]=\"'shared.cancel' | translate\" severity=\"secondary\" [outlined]=\"true\" (onClick)=\"onCancel()\" />\n <p-button type=\"submit\" [label]=\"(isEditMode() ? 'shared.update' : 'shared.create') | translate\" [loading]=\"isLoading()\" [disabled]=\"!isFormValid() || isLoading()\" />\n </div>\n </form>\n </div>\n `,\n})\nexport class FolderFormComponent extends BaseStoragePage {\n private readonly route = inject(ActivatedRoute);\n private readonly folderService = inject(FolderApiService);\n private readonly translateService = inject(TranslateService);\n\n private readonly routeParams = toSignal(this.route.paramMap);\n private initialized = false;\n\n readonly existingFolder = signal<IFolder | null>(null);\n readonly isEditMode = computed(() => !!this.existingFolder());\n\n readonly formModel = signal<IFolderFormModel>({\n id: '',\n name: '',\n });\n\n readonly folderForm = form(this.formModel, (f) => {\n required(f.name, { message: this.translateService.translate('storage.validation.folder.name.required') });\n });\n\n readonly isFormValid = computed(() => this.formModel().name.trim().length > 0);\n\n constructor() {\n super();\n effect(() => {\n const params = this.routeParams();\n if (!params || this.initialized) return;\n\n this.initialized = true;\n const folderId = params.get('id');\n if (folderId && folderId !== 'new') {\n this.loadFolder(folderId);\n }\n });\n }\n\n async loadFolder(id: string): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await this.folderService.findByIdAsync(id);\n if (response.success && response.data) {\n const folder = response.data;\n this.existingFolder.set(folder);\n this.formModel.set({ id: folder.id, name: folder.name });\n }\n } catch {\n this.showError(this.translateService.translate('storage.folder.load.failed'));\n this.navigateTo(['/storage/folders']);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n async onSubmit(): Promise<void> {\n if (!this.isFormValid()) return;\n\n this.isLoading.set(true);\n try {\n const formValue = this.formModel();\n\n if (this.isEditMode()) {\n await this.folderService.updateAsync({ id: formValue.id, name: formValue.name });\n this.showSuccess(this.translateService.translate('storage.folder.update.success'));\n } else {\n await this.folderService.insertAsync({ name: formValue.name });\n this.showSuccess(this.translateService.translate('storage.folder.create.success'));\n }\n\n this.navigateTo(['/storage/folders']);\n } catch {\n const action = this.isEditMode() ? 'update' : 'create';\n this.showError(this.translateService.translate(`storage.folder.${action}.failed`));\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onCancel(): void {\n this.navigateTo(['/storage/folders']);\n }\n}\n"],"names":["i2"],"mappings":"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"}