@flusys/ng-storage 1.1.1-beta → 3.0.0-rc

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 (27) hide show
  1. package/README.md +142 -5
  2. package/fesm2022/{flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs → flusys-ng-storage-file-manager-form.component-Bv8ER8J0.mjs} +110 -341
  3. package/fesm2022/flusys-ng-storage-file-manager-form.component-Bv8ER8J0.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-storage-file-manager-list.component-McM1zSlE.mjs +304 -0
  5. package/fesm2022/flusys-ng-storage-file-manager-list.component-McM1zSlE.mjs.map +1 -0
  6. package/fesm2022/flusys-ng-storage-folder-form.component-fRFiMFev.mjs +155 -0
  7. package/fesm2022/flusys-ng-storage-folder-form.component-fRFiMFev.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-storage-folder-list.component-C4xHI8SO.mjs +194 -0
  9. package/fesm2022/flusys-ng-storage-folder-list.component-C4xHI8SO.mjs.map +1 -0
  10. package/fesm2022/{flusys-ng-storage-storage-config-form.component-CjIAxfHC.mjs → flusys-ng-storage-storage-config-form.component-DEMexjmg.mjs} +217 -300
  11. package/fesm2022/flusys-ng-storage-storage-config-form.component-DEMexjmg.mjs.map +1 -0
  12. package/fesm2022/flusys-ng-storage-storage-config-list.component-iJez-rII.mjs +187 -0
  13. package/fesm2022/flusys-ng-storage-storage-config-list.component-iJez-rII.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-storage.mjs +247 -204
  15. package/fesm2022/flusys-ng-storage.mjs.map +1 -1
  16. package/package.json +5 -5
  17. package/types/flusys-ng-storage.d.ts +101 -151
  18. package/fesm2022/flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs.map +0 -1
  19. package/fesm2022/flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs +0 -475
  20. package/fesm2022/flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs.map +0 -1
  21. package/fesm2022/flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs +0 -253
  22. package/fesm2022/flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-storage-folder-list.component-D-oMaEgl.mjs +0 -267
  24. package/fesm2022/flusys-ng-storage-folder-list.component-D-oMaEgl.mjs.map +0 -1
  25. package/fesm2022/flusys-ng-storage-storage-config-form.component-CjIAxfHC.mjs.map +0 -1
  26. package/fesm2022/flusys-ng-storage-storage-config-list.component-jHk8O9Mx.mjs +0 -328
  27. package/fesm2022/flusys-ng-storage-storage-config-list.component-jHk8O9Mx.mjs.map +0 -1
@@ -1,13 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, Component } from '@angular/core';
2
+ import { inject, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { toSignal } from '@angular/core/rxjs-interop';
3
4
  import { form, required, FormField } from '@angular/forms/signals';
4
- import { Router, ActivatedRoute } from '@angular/router';
5
- import { APP_CONFIG, DEFAULT_APP_NAME } from '@flusys/ng-core';
6
- import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
5
+ import { ActivatedRoute } from '@angular/router';
7
6
  import { AngularModule, PrimeModule } from '@flusys/ng-shared';
8
- import { MessageService } from 'primeng/api';
9
7
  import { firstValueFrom } from 'rxjs';
10
- import { FileManagerApiService, UploadService, StorageConfigApiService, FolderApiService } from './flusys-ng-storage.mjs';
8
+ import { BaseStoragePage, FileManagerApiService, UploadService, StorageConfigApiService, FolderApiService, formatFileSize, getProviderLabel } from './flusys-ng-storage.mjs';
11
9
  import * as i1 from '@angular/forms';
12
10
  import * as i1$1 from 'primeng/button';
13
11
  import * as i3 from 'primeng/fileupload';
@@ -17,17 +15,14 @@ import * as i3$1 from 'primeng/inputtext';
17
15
  * File Manager Form Component
18
16
  * Upload and edit file metadata
19
17
  */
20
- class FileManagerFormComponent {
21
- router = inject(Router);
18
+ class FileManagerFormComponent extends BaseStoragePage {
22
19
  route = inject(ActivatedRoute);
23
- messageService = inject(MessageService);
24
20
  fileService = inject(FileManagerApiService);
25
21
  uploadService = inject(UploadService);
26
22
  configService = inject(StorageConfigApiService);
27
23
  folderService = inject(FolderApiService);
28
- appConfig = inject(APP_CONFIG);
29
- companyContext = inject(LAYOUT_AUTH_STATE);
30
- isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
24
+ routeParams = toSignal(this.route.paramMap);
25
+ initialized = false;
31
26
  isLoadingConfigs = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingConfigs" }] : []));
32
27
  isLoadingFolders = signal(false, ...(ngDevMode ? [{ debugName: "isLoadingFolders" }] : []));
33
28
  existingFile = signal(null, ...(ngDevMode ? [{ debugName: "existingFile" }] : []));
@@ -35,11 +30,9 @@ class FileManagerFormComponent {
35
30
  selectedFile = signal(null, ...(ngDevMode ? [{ debugName: "selectedFile" }] : []));
36
31
  availableConfigs = signal([], ...(ngDevMode ? [{ debugName: "availableConfigs" }] : []));
37
32
  availableFolders = signal([], ...(ngDevMode ? [{ debugName: "availableFolders" }] : []));
38
- showCompanyInfo = computed(() => this.appConfig.enableCompanyFeature, ...(ngDevMode ? [{ debugName: "showCompanyInfo" }] : []));
39
- currentCompanyName = computed(() => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME, ...(ngDevMode ? [{ debugName: "currentCompanyName" }] : []));
40
- // ============================================
41
- // Form (Signal Forms)
42
- // ============================================
33
+ /** Utility functions exposed to template */
34
+ formatFileSize = formatFileSize;
35
+ getProviderLabel = getProviderLabel;
43
36
  /** Form model */
44
37
  formModel = signal({
45
38
  id: '',
@@ -48,28 +41,28 @@ class FileManagerFormComponent {
48
41
  folderId: '',
49
42
  storageConfigId: '',
50
43
  }, ...(ngDevMode ? [{ debugName: "formModel" }] : []));
51
- /** Form with validation schema */
44
+ /** Form with validation */
52
45
  fileForm = form(this.formModel, (f) => {
53
46
  required(f.name, { message: 'File name is required' });
54
- // storageConfigId validation will be done manually in onSubmit
55
- // as it's only required for new uploads, not edits
56
47
  });
57
48
  /** Check if form is valid */
58
- isFormValid = computed(() => {
59
- const model = this.formModel();
60
- return model.name.trim().length > 0;
61
- }, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
62
- ngOnInit() {
63
- const fileId = this.route.snapshot.paramMap.get('id');
64
- if (fileId) {
65
- this.loadFile(fileId);
66
- }
67
- else {
68
- // Load storage configurations for new upload
69
- this.loadStorageConfigs();
70
- }
71
- // Load folders for both create and edit modes
72
- this.loadFolders();
49
+ isFormValid = computed(() => this.formModel().name.trim().length > 0, ...(ngDevMode ? [{ debugName: "isFormValid" }] : []));
50
+ constructor() {
51
+ super();
52
+ effect(() => {
53
+ const params = this.routeParams();
54
+ if (!params || this.initialized)
55
+ return;
56
+ this.initialized = true;
57
+ const fileId = params.get('id');
58
+ if (fileId) {
59
+ this.loadFile(fileId);
60
+ }
61
+ else {
62
+ this.loadStorageConfigs();
63
+ }
64
+ this.loadFolders();
65
+ });
73
66
  }
74
67
  async loadStorageConfigs() {
75
68
  this.isLoadingConfigs.set(true);
@@ -82,21 +75,13 @@ class FileManagerFormComponent {
82
75
  }));
83
76
  if (response.success && response.data) {
84
77
  this.availableConfigs.set(response.data);
85
- // Auto-select first config if only one available
86
78
  if (response.data.length === 1) {
87
- this.formModel.update((m) => ({
88
- ...m,
89
- storageConfigId: response.data[0].id,
90
- }));
79
+ this.formModel.update((m) => ({ ...m, storageConfigId: response.data[0].id }));
91
80
  }
92
81
  }
93
82
  }
94
- catch (error) {
95
- this.messageService.add({
96
- severity: 'error',
97
- summary: 'Error',
98
- detail: 'Failed to load storage configurations.',
99
- });
83
+ catch {
84
+ this.showError('Failed to load storage configurations.');
100
85
  }
101
86
  finally {
102
87
  this.isLoadingConfigs.set(false);
@@ -138,13 +123,9 @@ class FileManagerFormComponent {
138
123
  });
139
124
  }
140
125
  }
141
- catch (error) {
142
- this.messageService.add({
143
- severity: 'error',
144
- summary: 'Error',
145
- detail: 'Failed to load file.',
146
- });
147
- this.router.navigate(['/storage/files']);
126
+ catch {
127
+ this.showError('Failed to load file.');
128
+ this.navigateTo(['/storage/files']);
148
129
  }
149
130
  finally {
150
131
  this.isLoading.set(false);
@@ -154,7 +135,6 @@ class FileManagerFormComponent {
154
135
  const file = event.files?.[0] || event.currentFiles?.[0];
155
136
  if (file) {
156
137
  this.selectedFile.set(file);
157
- // Auto-fill file name
158
138
  this.formModel.update((m) => ({ ...m, name: file.name }));
159
139
  }
160
140
  }
@@ -165,40 +145,24 @@ class FileManagerFormComponent {
165
145
  try {
166
146
  const formValue = this.formModel();
167
147
  if (this.isEditMode()) {
168
- // Update existing file metadata only
169
148
  await this.fileService.updateAsync({
170
149
  id: formValue.id,
171
150
  name: formValue.name,
172
151
  isPrivate: formValue.isPrivate,
173
152
  folderId: formValue.folderId || null,
174
153
  });
175
- this.messageService.add({
176
- severity: 'success',
177
- summary: 'Success',
178
- detail: 'File updated successfully.',
179
- });
154
+ this.showSuccess('File updated successfully.');
180
155
  }
181
156
  else {
182
- // Upload new file
183
157
  const file = this.selectedFile();
184
158
  if (!file) {
185
- this.messageService.add({
186
- severity: 'error',
187
- summary: 'Error',
188
- detail: 'Please select a file to upload.',
189
- });
159
+ this.showError('Please select a file to upload.');
190
160
  return;
191
161
  }
192
- // Validate storage config selection
193
162
  if (!formValue.storageConfigId) {
194
- this.messageService.add({
195
- severity: 'error',
196
- summary: 'Error',
197
- detail: 'Please select a storage configuration.',
198
- });
163
+ this.showError('Please select a storage configuration.');
199
164
  return;
200
165
  }
201
- // Upload file first
202
166
  const uploadResponse = await firstValueFrom(this.uploadService.uploadSingleFile(file, {
203
167
  compress: true,
204
168
  quality: 85,
@@ -206,102 +170,52 @@ class FileManagerFormComponent {
206
170
  }));
207
171
  if (uploadResponse.success && uploadResponse.data) {
208
172
  const uploadedFileInfo = uploadResponse.data;
209
- // Save file metadata
210
- await this.fileService.insertAsync({
173
+ await this.fileService.createFileAsync({
211
174
  name: formValue.name,
212
175
  key: uploadedFileInfo.key,
213
176
  contentType: file.type || 'application/octet-stream',
214
177
  size: Math.round(file.size / 1024).toString(),
215
178
  isPrivate: formValue.isPrivate,
216
179
  folderId: formValue.folderId || undefined,
217
- storageConfigId: formValue.storageConfigId, // ✅ Include storage config ID
218
- });
219
- this.messageService.add({
220
- severity: 'success',
221
- summary: 'Success',
222
- detail: 'File uploaded successfully.',
180
+ storageConfigId: formValue.storageConfigId,
223
181
  });
182
+ this.showSuccess('File uploaded successfully.');
224
183
  }
225
184
  else {
226
185
  throw new Error('Upload failed');
227
186
  }
228
187
  }
229
- this.router.navigate(['/storage/files']);
188
+ this.navigateTo(['/storage/files']);
230
189
  }
231
190
  catch (error) {
232
- this.messageService.add({
233
- severity: 'error',
234
- summary: 'Error',
235
- detail: error?.message ||
236
- `Failed to ${this.isEditMode() ? 'update' : 'upload'} file.`,
237
- });
191
+ this.showError(error?.message || `Failed to ${this.isEditMode() ? 'update' : 'upload'} file.`);
238
192
  }
239
193
  finally {
240
194
  this.isLoading.set(false);
241
195
  }
242
196
  }
243
197
  onCancel() {
244
- this.router.navigate(['/storage/files']);
245
- }
246
- formatFileSize(bytes) {
247
- if (bytes === 0)
248
- return '0 Bytes';
249
- const k = 1024;
250
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
251
- const i = Math.floor(Math.log(bytes) / Math.log(k));
252
- return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
253
- }
254
- getProviderLabel(storage) {
255
- const labels = {
256
- AWS: 'AWS S3',
257
- AZURE: 'Azure Blob',
258
- SFTP: 'SFTP',
259
- LOCAL: 'Local',
260
- };
261
- return labels[storage] || storage;
198
+ this.navigateTo(['/storage/files']);
262
199
  }
263
200
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileManagerFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
264
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: FileManagerFormComponent, isStandalone: true, selector: "lib-file-manager-form", ngImport: i0, template: `
201
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: FileManagerFormComponent, isStandalone: true, selector: "lib-file-manager-form", usesInheritance: true, ngImport: i0, template: `
265
202
  <div class="card">
266
- <div class="flex justify-between items-center mb-4">
267
- <div>
268
- <h3 class="text-xl font-semibold">
269
- {{ isEditMode() ? 'Edit File' : 'Upload File' }}
270
- </h3>
271
- @if (showCompanyInfo()) {
272
- <p class="text-sm text-muted-color mt-1">
273
- Company: {{ currentCompanyName() }}
274
- </p>
275
- }
276
- </div>
277
- <p-button
278
- label="Back"
279
- icon="pi pi-arrow-left"
280
- severity="secondary"
281
- [text]="true"
282
- (onClick)="onCancel()"
283
- />
203
+ <div class="mb-4">
204
+ <h3 class="text-lg sm:text-xl font-semibold">{{ isEditMode() ? 'Edit File' : 'Upload File' }}</h3>
205
+ @if (showCompanyInfo()) {
206
+ <p class="text-sm text-muted-color mt-1">Company: {{ currentCompanyName() }}</p>
207
+ }
284
208
  </div>
285
209
 
286
210
  <form (ngSubmit)="onSubmit()">
287
- <!-- Storage Configuration & Folder Selection (only for new files) -->
288
211
  @if (!isEditMode()) {
289
212
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
290
- <!-- Storage Configuration -->
291
213
  <div class="field">
292
- <label for="storageConfig" class="block font-medium mb-2"
293
- >Storage Configuration *</label
294
- >
295
- <select
296
- id="storageConfig"
297
- class="p-select-native"
298
- [formField]="fileForm.storageConfigId"
299
- >
214
+ <label for="storageConfig" class="block font-medium mb-2 text-sm sm:text-base">Storage Configuration *</label>
215
+ <select id="storageConfig" class="p-select-native w-full" [formField]="fileForm.storageConfigId">
300
216
  <option value="">Select storage configuration...</option>
301
217
  @for (config of availableConfigs(); track config.id) {
302
- <option [value]="config.id">
303
- {{ config.name }} ({{ getProviderLabel(config.storage) }})
304
- </option>
218
+ <option [value]="config.id">{{ config.name }} ({{ getProviderLabel(config.storage) }})</option>
305
219
  }
306
220
  </select>
307
221
  @if (availableConfigs().length === 0 && !isLoadingConfigs()) {
@@ -312,16 +226,9 @@ class FileManagerFormComponent {
312
226
  }
313
227
  </div>
314
228
 
315
- <!-- Folder Selection -->
316
229
  <div class="field">
317
- <label for="folder" class="block font-medium mb-2"
318
- >Folder (Optional)</label
319
- >
320
- <select
321
- id="folder"
322
- class="p-select-native"
323
- [formField]="fileForm.folderId"
324
- >
230
+ <label for="folder" class="block font-medium mb-2 text-sm sm:text-base">Folder (Optional)</label>
231
+ <select id="folder" class="p-select-native w-full" [formField]="fileForm.folderId">
325
232
  <option value="">No folder (root level)</option>
326
233
  @for (folder of availableFolders(); track folder.id) {
327
234
  <option [value]="folder.id">{{ folder.name }}</option>
@@ -336,16 +243,9 @@ class FileManagerFormComponent {
336
243
  </div>
337
244
  </div>
338
245
  } @else {
339
- <!-- Folder Selection for Edit Mode -->
340
246
  <div class="field mb-4">
341
- <label for="folder" class="block font-medium mb-2"
342
- >Folder (Optional)</label
343
- >
344
- <select
345
- id="folder"
346
- class="p-select-native"
347
- [formField]="fileForm.folderId"
348
- >
247
+ <label for="folder" class="block font-medium mb-2 text-sm sm:text-base">Folder (Optional)</label>
248
+ <select id="folder" class="p-select-native w-full" [formField]="fileForm.folderId">
349
249
  <option value="">No folder (root level)</option>
350
250
  @for (folder of availableFolders(); track folder.id) {
351
251
  <option [value]="folder.id">{{ folder.name }}</option>
@@ -360,10 +260,9 @@ class FileManagerFormComponent {
360
260
  </div>
361
261
  }
362
262
 
363
- <!-- File Upload (only for new files) -->
364
263
  @if (!isEditMode()) {
365
264
  <div class="field mb-4">
366
- <label class="block font-medium mb-2">Select File *</label>
265
+ <label class="block font-medium mb-2 text-sm sm:text-base">Select File *</label>
367
266
  <p-fileupload
368
267
  #fileUpload
369
268
  [customUpload]="true"
@@ -381,154 +280,85 @@ class FileManagerFormComponent {
381
280
  @if (files && files.length > 0) {
382
281
  <div class="flex flex-col gap-2">
383
282
  @for (file of files; track file.name) {
384
- <div class="flex items-center gap-3 p-3 border rounded">
385
- <i class="pi pi-file text-2xl"></i>
386
- <div class="flex-1">
387
- <div class="font-medium">{{ file.name }}</div>
388
- <div class="text-sm text-muted-color">
389
- {{ formatFileSize(file.size) }}
390
- </div>
283
+ <div class="flex items-center gap-3 p-3 border border-surface rounded-lg bg-surface-ground">
284
+ <i class="pi pi-file text-xl sm:text-2xl text-primary"></i>
285
+ <div class="flex-1 min-w-0">
286
+ <div class="font-medium truncate">{{ file.name }}</div>
287
+ <div class="text-sm text-muted-color">{{ formatFileSize(file.size) }}</div>
391
288
  </div>
392
- <p-button
393
- icon="pi pi-times"
394
- [text]="true"
395
- severity="danger"
396
- size="small"
397
- (onClick)="fileUpload.clear()"
398
- />
289
+ <p-button icon="pi pi-times" [text]="true" severity="danger" size="small" (onClick)="fileUpload.clear()" />
399
290
  </div>
400
291
  }
401
292
  </div>
402
293
  } @else {
403
- <div
404
- class="flex items-center justify-center flex-col p-8 border-2 border-dashed border-surface-300 rounded"
405
- >
406
- <i
407
- class="pi pi-cloud-upload text-4xl text-muted-color mb-3"
408
- ></i>
409
- <p class="text-muted-color">
410
- Drag and drop file here or click to browse
411
- </p>
412
- <p class="text-sm text-muted-color mt-2">
413
- Maximum file size: 50MB
414
- </p>
294
+ <div class="flex items-center justify-center flex-col p-6 sm:p-8 border-2 border-dashed border-surface rounded-lg">
295
+ <i class="pi pi-cloud-upload text-3xl sm:text-4xl text-muted-color mb-3"></i>
296
+ <p class="text-muted-color text-center text-sm sm:text-base">Drag and drop file here or click to browse</p>
297
+ <p class="text-xs sm:text-sm text-muted-color mt-2">Maximum file size: 50MB</p>
415
298
  </div>
416
299
  }
417
300
  </ng-template>
418
301
  </p-fileupload>
419
302
  @if (!selectedFile() && !isEditMode()) {
420
- <small class="text-muted-color"
421
- >Please select a file to upload</small
422
- >
303
+ <small class="text-muted-color">Please select a file to upload</small>
423
304
  }
424
305
  </div>
425
306
  }
426
307
 
427
308
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
428
- <!-- File Name (read-only for uploads, editable for existing) -->
429
309
  <div class="field md:col-span-2">
430
- <label for="name" class="block font-medium mb-2">File Name *</label>
431
- <input
432
- pInputText
433
- id="name"
434
- [formField]="fileForm.name"
435
- [placeholder]="
436
- isEditMode()
437
- ? 'Enter file name'
438
- : 'Will be auto-filled from selected file'
439
- "
440
- class="w-full"
441
- />
310
+ <label for="name" class="block font-medium mb-2 text-sm sm:text-base">File Name *</label>
311
+ <input pInputText id="name" [formField]="fileForm.name" [placeholder]="isEditMode() ? 'Enter file name' : 'Will be auto-filled from selected file'" class="w-full" />
442
312
  </div>
443
313
 
444
- <!-- Privacy Toggle -->
445
314
  <div class="field">
446
- <label class="p-checkbox-native">
315
+ <label class="p-checkbox-native flex items-center gap-2">
447
316
  <input type="checkbox" [formField]="fileForm.isPrivate" />
448
317
  <span>Private File</span>
449
318
  </label>
450
319
  <small class="text-muted-color block mt-2">
451
- {{
452
- formModel().isPrivate
453
- ? 'Only users with permission can access'
454
- : 'File is publicly accessible'
455
- }}
320
+ {{ formModel().isPrivate ? 'Only users with permission can access' : 'File is publicly accessible' }}
456
321
  </small>
457
322
  </div>
458
323
  </div>
459
324
 
460
- <div class="flex gap-2 mt-4">
325
+ <div class="flex justify-end gap-2 mt-4">
326
+ <p-button label="Cancel" severity="secondary" [outlined]="true" (onClick)="onCancel()" />
461
327
  <p-button
462
328
  type="submit"
463
329
  [label]="isEditMode() ? 'Update' : 'Upload'"
464
- [icon]="isEditMode() ? 'pi pi-check' : 'pi pi-cloud-upload'"
465
330
  [loading]="isLoading()"
466
- [disabled]="
467
- !isFormValid() ||
468
- (!isEditMode() && !selectedFile()) ||
469
- isLoading()
470
- "
471
- />
472
- <p-button
473
- type="button"
474
- label="Cancel"
475
- severity="secondary"
476
- icon="pi pi-times"
477
- [text]="true"
478
- (onClick)="onCancel()"
331
+ [disabled]="!isFormValid() || (!isEditMode() && !selectedFile()) || isLoading()"
479
332
  />
480
333
  </div>
481
334
  </form>
482
335
  </div>
483
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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: "component", type: i3.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "directive", type: i3$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }] });
336
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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: "component", type: i3.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "directive", type: i3$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
484
337
  }
485
338
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileManagerFormComponent, decorators: [{
486
339
  type: Component,
487
340
  args: [{
488
341
  selector: 'lib-file-manager-form',
489
- standalone: true,
342
+ changeDetection: ChangeDetectionStrategy.OnPush,
490
343
  imports: [AngularModule, PrimeModule, FormField],
491
344
  template: `
492
345
  <div class="card">
493
- <div class="flex justify-between items-center mb-4">
494
- <div>
495
- <h3 class="text-xl font-semibold">
496
- {{ isEditMode() ? 'Edit File' : 'Upload File' }}
497
- </h3>
498
- @if (showCompanyInfo()) {
499
- <p class="text-sm text-muted-color mt-1">
500
- Company: {{ currentCompanyName() }}
501
- </p>
502
- }
503
- </div>
504
- <p-button
505
- label="Back"
506
- icon="pi pi-arrow-left"
507
- severity="secondary"
508
- [text]="true"
509
- (onClick)="onCancel()"
510
- />
346
+ <div class="mb-4">
347
+ <h3 class="text-lg sm:text-xl font-semibold">{{ isEditMode() ? 'Edit File' : 'Upload File' }}</h3>
348
+ @if (showCompanyInfo()) {
349
+ <p class="text-sm text-muted-color mt-1">Company: {{ currentCompanyName() }}</p>
350
+ }
511
351
  </div>
512
352
 
513
353
  <form (ngSubmit)="onSubmit()">
514
- <!-- Storage Configuration & Folder Selection (only for new files) -->
515
354
  @if (!isEditMode()) {
516
355
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
517
- <!-- Storage Configuration -->
518
356
  <div class="field">
519
- <label for="storageConfig" class="block font-medium mb-2"
520
- >Storage Configuration *</label
521
- >
522
- <select
523
- id="storageConfig"
524
- class="p-select-native"
525
- [formField]="fileForm.storageConfigId"
526
- >
357
+ <label for="storageConfig" class="block font-medium mb-2 text-sm sm:text-base">Storage Configuration *</label>
358
+ <select id="storageConfig" class="p-select-native w-full" [formField]="fileForm.storageConfigId">
527
359
  <option value="">Select storage configuration...</option>
528
360
  @for (config of availableConfigs(); track config.id) {
529
- <option [value]="config.id">
530
- {{ config.name }} ({{ getProviderLabel(config.storage) }})
531
- </option>
361
+ <option [value]="config.id">{{ config.name }} ({{ getProviderLabel(config.storage) }})</option>
532
362
  }
533
363
  </select>
534
364
  @if (availableConfigs().length === 0 && !isLoadingConfigs()) {
@@ -539,16 +369,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
539
369
  }
540
370
  </div>
541
371
 
542
- <!-- Folder Selection -->
543
372
  <div class="field">
544
- <label for="folder" class="block font-medium mb-2"
545
- >Folder (Optional)</label
546
- >
547
- <select
548
- id="folder"
549
- class="p-select-native"
550
- [formField]="fileForm.folderId"
551
- >
373
+ <label for="folder" class="block font-medium mb-2 text-sm sm:text-base">Folder (Optional)</label>
374
+ <select id="folder" class="p-select-native w-full" [formField]="fileForm.folderId">
552
375
  <option value="">No folder (root level)</option>
553
376
  @for (folder of availableFolders(); track folder.id) {
554
377
  <option [value]="folder.id">{{ folder.name }}</option>
@@ -563,16 +386,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
563
386
  </div>
564
387
  </div>
565
388
  } @else {
566
- <!-- Folder Selection for Edit Mode -->
567
389
  <div class="field mb-4">
568
- <label for="folder" class="block font-medium mb-2"
569
- >Folder (Optional)</label
570
- >
571
- <select
572
- id="folder"
573
- class="p-select-native"
574
- [formField]="fileForm.folderId"
575
- >
390
+ <label for="folder" class="block font-medium mb-2 text-sm sm:text-base">Folder (Optional)</label>
391
+ <select id="folder" class="p-select-native w-full" [formField]="fileForm.folderId">
576
392
  <option value="">No folder (root level)</option>
577
393
  @for (folder of availableFolders(); track folder.id) {
578
394
  <option [value]="folder.id">{{ folder.name }}</option>
@@ -587,10 +403,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
587
403
  </div>
588
404
  }
589
405
 
590
- <!-- File Upload (only for new files) -->
591
406
  @if (!isEditMode()) {
592
407
  <div class="field mb-4">
593
- <label class="block font-medium mb-2">Select File *</label>
408
+ <label class="block font-medium mb-2 text-sm sm:text-base">Select File *</label>
594
409
  <p-fileupload
595
410
  #fileUpload
596
411
  [customUpload]="true"
@@ -608,108 +423,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
608
423
  @if (files && files.length > 0) {
609
424
  <div class="flex flex-col gap-2">
610
425
  @for (file of files; track file.name) {
611
- <div class="flex items-center gap-3 p-3 border rounded">
612
- <i class="pi pi-file text-2xl"></i>
613
- <div class="flex-1">
614
- <div class="font-medium">{{ file.name }}</div>
615
- <div class="text-sm text-muted-color">
616
- {{ formatFileSize(file.size) }}
617
- </div>
426
+ <div class="flex items-center gap-3 p-3 border border-surface rounded-lg bg-surface-ground">
427
+ <i class="pi pi-file text-xl sm:text-2xl text-primary"></i>
428
+ <div class="flex-1 min-w-0">
429
+ <div class="font-medium truncate">{{ file.name }}</div>
430
+ <div class="text-sm text-muted-color">{{ formatFileSize(file.size) }}</div>
618
431
  </div>
619
- <p-button
620
- icon="pi pi-times"
621
- [text]="true"
622
- severity="danger"
623
- size="small"
624
- (onClick)="fileUpload.clear()"
625
- />
432
+ <p-button icon="pi pi-times" [text]="true" severity="danger" size="small" (onClick)="fileUpload.clear()" />
626
433
  </div>
627
434
  }
628
435
  </div>
629
436
  } @else {
630
- <div
631
- class="flex items-center justify-center flex-col p-8 border-2 border-dashed border-surface-300 rounded"
632
- >
633
- <i
634
- class="pi pi-cloud-upload text-4xl text-muted-color mb-3"
635
- ></i>
636
- <p class="text-muted-color">
637
- Drag and drop file here or click to browse
638
- </p>
639
- <p class="text-sm text-muted-color mt-2">
640
- Maximum file size: 50MB
641
- </p>
437
+ <div class="flex items-center justify-center flex-col p-6 sm:p-8 border-2 border-dashed border-surface rounded-lg">
438
+ <i class="pi pi-cloud-upload text-3xl sm:text-4xl text-muted-color mb-3"></i>
439
+ <p class="text-muted-color text-center text-sm sm:text-base">Drag and drop file here or click to browse</p>
440
+ <p class="text-xs sm:text-sm text-muted-color mt-2">Maximum file size: 50MB</p>
642
441
  </div>
643
442
  }
644
443
  </ng-template>
645
444
  </p-fileupload>
646
445
  @if (!selectedFile() && !isEditMode()) {
647
- <small class="text-muted-color"
648
- >Please select a file to upload</small
649
- >
446
+ <small class="text-muted-color">Please select a file to upload</small>
650
447
  }
651
448
  </div>
652
449
  }
653
450
 
654
451
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
655
- <!-- File Name (read-only for uploads, editable for existing) -->
656
452
  <div class="field md:col-span-2">
657
- <label for="name" class="block font-medium mb-2">File Name *</label>
658
- <input
659
- pInputText
660
- id="name"
661
- [formField]="fileForm.name"
662
- [placeholder]="
663
- isEditMode()
664
- ? 'Enter file name'
665
- : 'Will be auto-filled from selected file'
666
- "
667
- class="w-full"
668
- />
453
+ <label for="name" class="block font-medium mb-2 text-sm sm:text-base">File Name *</label>
454
+ <input pInputText id="name" [formField]="fileForm.name" [placeholder]="isEditMode() ? 'Enter file name' : 'Will be auto-filled from selected file'" class="w-full" />
669
455
  </div>
670
456
 
671
- <!-- Privacy Toggle -->
672
457
  <div class="field">
673
- <label class="p-checkbox-native">
458
+ <label class="p-checkbox-native flex items-center gap-2">
674
459
  <input type="checkbox" [formField]="fileForm.isPrivate" />
675
460
  <span>Private File</span>
676
461
  </label>
677
462
  <small class="text-muted-color block mt-2">
678
- {{
679
- formModel().isPrivate
680
- ? 'Only users with permission can access'
681
- : 'File is publicly accessible'
682
- }}
463
+ {{ formModel().isPrivate ? 'Only users with permission can access' : 'File is publicly accessible' }}
683
464
  </small>
684
465
  </div>
685
466
  </div>
686
467
 
687
- <div class="flex gap-2 mt-4">
468
+ <div class="flex justify-end gap-2 mt-4">
469
+ <p-button label="Cancel" severity="secondary" [outlined]="true" (onClick)="onCancel()" />
688
470
  <p-button
689
471
  type="submit"
690
472
  [label]="isEditMode() ? 'Update' : 'Upload'"
691
- [icon]="isEditMode() ? 'pi pi-check' : 'pi pi-cloud-upload'"
692
473
  [loading]="isLoading()"
693
- [disabled]="
694
- !isFormValid() ||
695
- (!isEditMode() && !selectedFile()) ||
696
- isLoading()
697
- "
698
- />
699
- <p-button
700
- type="button"
701
- label="Cancel"
702
- severity="secondary"
703
- icon="pi pi-times"
704
- [text]="true"
705
- (onClick)="onCancel()"
474
+ [disabled]="!isFormValid() || (!isEditMode() && !selectedFile()) || isLoading()"
706
475
  />
707
476
  </div>
708
477
  </form>
709
478
  </div>
710
479
  `,
711
480
  }]
712
- }] });
481
+ }], ctorParameters: () => [] });
713
482
 
714
483
  export { FileManagerFormComponent };
715
- //# sourceMappingURL=flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs.map
484
+ //# sourceMappingURL=flusys-ng-storage-file-manager-form.component-Bv8ER8J0.mjs.map