@flusys/ng-storage 1.0.0-beta → 1.1.1-beta

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 +68 -1
  2. package/fesm2022/{flusys-ng-storage-file-manager-form.component-DVZsFYrj.mjs → flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs} +27 -27
  3. package/fesm2022/flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs.map +1 -0
  4. package/fesm2022/{flusys-ng-storage-file-manager-list.component-CwnyNoYb.mjs → flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs} +8 -8
  5. package/fesm2022/flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-storage-folder-form.component-DH-KCz21.mjs → flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs} +6 -6
  7. package/fesm2022/flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs.map +1 -0
  8. package/fesm2022/{flusys-ng-storage-folder-list.component-iIys4NvL.mjs → flusys-ng-storage-folder-list.component-D-oMaEgl.mjs} +6 -6
  9. package/fesm2022/flusys-ng-storage-folder-list.component-D-oMaEgl.mjs.map +1 -0
  10. package/fesm2022/{flusys-ng-storage-storage-config-form.component-Bc95TVD0.mjs → flusys-ng-storage-storage-config-form.component-CjIAxfHC.mjs} +39 -6
  11. package/fesm2022/flusys-ng-storage-storage-config-form.component-CjIAxfHC.mjs.map +1 -0
  12. package/fesm2022/{flusys-ng-storage-storage-config-list.component-Bfomqyr3.mjs → flusys-ng-storage-storage-config-list.component-jHk8O9Mx.mjs} +7 -7
  13. package/fesm2022/flusys-ng-storage-storage-config-list.component-jHk8O9Mx.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-storage.mjs +195 -74
  15. package/fesm2022/flusys-ng-storage.mjs.map +1 -1
  16. package/package.json +4 -4
  17. package/types/flusys-ng-storage.d.ts +77 -4
  18. package/fesm2022/flusys-ng-storage-file-manager-form.component-DVZsFYrj.mjs.map +0 -1
  19. package/fesm2022/flusys-ng-storage-file-manager-list.component-CwnyNoYb.mjs.map +0 -1
  20. package/fesm2022/flusys-ng-storage-folder-form.component-DH-KCz21.mjs.map +0 -1
  21. package/fesm2022/flusys-ng-storage-folder-list.component-iIys4NvL.mjs.map +0 -1
  22. package/fesm2022/flusys-ng-storage-storage-config-form.component-Bc95TVD0.mjs.map +0 -1
  23. package/fesm2022/flusys-ng-storage-storage-config-list.component-Bfomqyr3.mjs.map +0 -1
package/README.md CHANGED
@@ -233,6 +233,8 @@ interface IStorageConfig extends IBaseEntity {
233
233
  name: string;
234
234
  storage: FileLocationEnum;
235
235
  config: Record<string, any>; // Provider-specific configuration
236
+ isActive: boolean; // Whether config is active and usable
237
+ isDefault: boolean; // Set as default configuration
236
238
  companyId?: string | null;
237
239
  }
238
240
 
@@ -240,6 +242,8 @@ interface ICreateStorageConfigDto {
240
242
  name: string;
241
243
  storage: FileLocationEnum;
242
244
  config: Record<string, any>;
245
+ isActive?: boolean;
246
+ isDefault?: boolean;
243
247
  }
244
248
 
245
249
  interface IUpdateStorageConfigDto {
@@ -247,6 +251,8 @@ interface IUpdateStorageConfigDto {
247
251
  name?: string;
248
252
  storage?: FileLocationEnum;
249
253
  config?: Record<string, any>;
254
+ isActive?: boolean;
255
+ isDefault?: boolean;
250
256
  }
251
257
  ```
252
258
 
@@ -389,6 +395,11 @@ All form components share:
389
395
  - Azure Blob: accountName, accountKey, containerName
390
396
  - SFTP: host, port, username, password, basePath
391
397
  - Local: basePath
398
+ - **Active toggle** - enables/disables the configuration
399
+ - **Set as Default toggle** - marks configuration as the default for uploads
400
+
401
+ **Default Configuration:**
402
+ When `isDefault: true`, this configuration will be used automatically when no `storageConfigId` is provided in upload requests.
392
403
 
393
404
  ---
394
405
 
@@ -557,6 +568,59 @@ services: {
557
568
 
558
569
  ---
559
570
 
571
+ ## Provider Functions
572
+
573
+ ### provideStorageProviders()
574
+
575
+ Registers provider adapters that enable other packages (ng-auth) to access storage functionality without direct dependencies.
576
+
577
+ ```typescript
578
+ import { provideStorageProviders } from '@flusys/ng-storage';
579
+
580
+ // app.config.ts
581
+ export const appConfig: ApplicationConfig = {
582
+ providers: [
583
+ ...provideStorageProviders(), // Register storage providers
584
+ ],
585
+ };
586
+ ```
587
+
588
+ **Registers:**
589
+
590
+ | Token | Adapter | Purpose |
591
+ |-------|---------|---------|
592
+ | `PROFILE_UPLOAD_PROVIDER` | `ProfileUploadProviderAdapter` | Profile picture upload for ng-auth |
593
+
594
+ ### ProfileUploadProviderAdapter
595
+
596
+ Implements `IProfileUploadProvider` from ng-shared. Enables ng-auth's profile page to upload profile pictures.
597
+
598
+ ```typescript
599
+ interface IProfileUploadProvider {
600
+ uploadProfilePicture(
601
+ file: File,
602
+ options?: IProfileUploadOptions
603
+ ): Observable<ISingleResponse<IProfileUploadResult>>;
604
+ }
605
+ ```
606
+
607
+ **Usage in ng-auth profile page:**
608
+
609
+ ```typescript
610
+ // Optional injection - graceful degradation when storage disabled
611
+ private readonly uploadProvider = inject(PROFILE_UPLOAD_PROVIDER, { optional: true });
612
+
613
+ // Upload profile picture
614
+ if (this.uploadProvider) {
615
+ this.uploadProvider.uploadProfilePicture(file, { compress: true }).subscribe(response => {
616
+ // response.data.id contains the file manager ID
617
+ this.updateUserProfile({ profilePictureId: response.data.id });
618
+ });
619
+ }
620
+ ```
621
+
622
+ ---
623
+
560
624
  ## Public API Exports
561
625
 
562
626
  ```typescript
@@ -582,9 +646,12 @@ export {
582
646
  // Routes & Components
583
647
  export { STORAGE_ROUTES } from '@flusys/ng-storage';
584
648
  export { StorageContainerComponent } from '@flusys/ng-storage';
649
+
650
+ // Provider Functions
651
+ export { provideStorageProviders } from '@flusys/ng-storage';
585
652
  ```
586
653
 
587
654
  ---
588
655
 
589
- **Last Updated:** 2026-02-15
656
+ **Last Updated:** 2026-02-16
590
657
  **Angular Version:** 21
@@ -9,9 +9,9 @@ import { MessageService } from 'primeng/api';
9
9
  import { firstValueFrom } from 'rxjs';
10
10
  import { FileManagerApiService, UploadService, StorageConfigApiService, FolderApiService } from './flusys-ng-storage.mjs';
11
11
  import * as i1 from '@angular/forms';
12
- import * as i2 from 'primeng/inputtext';
13
- import * as i3 from 'primeng/button';
14
- import * as i4 from 'primeng/fileupload';
12
+ import * as i1$1 from 'primeng/button';
13
+ import * as i3 from 'primeng/fileupload';
14
+ import * as i3$1 from 'primeng/inputtext';
15
15
 
16
16
  /**
17
17
  * File Manager Form Component
@@ -269,7 +269,7 @@ class FileManagerFormComponent {
269
269
  {{ isEditMode() ? 'Edit File' : 'Upload File' }}
270
270
  </h3>
271
271
  @if (showCompanyInfo()) {
272
- <p class="text-sm text-gray-600 mt-1">
272
+ <p class="text-sm text-muted-color mt-1">
273
273
  Company: {{ currentCompanyName() }}
274
274
  </p>
275
275
  }
@@ -305,7 +305,7 @@ class FileManagerFormComponent {
305
305
  }
306
306
  </select>
307
307
  @if (availableConfigs().length === 0 && !isLoadingConfigs()) {
308
- <small class="text-orange-600 block mt-2">
308
+ <small class="text-warn block mt-2">
309
309
  <i class="pi pi-exclamation-triangle mr-1"></i>
310
310
  No storage configurations found. Please create one first.
311
311
  </small>
@@ -328,7 +328,7 @@ class FileManagerFormComponent {
328
328
  }
329
329
  </select>
330
330
  @if (availableFolders().length === 0 && !isLoadingFolders()) {
331
- <small class="text-gray-600 block mt-2">
331
+ <small class="text-muted-color block mt-2">
332
332
  <i class="pi pi-info-circle mr-1"></i>
333
333
  No folders available. File will be uploaded to root level.
334
334
  </small>
@@ -352,7 +352,7 @@ class FileManagerFormComponent {
352
352
  }
353
353
  </select>
354
354
  @if (availableFolders().length === 0 && !isLoadingFolders()) {
355
- <small class="text-gray-600 block mt-2">
355
+ <small class="text-muted-color block mt-2">
356
356
  <i class="pi pi-info-circle mr-1"></i>
357
357
  No folders available.
358
358
  </small>
@@ -385,7 +385,7 @@ class FileManagerFormComponent {
385
385
  <i class="pi pi-file text-2xl"></i>
386
386
  <div class="flex-1">
387
387
  <div class="font-medium">{{ file.name }}</div>
388
- <div class="text-sm text-gray-600">
388
+ <div class="text-sm text-muted-color">
389
389
  {{ formatFileSize(file.size) }}
390
390
  </div>
391
391
  </div>
@@ -401,15 +401,15 @@ class FileManagerFormComponent {
401
401
  </div>
402
402
  } @else {
403
403
  <div
404
- class="flex items-center justify-center flex-col p-8 border-2 border-dashed border-gray-300 rounded"
404
+ class="flex items-center justify-center flex-col p-8 border-2 border-dashed border-surface-300 rounded"
405
405
  >
406
406
  <i
407
- class="pi pi-cloud-upload text-4xl text-gray-400 mb-3"
407
+ class="pi pi-cloud-upload text-4xl text-muted-color mb-3"
408
408
  ></i>
409
- <p class="text-gray-600">
409
+ <p class="text-muted-color">
410
410
  Drag and drop file here or click to browse
411
411
  </p>
412
- <p class="text-sm text-gray-500 mt-2">
412
+ <p class="text-sm text-muted-color mt-2">
413
413
  Maximum file size: 50MB
414
414
  </p>
415
415
  </div>
@@ -417,7 +417,7 @@ class FileManagerFormComponent {
417
417
  </ng-template>
418
418
  </p-fileupload>
419
419
  @if (!selectedFile() && !isEditMode()) {
420
- <small class="text-gray-600"
420
+ <small class="text-muted-color"
421
421
  >Please select a file to upload</small
422
422
  >
423
423
  }
@@ -447,7 +447,7 @@ class FileManagerFormComponent {
447
447
  <input type="checkbox" [formField]="fileForm.isPrivate" />
448
448
  <span>Private File</span>
449
449
  </label>
450
- <small class="text-gray-600 block mt-2">
450
+ <small class="text-muted-color block mt-2">
451
451
  {{
452
452
  formModel().isPrivate
453
453
  ? 'Only users with permission can access'
@@ -480,7 +480,7 @@ class FileManagerFormComponent {
480
480
  </div>
481
481
  </form>
482
482
  </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: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i3.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: i4.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: FormField, selector: "[formField]", inputs: ["formField"] }] });
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"] }] });
484
484
  }
485
485
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileManagerFormComponent, decorators: [{
486
486
  type: Component,
@@ -496,7 +496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
496
496
  {{ isEditMode() ? 'Edit File' : 'Upload File' }}
497
497
  </h3>
498
498
  @if (showCompanyInfo()) {
499
- <p class="text-sm text-gray-600 mt-1">
499
+ <p class="text-sm text-muted-color mt-1">
500
500
  Company: {{ currentCompanyName() }}
501
501
  </p>
502
502
  }
@@ -532,7 +532,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
532
532
  }
533
533
  </select>
534
534
  @if (availableConfigs().length === 0 && !isLoadingConfigs()) {
535
- <small class="text-orange-600 block mt-2">
535
+ <small class="text-warn block mt-2">
536
536
  <i class="pi pi-exclamation-triangle mr-1"></i>
537
537
  No storage configurations found. Please create one first.
538
538
  </small>
@@ -555,7 +555,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
555
555
  }
556
556
  </select>
557
557
  @if (availableFolders().length === 0 && !isLoadingFolders()) {
558
- <small class="text-gray-600 block mt-2">
558
+ <small class="text-muted-color block mt-2">
559
559
  <i class="pi pi-info-circle mr-1"></i>
560
560
  No folders available. File will be uploaded to root level.
561
561
  </small>
@@ -579,7 +579,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
579
579
  }
580
580
  </select>
581
581
  @if (availableFolders().length === 0 && !isLoadingFolders()) {
582
- <small class="text-gray-600 block mt-2">
582
+ <small class="text-muted-color block mt-2">
583
583
  <i class="pi pi-info-circle mr-1"></i>
584
584
  No folders available.
585
585
  </small>
@@ -612,7 +612,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
612
612
  <i class="pi pi-file text-2xl"></i>
613
613
  <div class="flex-1">
614
614
  <div class="font-medium">{{ file.name }}</div>
615
- <div class="text-sm text-gray-600">
615
+ <div class="text-sm text-muted-color">
616
616
  {{ formatFileSize(file.size) }}
617
617
  </div>
618
618
  </div>
@@ -628,15 +628,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
628
628
  </div>
629
629
  } @else {
630
630
  <div
631
- class="flex items-center justify-center flex-col p-8 border-2 border-dashed border-gray-300 rounded"
631
+ class="flex items-center justify-center flex-col p-8 border-2 border-dashed border-surface-300 rounded"
632
632
  >
633
633
  <i
634
- class="pi pi-cloud-upload text-4xl text-gray-400 mb-3"
634
+ class="pi pi-cloud-upload text-4xl text-muted-color mb-3"
635
635
  ></i>
636
- <p class="text-gray-600">
636
+ <p class="text-muted-color">
637
637
  Drag and drop file here or click to browse
638
638
  </p>
639
- <p class="text-sm text-gray-500 mt-2">
639
+ <p class="text-sm text-muted-color mt-2">
640
640
  Maximum file size: 50MB
641
641
  </p>
642
642
  </div>
@@ -644,7 +644,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
644
644
  </ng-template>
645
645
  </p-fileupload>
646
646
  @if (!selectedFile() && !isEditMode()) {
647
- <small class="text-gray-600"
647
+ <small class="text-muted-color"
648
648
  >Please select a file to upload</small
649
649
  >
650
650
  }
@@ -674,7 +674,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
674
674
  <input type="checkbox" [formField]="fileForm.isPrivate" />
675
675
  <span>Private File</span>
676
676
  </label>
677
- <small class="text-gray-600 block mt-2">
677
+ <small class="text-muted-color block mt-2">
678
678
  {{
679
679
  formModel().isPrivate
680
680
  ? 'Only users with permission can access'
@@ -712,4 +712,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
712
712
  }] });
713
713
 
714
714
  export { FileManagerFormComponent };
715
- //# sourceMappingURL=flusys-ng-storage-file-manager-form.component-DVZsFYrj.mjs.map
715
+ //# sourceMappingURL=flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs","sources":["../../../projects/ng-storage/pages/file-manager/file-manager-form.component.ts"],"sourcesContent":["import { Component, computed, inject, OnInit, signal } from '@angular/core';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { APP_CONFIG, DEFAULT_APP_NAME } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule } from '@flusys/ng-shared';\nimport { MessageService } from 'primeng/api';\nimport { firstValueFrom } from 'rxjs';\nimport { IFileManager } from '../../interfaces/file-manager.interface';\nimport { IFolder } from '../../interfaces/folder.interface';\nimport { IStorageConfig } from '../../interfaces/storage-config.interface';\nimport { FileManagerApiService } from '../../services/file-manager-api.service';\nimport { FolderApiService } from '../../services/folder-api.service';\nimport { StorageConfigApiService } from '../../services/storage-config-api.service';\nimport { UploadService } from '../../services/upload.service';\n\n/** File manager form model interface */\ninterface IFileManagerFormModel {\n id: string;\n name: string;\n isPrivate: boolean;\n folderId: string;\n storageConfigId: string;\n}\n\n/**\n * File Manager Form Component\n * Upload and edit file metadata\n */\n@Component({\n selector: 'lib-file-manager-form',\n standalone: true,\n imports: [AngularModule, PrimeModule, FormField],\n template: `\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-4\">\n <div>\n <h3 class=\"text-xl font-semibold\">\n {{ isEditMode() ? 'Edit File' : 'Upload File' }}\n </h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n Company: {{ currentCompanyName() }}\n </p>\n }\n </div>\n <p-button\n label=\"Back\"\n icon=\"pi pi-arrow-left\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onCancel()\"\n />\n </div>\n\n <form (ngSubmit)=\"onSubmit()\">\n <!-- Storage Configuration & Folder Selection (only for new files) -->\n @if (!isEditMode()) {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\n <!-- Storage Configuration -->\n <div class=\"field\">\n <label for=\"storageConfig\" class=\"block font-medium mb-2\"\n >Storage Configuration *</label\n >\n <select\n id=\"storageConfig\"\n class=\"p-select-native\"\n [formField]=\"fileForm.storageConfigId\"\n >\n <option value=\"\">Select storage configuration...</option>\n @for (config of availableConfigs(); track config.id) {\n <option [value]=\"config.id\">\n {{ config.name }} ({{ getProviderLabel(config.storage) }})\n </option>\n }\n </select>\n @if (availableConfigs().length === 0 && !isLoadingConfigs()) {\n <small class=\"text-warn block mt-2\">\n <i class=\"pi pi-exclamation-triangle mr-1\"></i>\n No storage configurations found. Please create one first.\n </small>\n }\n </div>\n\n <!-- Folder Selection -->\n <div class=\"field\">\n <label for=\"folder\" class=\"block font-medium mb-2\"\n >Folder (Optional)</label\n >\n <select\n id=\"folder\"\n class=\"p-select-native\"\n [formField]=\"fileForm.folderId\"\n >\n <option value=\"\">No folder (root level)</option>\n @for (folder of availableFolders(); track folder.id) {\n <option [value]=\"folder.id\">{{ folder.name }}</option>\n }\n </select>\n @if (availableFolders().length === 0 && !isLoadingFolders()) {\n <small class=\"text-muted-color block mt-2\">\n <i class=\"pi pi-info-circle mr-1\"></i>\n No folders available. File will be uploaded to root level.\n </small>\n }\n </div>\n </div>\n } @else {\n <!-- Folder Selection for Edit Mode -->\n <div class=\"field mb-4\">\n <label for=\"folder\" class=\"block font-medium mb-2\"\n >Folder (Optional)</label\n >\n <select\n id=\"folder\"\n class=\"p-select-native\"\n [formField]=\"fileForm.folderId\"\n >\n <option value=\"\">No folder (root level)</option>\n @for (folder of availableFolders(); track folder.id) {\n <option [value]=\"folder.id\">{{ folder.name }}</option>\n }\n </select>\n @if (availableFolders().length === 0 && !isLoadingFolders()) {\n <small class=\"text-muted-color block mt-2\">\n <i class=\"pi pi-info-circle mr-1\"></i>\n No folders available.\n </small>\n }\n </div>\n }\n\n <!-- File Upload (only for new files) -->\n @if (!isEditMode()) {\n <div class=\"field mb-4\">\n <label class=\"block font-medium mb-2\">Select File *</label>\n <p-fileupload\n #fileUpload\n [customUpload]=\"true\"\n (onSelect)=\"onFileSelect($event)\"\n [multiple]=\"false\"\n [maxFileSize]=\"50000000\"\n [showUploadButton]=\"false\"\n [showCancelButton]=\"false\"\n chooseLabel=\"Choose File\"\n chooseIcon=\"pi pi-upload\"\n accept=\"*/*\"\n class=\"w-full\"\n >\n <ng-template #content let-files>\n @if (files && files.length > 0) {\n <div class=\"flex flex-col gap-2\">\n @for (file of files; track file.name) {\n <div class=\"flex items-center gap-3 p-3 border rounded\">\n <i class=\"pi pi-file text-2xl\"></i>\n <div class=\"flex-1\">\n <div class=\"font-medium\">{{ file.name }}</div>\n <div class=\"text-sm text-muted-color\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <p-button\n icon=\"pi pi-times\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n (onClick)=\"fileUpload.clear()\"\n />\n </div>\n }\n </div>\n } @else {\n <div\n class=\"flex items-center justify-center flex-col p-8 border-2 border-dashed border-surface-300 rounded\"\n >\n <i\n class=\"pi pi-cloud-upload text-4xl text-muted-color mb-3\"\n ></i>\n <p class=\"text-muted-color\">\n Drag and drop file here or click to browse\n </p>\n <p class=\"text-sm text-muted-color mt-2\">\n Maximum file size: 50MB\n </p>\n </div>\n }\n </ng-template>\n </p-fileupload>\n @if (!selectedFile() && !isEditMode()) {\n <small class=\"text-muted-color\"\n >Please select a file to upload</small\n >\n }\n </div>\n }\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <!-- File Name (read-only for uploads, editable for existing) -->\n <div class=\"field md:col-span-2\">\n <label for=\"name\" class=\"block font-medium mb-2\">File Name *</label>\n <input\n pInputText\n id=\"name\"\n [formField]=\"fileForm.name\"\n [placeholder]=\"\n isEditMode()\n ? 'Enter file name'\n : 'Will be auto-filled from selected file'\n \"\n class=\"w-full\"\n />\n </div>\n\n <!-- Privacy Toggle -->\n <div class=\"field\">\n <label class=\"p-checkbox-native\">\n <input type=\"checkbox\" [formField]=\"fileForm.isPrivate\" />\n <span>Private File</span>\n </label>\n <small class=\"text-muted-color block mt-2\">\n {{\n formModel().isPrivate\n ? 'Only users with permission can access'\n : 'File is publicly accessible'\n }}\n </small>\n </div>\n </div>\n\n <div class=\"flex gap-2 mt-4\">\n <p-button\n type=\"submit\"\n [label]=\"isEditMode() ? 'Update' : 'Upload'\"\n [icon]=\"isEditMode() ? 'pi pi-check' : 'pi pi-cloud-upload'\"\n [loading]=\"isLoading()\"\n [disabled]=\"\n !isFormValid() ||\n (!isEditMode() && !selectedFile()) ||\n isLoading()\n \"\n />\n <p-button\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n icon=\"pi pi-times\"\n [text]=\"true\"\n (onClick)=\"onCancel()\"\n />\n </div>\n </form>\n </div>\n `,\n})\nexport class FileManagerFormComponent implements OnInit {\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly messageService = inject(MessageService);\n private readonly fileService = inject(FileManagerApiService);\n private readonly uploadService = inject(UploadService);\n private readonly configService = inject(StorageConfigApiService);\n private readonly folderService = inject(FolderApiService);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n\n readonly isLoading = signal(false);\n readonly isLoadingConfigs = signal(false);\n readonly isLoadingFolders = signal(false);\n readonly existingFile = signal<IFileManager | null>(null);\n readonly isEditMode = computed(() => !!this.existingFile());\n readonly selectedFile = signal<File | null>(null);\n readonly availableConfigs = signal<IStorageConfig[]>([]);\n readonly availableFolders = signal<IFolder[]>([]);\n\n readonly showCompanyInfo = computed(\n () => this.appConfig.enableCompanyFeature,\n );\n readonly currentCompanyName = computed(\n () => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME,\n );\n\n // ============================================\n // Form (Signal Forms)\n // ============================================\n\n /** Form model */\n readonly formModel = signal<IFileManagerFormModel>({\n id: '',\n name: '',\n isPrivate: false,\n folderId: '',\n storageConfigId: '',\n });\n\n /** Form with validation schema */\n readonly fileForm = form(this.formModel, (f) => {\n required(f.name, { message: 'File name is required' });\n // storageConfigId validation will be done manually in onSubmit\n // as it's only required for new uploads, not edits\n });\n\n /** Check if form is valid */\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.name.trim().length > 0;\n });\n\n ngOnInit(): void {\n const fileId = this.route.snapshot.paramMap.get('id');\n if (fileId) {\n this.loadFile(fileId);\n } else {\n // Load storage configurations for new upload\n this.loadStorageConfigs();\n }\n // Load folders for both create and edit modes\n this.loadFolders();\n }\n\n async loadStorageConfigs(): Promise<void> {\n this.isLoadingConfigs.set(true);\n try {\n const response = await firstValueFrom(\n this.configService.getAll('', {\n pagination: { currentPage: 0, pageSize: 100 },\n filter: {},\n select: [],\n sort: {},\n }),\n );\n if (response.success && response.data) {\n this.availableConfigs.set(response.data);\n // Auto-select first config if only one available\n if (response.data.length === 1) {\n this.formModel.update((m) => ({\n ...m,\n storageConfigId: response.data![0].id,\n }));\n }\n }\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load storage configurations.',\n });\n } finally {\n this.isLoadingConfigs.set(false);\n }\n }\n\n async loadFolders(): Promise<void> {\n this.isLoadingFolders.set(true);\n try {\n const response = await firstValueFrom(\n this.folderService.getAll('', {\n pagination: { currentPage: 0, pageSize: 100 },\n filter: {},\n select: [],\n sort: {},\n }),\n );\n if (response.success && response.data) {\n this.availableFolders.set(response.data);\n }\n } catch {\n // Silently fail - folders are optional\n } finally {\n this.isLoadingFolders.set(false);\n }\n }\n\n async loadFile(id: string): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await this.fileService.findByIdAsync(id);\n if (response.success && response.data) {\n const file = response.data;\n this.existingFile.set(file);\n this.formModel.set({\n id: file.id,\n name: file.name,\n isPrivate: file.isPrivate ?? false,\n folderId: file.folderId ?? '',\n storageConfigId: '',\n });\n }\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load file.',\n });\n this.router.navigate(['/storage/files']);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onFileSelect(event: any): void {\n const file = event.files?.[0] || event.currentFiles?.[0];\n if (file) {\n this.selectedFile.set(file);\n // Auto-fill file name\n this.formModel.update((m) => ({ ...m, name: file.name }));\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 // Update existing file metadata only\n await this.fileService.updateAsync({\n id: formValue.id,\n name: formValue.name,\n isPrivate: formValue.isPrivate,\n folderId: formValue.folderId || null,\n } as any);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'File updated successfully.',\n });\n } else {\n // Upload new file\n const file = this.selectedFile();\n if (!file) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Please select a file to upload.',\n });\n return;\n }\n\n // Validate storage config selection\n if (!formValue.storageConfigId) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Please select a storage configuration.',\n });\n return;\n }\n\n // Upload file first\n const uploadResponse = await firstValueFrom(\n this.uploadService.uploadSingleFile(file, {\n compress: true,\n quality: 85,\n storageConfigId: formValue.storageConfigId,\n }),\n );\n\n if (uploadResponse.success && uploadResponse.data) {\n const uploadedFileInfo = uploadResponse.data;\n\n // Save file metadata\n await this.fileService.insertAsync({\n name: formValue.name,\n key: uploadedFileInfo.key,\n contentType: file.type || 'application/octet-stream',\n size: Math.round(file.size / 1024).toString(),\n isPrivate: formValue.isPrivate,\n folderId: formValue.folderId || undefined,\n storageConfigId: formValue.storageConfigId, // ✅ Include storage config ID\n } as any);\n\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'File uploaded successfully.',\n });\n } else {\n throw new Error('Upload failed');\n }\n }\n\n this.router.navigate(['/storage/files']);\n } catch (error: any) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail:\n error?.message ||\n `Failed to ${this.isEditMode() ? 'update' : 'upload'} file.`,\n });\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onCancel(): void {\n this.router.navigate(['/storage/files']);\n }\n\n formatFileSize(bytes: number): string {\n if (bytes === 0) return '0 Bytes';\n const k = 1024;\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];\n }\n\n getProviderLabel(storage: string): string {\n const labels: Record<string, string> = {\n AWS: 'AWS S3',\n AZURE: 'Azure Blob',\n SFTP: 'SFTP',\n LOCAL: 'Local',\n };\n return labels[storage] || storage;\n }\n}\n"],"names":["i2","i4"],"mappings":"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"}
@@ -7,10 +7,10 @@ import { AngularModule, PrimeModule } from '@flusys/ng-shared';
7
7
  import { MessageService, ConfirmationService } from 'primeng/api';
8
8
  import { firstValueFrom } from 'rxjs';
9
9
  import { FileManagerApiService } from './flusys-ng-storage.mjs';
10
- import * as i1 from 'primeng/tag';
11
- import * as i3 from 'primeng/button';
12
- import * as i3$1 from 'primeng/tooltip';
13
- import * as i4 from 'primeng/table';
10
+ import * as i1 from 'primeng/button';
11
+ import * as i2 from 'primeng/table';
12
+ import * as i3 from 'primeng/tag';
13
+ import * as i4 from 'primeng/tooltip';
14
14
  import * as i5 from '@angular/common';
15
15
 
16
16
  /**
@@ -235,7 +235,7 @@ class FileManagerListComponent {
235
235
  <div>
236
236
  <h3 class="text-xl font-semibold">File Manager</h3>
237
237
  @if (showCompanyInfo()) {
238
- <p class="text-sm text-gray-600 mt-1">
238
+ <p class="text-sm text-muted-color mt-1">
239
239
  Company: {{ currentCompanyName() }}
240
240
  </p>
241
241
  }
@@ -344,7 +344,7 @@ class FileManagerListComponent {
344
344
  </ng-template>
345
345
  </p-table>
346
346
  </div>
347
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: i1.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i3.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$1.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: "component", type: i4.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: "pipe", type: i5.DatePipe, name: "date" }] });
347
+ `, 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: "pipe", type: i5.DatePipe, name: "date" }] });
348
348
  }
349
349
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileManagerListComponent, decorators: [{
350
350
  type: Component,
@@ -358,7 +358,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
358
358
  <div>
359
359
  <h3 class="text-xl font-semibold">File Manager</h3>
360
360
  @if (showCompanyInfo()) {
361
- <p class="text-sm text-gray-600 mt-1">
361
+ <p class="text-sm text-muted-color mt-1">
362
362
  Company: {{ currentCompanyName() }}
363
363
  </p>
364
364
  }
@@ -472,4 +472,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
472
472
  }] });
473
473
 
474
474
  export { FileManagerListComponent };
475
- //# sourceMappingURL=flusys-ng-storage-file-manager-list.component-CwnyNoYb.mjs.map
475
+ //# sourceMappingURL=flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs","sources":["../../../projects/ng-storage/pages/file-manager/file-manager-list.component.ts"],"sourcesContent":["import { Component, computed, inject, OnInit, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { APP_CONFIG, DEFAULT_APP_NAME } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule } from '@flusys/ng-shared';\nimport { ConfirmationService, MessageService } from 'primeng/api';\nimport { firstValueFrom } from 'rxjs';\nimport { IFileManager } from '../../interfaces/file-manager.interface';\nimport { FileManagerApiService } from '../../services/file-manager-api.service';\n\n/**\n * File Manager List Component\n * Displays all files with company filter (if enabled)\n * Shows current company name in header\n */\n@Component({\n selector: 'lib-file-manager-list',\n standalone: true,\n imports: [AngularModule, PrimeModule],\n template: `\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-4\">\n <div>\n <h3 class=\"text-xl font-semibold\">File Manager</h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n Company: {{ currentCompanyName() }}\n </p>\n }\n </div>\n <p-button\n label=\"Upload File\"\n icon=\"pi pi-upload\"\n (onClick)=\"onUpload()\"\n />\n </div>\n\n <p-table\n [value]=\"files()\"\n [loading]=\"isLoading()\"\n [paginator]=\"true\"\n [rows]=\"pageSize()\"\n [totalRecords]=\"totalRecords()\"\n [lazy]=\"true\"\n (onLazyLoad)=\"onPageChange($event)\"\n styleClass=\"p-datatable-sm\"\n >\n <ng-template #header>\n <tr>\n <th>Name</th>\n <th>Type</th>\n <th>Size</th>\n <th>Location</th>\n <th>Config</th>\n <th>Private</th>\n <th>Created</th>\n <th>Actions</th>\n </tr>\n </ng-template>\n <ng-template #body let-file>\n <tr>\n <td>\n <i [class]=\"getFileIcon(file.contentType)\" class=\"mr-2\"></i>\n {{ file.name }}\n </td>\n <td>{{ file.contentType }}</td>\n <td>{{ file.size }} KB</td>\n <td>\n <p-tag [value]=\"getLocationLabel(file.location)\" [severity]=\"getLocationSeverity(file.location)\" />\n </td>\n <td>{{ file.providerName || '-' }}</td>\n <td>\n @if (file.isPrivate) {\n <p-tag value=\"Private\" severity=\"warn\" />\n } @else {\n <p-tag value=\"Public\" severity=\"success\" />\n }\n </td>\n <td>{{ file.createdAt | date: 'short' }}</td>\n <td>\n <p-button\n icon=\"pi pi-eye\"\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n [loading]=\"isViewLoading() === file.id\"\n [disabled]=\"isViewLoading() === file.id\"\n (onClick)=\"onView(file)\"\n pTooltip=\"View file\"\n tooltipPosition=\"top\"\n />\n <p-button\n icon=\"pi pi-pencil\"\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n (onClick)=\"onEdit(file.id)\"\n pTooltip=\"Edit file metadata\"\n tooltipPosition=\"top\"\n />\n <p-button\n icon=\"pi pi-trash\"\n [text]=\"true\"\n severity=\"warn\"\n size=\"small\"\n (onClick)=\"onSoftDelete(file)\"\n pTooltip=\"Move to trash (recoverable)\"\n tooltipPosition=\"top\"\n />\n <p-button\n icon=\"pi pi-times-circle\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n (onClick)=\"onPermanentDelete(file)\"\n pTooltip=\"Delete permanently (cannot be recovered)\"\n tooltipPosition=\"top\"\n />\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"8\" class=\"text-center py-4\">\n @if (showCompanyInfo()) {\n No files found in current company\n } @else {\n No files found\n }\n </td>\n </tr>\n </ng-template>\n </p-table>\n </div>\n `,\n})\nexport class FileManagerListComponent implements OnInit {\n private readonly router = inject(Router);\n private readonly messageService = inject(MessageService);\n private readonly confirmationService = inject(ConfirmationService);\n private readonly fileService = inject(FileManagerApiService);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n\n /** Loading state */\n readonly isLoading = signal(false);\n\n /** Loading state for file viewing */\n readonly isViewLoading = signal<string | null>(null);\n\n /** Files list */\n readonly files = signal<IFileManager[]>([]);\n\n /** Total records for pagination */\n readonly totalRecords = signal(0);\n\n /** Page size */\n readonly pageSize = signal(50);\n\n /** Current page */\n readonly currentPage = signal(1);\n\n /** Show company info if company feature enabled */\n readonly showCompanyInfo = computed(\n () => this.appConfig.enableCompanyFeature,\n );\n\n /** Current company name */\n readonly currentCompanyName = computed(\n () => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME,\n );\n\n ngOnInit(): void {\n this.loadFiles();\n }\n\n async loadFiles(): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await firstValueFrom(\n this.fileService.getAll('', {\n pagination: {\n currentPage: this.currentPage() - 1, // ApiResourceService uses 0-based pages\n pageSize: this.pageSize(),\n },\n filter: {},\n select: [],\n sort: {},\n }),\n );\n\n if (response.success) {\n this.files.set(response.data ?? []);\n this.totalRecords.set(response.meta?.total ?? 0);\n }\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load files.',\n });\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onPageChange(event: any): void {\n this.currentPage.set(event.first / event.rows + 1);\n this.pageSize.set(event.rows);\n this.loadFiles();\n }\n\n onUpload(): void {\n this.router.navigate(['/storage/files/new']);\n }\n\n onEdit(fileId: string): void {\n this.router.navigate(['/storage/files', fileId]);\n }\n\n async onView(file: IFileManager): Promise<void> {\n this.isViewLoading.set(file.id);\n try {\n const response = await firstValueFrom(\n this.fileService.getFiles([file.id]),\n );\n\n let files: any[] = [];\n\n if (response && typeof response === 'object') {\n if (\n 'success' in response &&\n response.success &&\n Array.isArray(response.data)\n ) {\n files = response.data;\n } else if (Array.isArray(response)) {\n files = response as any;\n }\n }\n\n if (files.length > 0) {\n const fileUrl = files[0].url;\n\n if (!fileUrl) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'File URL is not available.',\n });\n return;\n }\n\n window.open(fileUrl, '_blank');\n } else {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to retrieve file URL.',\n });\n }\n } catch {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to get file URL.',\n });\n } finally {\n this.isViewLoading.set(null);\n }\n }\n\n /**\n * Soft delete - Move file to trash (recommended)\n * File can be recovered later\n */\n onSoftDelete(file: IFileManager): void {\n this.confirmationService.confirm({\n message: `Move \"${file.name}\" to trash? You can recover it later.`,\n header: 'Move to Trash',\n icon: 'pi pi-trash',\n acceptLabel: '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.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'File moved to trash successfully.',\n });\n this.loadFiles();\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to move file to trash.',\n });\n }\n },\n });\n }\n\n /**\n * Permanent delete - Cannot be recovered\n * Also deletes the actual file from storage\n */\n onPermanentDelete(file: IFileManager): void {\n this.confirmationService.confirm({\n message: `Permanently delete \"${file.name}\"? This action CANNOT be undone and will delete the file from storage.`,\n header: 'Permanent Delete',\n icon: 'pi pi-exclamation-triangle',\n acceptLabel: 'Delete Permanently',\n rejectLabel: 'Cancel',\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n try {\n await this.fileService.deleteAsync({\n id: file.id,\n type: 'permanent',\n });\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'File permanently deleted.',\n });\n this.loadFiles();\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to permanently delete file.',\n });\n }\n },\n });\n }\n\n getFileIcon(contentType: string): string {\n if (contentType.startsWith('image/')) return 'pi pi-image';\n if (contentType.startsWith('video/')) return 'pi pi-video';\n if (contentType.startsWith('audio/')) return 'pi pi-volume-up';\n if (contentType.includes('pdf')) return 'pi pi-file-pdf';\n if (contentType.includes('word') || contentType.includes('document'))\n return 'pi pi-file-word';\n if (contentType.includes('excel') || contentType.includes('spreadsheet'))\n return 'pi pi-file-excel';\n return 'pi pi-file';\n }\n\n getLocationLabel(location: string): string {\n const labels: Record<string, string> = {\n local: 'Local',\n aws: 'AWS S3',\n azure: 'Azure',\n sftp: 'SFTP',\n };\n return labels[location] ?? location;\n }\n\n getLocationSeverity(location: string): 'success' | 'info' | 'warn' | 'danger' | 'secondary' | 'contrast' {\n const severities: Record<string, 'success' | 'info' | 'warn' | 'danger' | 'secondary' | 'contrast'> = {\n local: 'secondary',\n aws: 'warn',\n azure: 'info',\n sftp: 'contrast',\n };\n return severities[location] ?? 'secondary';\n }\n}\n"],"names":[],"mappings":"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"}
@@ -8,8 +8,8 @@ import { AngularModule, PrimeModule } from '@flusys/ng-shared';
8
8
  import { MessageService } from 'primeng/api';
9
9
  import { FolderApiService } from './flusys-ng-storage.mjs';
10
10
  import * as i1 from '@angular/forms';
11
- import * as i2 from 'primeng/inputtext';
12
- import * as i3 from 'primeng/button';
11
+ import * as i1$1 from 'primeng/button';
12
+ import * as i3 from 'primeng/inputtext';
13
13
 
14
14
  /**
15
15
  * Folder Form Component
@@ -129,7 +129,7 @@ class FolderFormComponent {
129
129
  {{ isEditMode() ? 'Edit Folder' : 'New Folder' }}
130
130
  </h3>
131
131
  @if (showCompanyInfo()) {
132
- <p class="text-sm text-gray-600 mt-1">
132
+ <p class="text-sm text-muted-color mt-1">
133
133
  Company: {{ currentCompanyName() }}
134
134
  </p>
135
135
  }
@@ -179,7 +179,7 @@ class FolderFormComponent {
179
179
  </div>
180
180
  </form>
181
181
  </div>
182
- `, 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: "directive", type: i2.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i3.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: FormField, selector: "[formField]", inputs: ["formField"] }] });
182
+ `, 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"] }] });
183
183
  }
184
184
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FolderFormComponent, decorators: [{
185
185
  type: Component,
@@ -195,7 +195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
195
195
  {{ isEditMode() ? 'Edit Folder' : 'New Folder' }}
196
196
  </h3>
197
197
  @if (showCompanyInfo()) {
198
- <p class="text-sm text-gray-600 mt-1">
198
+ <p class="text-sm text-muted-color mt-1">
199
199
  Company: {{ currentCompanyName() }}
200
200
  </p>
201
201
  }
@@ -250,4 +250,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
250
250
  }] });
251
251
 
252
252
  export { FolderFormComponent };
253
- //# sourceMappingURL=flusys-ng-storage-folder-form.component-DH-KCz21.mjs.map
253
+ //# sourceMappingURL=flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs","sources":["../../../projects/ng-storage/pages/folder/folder-form.component.ts"],"sourcesContent":["import { Component, computed, inject, OnInit, signal } from '@angular/core';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { APP_CONFIG, DEFAULT_APP_NAME } from '@flusys/ng-core';\nimport { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';\nimport { AngularModule, PrimeModule } from '@flusys/ng-shared';\nimport { MessageService } from 'primeng/api';\nimport { IFolder } from '../../interfaces/folder.interface';\nimport { FolderApiService } from '../../services/folder-api.service';\n\n/** Folder form model interface */\ninterface IFolderFormModel {\n id: string;\n name: string;\n}\n\n/**\n * Folder Form Component\n * Create and edit folders\n */\n@Component({\n selector: 'lib-folder-form',\n standalone: true,\n imports: [AngularModule, PrimeModule, FormField],\n template: `\n <div class=\"card\">\n <div class=\"flex justify-between items-center mb-4\">\n <div>\n <h3 class=\"text-xl font-semibold\">\n {{ isEditMode() ? 'Edit Folder' : 'New Folder' }}\n </h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n Company: {{ currentCompanyName() }}\n </p>\n }\n </div>\n <p-button\n label=\"Back\"\n icon=\"pi pi-arrow-left\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"onCancel()\"\n />\n </div>\n\n <form (ngSubmit)=\"onSubmit()\">\n <div class=\"grid grid-cols-1 gap-4\">\n <!-- Name -->\n <div class=\"field\">\n <label for=\"name\" class=\"block font-medium mb-2\"\n >Folder Name *</label\n >\n <input\n pInputText\n id=\"name\"\n [formField]=\"folderForm.name\"\n placeholder=\"Enter folder name\"\n class=\"w-full\"\n />\n </div>\n </div>\n\n <div class=\"flex gap-2 mt-4\">\n <p-button\n type=\"submit\"\n [label]=\"isEditMode() ? 'Update' : 'Create'\"\n icon=\"pi pi-check\"\n [loading]=\"isLoading()\"\n [disabled]=\"!isFormValid() || isLoading()\"\n />\n <p-button\n type=\"button\"\n label=\"Cancel\"\n severity=\"secondary\"\n icon=\"pi pi-times\"\n [text]=\"true\"\n (onClick)=\"onCancel()\"\n />\n </div>\n </form>\n </div>\n `,\n})\nexport class FolderFormComponent implements OnInit {\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly messageService = inject(MessageService);\n private readonly folderService = inject(FolderApiService);\n private readonly appConfig = inject(APP_CONFIG);\n private readonly companyContext = inject(LAYOUT_AUTH_STATE);\n\n readonly isLoading = signal(false);\n readonly existingFolder = signal<IFolder | null>(null);\n readonly isEditMode = computed(() => !!this.existingFolder());\n\n /** Show company info if company feature enabled */\n readonly showCompanyInfo = computed(\n () => this.appConfig.enableCompanyFeature,\n );\n\n /** Current company name */\n readonly currentCompanyName = computed(\n () => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME,\n );\n\n // ============================================\n // Form (Signal Forms)\n // ============================================\n\n /** Form model */\n readonly formModel = signal<IFolderFormModel>({\n id: '',\n name: '',\n });\n\n /** Form with validation schema */\n readonly folderForm = form(this.formModel, (f) => {\n required(f.name, { message: 'Folder name is required' });\n });\n\n /** Check if form is valid */\n readonly isFormValid = computed(() => {\n const model = this.formModel();\n return model.name.trim().length > 0;\n });\n\n ngOnInit(): void {\n const folderId = this.route.snapshot.paramMap.get('id');\n if (folderId) {\n this.loadFolder(folderId);\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({\n id: folder.id,\n name: folder.name,\n });\n }\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: 'Failed to load folder.',\n });\n this.router.navigate(['/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({\n id: formValue.id,\n name: formValue.name,\n });\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Folder updated successfully.',\n });\n } else {\n await this.folderService.insertAsync({\n name: formValue.name,\n } as any);\n this.messageService.add({\n severity: 'success',\n summary: 'Success',\n detail: 'Folder created successfully.',\n });\n }\n\n this.router.navigate(['/storage/folders']);\n } catch (error) {\n this.messageService.add({\n severity: 'error',\n summary: 'Error',\n detail: `Failed to ${this.isEditMode() ? 'update' : 'create'} folder.`,\n });\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onCancel(): void {\n this.router.navigate(['/storage/folders']);\n }\n}\n"],"names":["i2"],"mappings":"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"}