@flusys/ng-storage 1.1.1-beta → 1.2.0-rc.1

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 (29) hide show
  1. package/README.md +36 -623
  2. package/fesm2022/flusys-ng-storage-file-manager-form.component-DhqZmpuX.mjs +671 -0
  3. package/fesm2022/flusys-ng-storage-file-manager-form.component-DhqZmpuX.mjs.map +1 -0
  4. package/fesm2022/flusys-ng-storage-file-manager-list.component-nZDj1UfS.mjs +464 -0
  5. package/fesm2022/flusys-ng-storage-file-manager-list.component-nZDj1UfS.mjs.map +1 -0
  6. package/fesm2022/flusys-ng-storage-folder-form.component-Bru9NQyr.mjs +218 -0
  7. package/fesm2022/flusys-ng-storage-folder-form.component-Bru9NQyr.mjs.map +1 -0
  8. package/fesm2022/flusys-ng-storage-folder-list.component-fuJMWYWZ.mjs +263 -0
  9. package/fesm2022/flusys-ng-storage-folder-list.component-fuJMWYWZ.mjs.map +1 -0
  10. package/fesm2022/flusys-ng-storage-storage-config-form.component-Da-pWR7d.mjs +891 -0
  11. package/fesm2022/flusys-ng-storage-storage-config-form.component-Da-pWR7d.mjs.map +1 -0
  12. package/fesm2022/flusys-ng-storage-storage-config-list.component-D59X4sae.mjs +288 -0
  13. package/fesm2022/flusys-ng-storage-storage-config-list.component-D59X4sae.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-storage.mjs +679 -321
  15. package/fesm2022/flusys-ng-storage.mjs.map +1 -1
  16. package/package.json +11 -10
  17. package/types/flusys-ng-storage.d.ts +179 -178
  18. package/fesm2022/flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs +0 -715
  19. package/fesm2022/flusys-ng-storage-file-manager-form.component-H3OZS0SW.mjs.map +0 -1
  20. package/fesm2022/flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs +0 -475
  21. package/fesm2022/flusys-ng-storage-file-manager-list.component-4pb6TafD.mjs.map +0 -1
  22. package/fesm2022/flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs +0 -253
  23. package/fesm2022/flusys-ng-storage-folder-form.component-DQ0QY7P0.mjs.map +0 -1
  24. package/fesm2022/flusys-ng-storage-folder-list.component-D-oMaEgl.mjs +0 -267
  25. package/fesm2022/flusys-ng-storage-folder-list.component-D-oMaEgl.mjs.map +0 -1
  26. package/fesm2022/flusys-ng-storage-storage-config-form.component-CjIAxfHC.mjs +0 -546
  27. package/fesm2022/flusys-ng-storage-storage-config-form.component-CjIAxfHC.mjs.map +0 -1
  28. package/fesm2022/flusys-ng-storage-storage-config-list.component-jHk8O9Mx.mjs +0 -328
  29. package/fesm2022/flusys-ng-storage-storage-config-list.component-jHk8O9Mx.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-storage-file-manager-form.component-DhqZmpuX.mjs","sources":["../../../projects/ng-storage/pages/file-manager/file-manager-form.component.ts"],"sourcesContent":["import { Component, computed, effect, inject, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { form, FormField, required } from '@angular/forms/signals';\nimport { ActivatedRoute } from '@angular/router';\nimport {\n AngularModule,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\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';\nimport { BaseStoragePage } from '../../utils/base-storage-page';\nimport { formatFileSize, getProviderLabelKey } from '../../utils/storage-utils';\nimport { FileSelectEvent, UiModule } from '@flusys/ng-ui';\n\ninterface IFileManagerFormModel {\n id: string;\n name: string;\n isPrivate: boolean;\n folderId: string;\n storageConfigId: string;\n}\n\n@Component({\n selector: 'lib-file-manager-form',\n imports: [AngularModule, UiModule, FormField, TranslatePipe],\n template: `\n <div class=\"card\">\n <div class=\"mb-4\">\n <h3 class=\"text-lg sm:text-xl font-semibold\">\n {{\n (isEditMode()\n ? 'storage.file.manager.edit.file'\n : 'storage.file.manager.upload.file'\n ) | translate\n }}\n </h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n {{ 'shared.company' | translate }}: {{ currentCompanyName() }}\n </p>\n }\n </div>\n\n <form (ngSubmit)=\"onSubmit()\">\n @if (!isEditMode()) {\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 mb-4\">\n <div class=\"field\">\n <label\n for=\"storageConfig\"\n class=\"block font-medium mb-2 text-sm sm:text-base\"\n >{{ 'storage.config.provider.required' | translate }}</label\n >\n <f-select\n inputId=\"storageConfig\"\n [options]=\"availableConfigs()\"\n optionValue=\"id\"\n [formField]=\"fileForm.storageConfigId\"\n [placeholder]=\"'storage.config.select.config' | translate\"\n >\n <ng-template #item let-config>{{ config.name }} ({{ getProviderLabelKey(config.storage) | translate }})</ng-template>\n <ng-template #selectedItem let-config>{{ config.name }} ({{ getProviderLabelKey(config.storage) | translate }})</ng-template>\n </f-select>\n @if (availableConfigs().length === 0 && !isLoadingConfigs()) {\n <small class=\"text-warn block mt-2\">\n <ui-icon name=\"exclamation-triangle\" class=\"mr-1\"></ui-icon>\n {{ 'storage.config.no.configs' | translate }}\n </small>\n }\n </div>\n\n <div class=\"field\">\n <label\n for=\"folder\"\n class=\"block font-medium mb-2 text-sm sm:text-base\"\n >{{ 'storage.folder.optional' | translate }}</label\n >\n <f-select\n inputId=\"folder\"\n [options]=\"availableFolders()\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [formField]=\"fileForm.folderId\"\n [placeholder]=\"'storage.folder.no.folder' | translate\"\n />\n @if (availableFolders().length === 0 && !isLoadingFolders()) {\n <small class=\"text-muted-color block mt-2\">\n <ui-icon name=\"info-circle\" class=\"mr-1\"></ui-icon>\n {{ 'storage.folder.no.folders.available' | translate }}\n </small>\n }\n </div>\n </div>\n } @else {\n <div class=\"field mb-4\">\n <label\n for=\"folder\"\n class=\"block font-medium mb-2 text-sm sm:text-base\"\n >{{ 'storage.folder.optional' | translate }}</label\n >\n <f-select\n inputId=\"folder\"\n [options]=\"availableFolders()\"\n optionLabel=\"name\"\n optionValue=\"id\"\n [formField]=\"fileForm.folderId\"\n [placeholder]=\"'storage.folder.no.folder' | translate\"\n />\n @if (availableFolders().length === 0 && !isLoadingFolders()) {\n <small class=\"text-muted-color block mt-2\">\n <ui-icon name=\"info-circle\" class=\"mr-1\"></ui-icon>\n {{ 'storage.folder.no.folders.edit' | translate }}\n </small>\n }\n </div>\n }\n\n @if (!isEditMode()) {\n <div class=\"field mb-4\">\n <label class=\"block font-medium mb-2 text-sm sm:text-base\">{{\n 'storage.file.select.required' | translate\n }}</label>\n <f-fileupload\n #fileUpload\n [customUpload]=\"true\"\n (onSelect)=\"onFileSelect($event)\"\n [multiple]=\"false\"\n [maxFileSize]=\"50000000\"\n [showUploadButton]=\"false\"\n [showCancelButton]=\"false\"\n [chooseLabel]=\"'storage.button.choose.file' | translate\"\n chooseIcon=\"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\n class=\"flex items-center gap-3 p-3 border border-surface rounded-lg bg-surface-ground\"\n >\n <ui-icon name=\"file\" class=\"text-xl sm:text-2xl text-primary\"></ui-icon>\n <div class=\"flex-1 min-w-0\">\n <div class=\"font-medium truncate\">\n {{ file.name }}\n </div>\n <div class=\"text-sm text-muted-color\">\n {{ formatFileSize(file.size) }}\n </div>\n </div>\n <button\n fButton\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n (click)=\"fileUpload.clear()\"\n >\n <ui-icon pButtonIcon name=\"times\"></ui-icon>\n </button>\n </div>\n }\n </div>\n } @else {\n <div\n class=\"flex items-center justify-center flex-col p-6 sm:p-8 border-2 border-dashed border-surface rounded-lg\"\n >\n <ui-icon name=\"cloud-upload\" class=\"text-3xl sm:text-4xl text-muted-color mb-3\"></ui-icon>\n <p\n class=\"text-muted-color text-center text-sm sm:text-base\"\n >\n {{ 'storage.upload.drag.drop' | translate }}\n </p>\n <p class=\"text-xs sm:text-sm text-muted-color mt-2\">\n {{\n 'storage.upload.max.size' | translate: { size: '50MB' }\n }}\n </p>\n </div>\n }\n </ng-template>\n </f-fileupload>\n @if (!selectedFile() && !isEditMode()) {\n <small class=\"text-muted-color\">{{\n 'storage.upload.please.select' | translate\n }}</small>\n }\n </div>\n }\n\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div class=\"field md:col-span-2\">\n <label\n for=\"name\"\n class=\"block font-medium mb-2 text-sm sm:text-base\"\n >{{ 'storage.file.name.required' | translate }}</label\n >\n <input\n fInputText\n id=\"name\"\n [formField]=\"fileForm.name\"\n [placeholder]=\"\n (isEditMode()\n ? 'storage.file.placeholder.edit'\n : 'storage.file.placeholder'\n ) | translate\n \"\n class=\"w-full\"\n />\n </div>\n\n <div class=\"field\">\n <f-checkbox [formField]=\"fileForm.isPrivate\" [label]=\"'storage.file.private' | translate\" />\n <small class=\"text-muted-color block mt-2\">\n {{\n (formModel().isPrivate\n ? 'storage.file.private.hint'\n : 'storage.file.public.hint'\n ) | translate\n }}\n </small>\n </div>\n </div>\n\n <div class=\"flex justify-end gap-2 mt-4\">\n <button\n fButton\n severity=\"secondary\"\n [outlined]=\"true\"\n (click)=\"onCancel()\"\n >\n <span pButtonLabel>{{ 'shared.cancel' | translate }}</span>\n </button>\n <button\n fButton\n type=\"submit\"\n [disabled]=\"\n !isFormValid() ||\n (!isEditMode() && !selectedFile()) ||\n isLoading()\n \"\n >\n @if (isLoading()) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n }\n <span pButtonLabel>{{ \n (isEditMode() ? 'shared.update' : 'shared.upload') | translate\n }}</span>\n </button>\n </div>\n </form>\n </div>\n `,\n})\nexport class FileManagerFormComponent extends BaseStoragePage {\n private readonly route = inject(ActivatedRoute);\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 translateService = inject(TranslateService);\n\n private readonly routeParams = toSignal(this.route.paramMap);\n private initialized = false;\n\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 formatFileSize = formatFileSize;\n readonly getProviderLabelKey = getProviderLabelKey;\n\n readonly formModel = signal<IFileManagerFormModel>({\n id: '',\n name: '',\n isPrivate: false,\n folderId: '',\n storageConfigId: '',\n });\n\n readonly fileForm = form(this.formModel, (f) => {\n required(f.name, {\n message: this.translateService.translate(\n 'storage.validation.file.name.required',\n ),\n });\n });\n\n readonly isFormValid = computed(\n () => this.formModel().name.trim().length > 0,\n );\n\n constructor() {\n super();\n effect(() => {\n const params = this.routeParams();\n if (!params || this.initialized) return;\n\n this.initialized = true;\n const fileId = params.get('id');\n if (fileId) {\n this.loadFile(fileId);\n } else {\n this.loadStorageConfigs();\n }\n this.loadFolders();\n });\n }\n\n async loadStorageConfigs(): Promise<void> {\n this.isLoadingConfigs.set(true);\n try {\n const response = await this.configService.getAll({\n pagination: { currentPage: 0, pageSize: 100 },\n filter: {},\n select: [],\n sort: {},\n });\n if (response.success && response.data) {\n this.availableConfigs.set(response.data);\n if (response.data.length === 1) {\n this.formModel.update((m) => ({\n ...m,\n storageConfigId: response.data![0].id,\n }));\n }\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 this.folderService.getAll({\n pagination: { currentPage: 0, pageSize: 100 },\n filter: {},\n select: [],\n sort: {},\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.findById(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 {\n this.navigateTo(['/storage/files']);\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onFileSelect(event: FileSelectEvent): void {\n const file = event.files?.[0] || event.currentFiles?.[0];\n if (file) {\n this.selectedFile.set(file);\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 const response = await this.fileService.update({\n id: formValue.id,\n name: formValue.name,\n isPrivate: formValue.isPrivate,\n folderId: formValue.folderId || null,\n });\n this.showSuccess(\n response.messageKey\n ? this.translateService.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : (response.message ?? ''),\n );\n } else {\n const file = this.selectedFile();\n if (!file) {\n this.showError(\n this.translateService.translate('storage.error.no.file'),\n );\n return;\n }\n\n if (!formValue.storageConfigId) {\n this.showError(\n this.translateService.translate('storage.error.no.config'),\n );\n return;\n }\n\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 const createResponse = await firstValueFrom(\n this.fileService.createFile({\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,\n }),\n );\n this.showSuccess(\n createResponse?.messageKey\n ? this.translateService.translate(\n createResponse.messageKey,\n createResponse.messageVariables as Record<\n string,\n string | number\n >,\n )\n : (createResponse?.message ?? ''),\n );\n } else {\n throw new Error(\n this.translateService.translate('storage.upload.failed'),\n );\n }\n }\n\n this.navigateTo(['/storage/files']);\n } catch {\n this.showError(this.translateService.translate('storage.upload.failed'));\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onCancel(): void {\n this.navigateTo(['/storage/files']);\n }\n}\n"],"names":["i2"],"mappings":"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"}
@@ -0,0 +1,464 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Component } from '@angular/core';
3
+ import { FILE_PERMISSIONS, TranslateService, AngularModule, HasPermissionDirective, TranslatePipe } from '@flusys/ng-shared';
4
+ import * as i1 from '@flusys/ng-ui';
5
+ import { UiModule } from '@flusys/ng-ui';
6
+ import { firstValueFrom } from 'rxjs';
7
+ import { BaseStorageListPage, FileManagerApiService, getFileIcon, getProviderLabelKey, getProviderSeverity } from './flusys-ng-storage.mjs';
8
+ import * as i2 from '@angular/common';
9
+
10
+ class FileManagerListComponent extends BaseStorageListPage {
11
+ FILE_PERMISSIONS = FILE_PERMISSIONS;
12
+ fileService = inject(FileManagerApiService);
13
+ translateService = inject(TranslateService);
14
+ files = this.items;
15
+ viewingFileId = signal(null, /* @ts-ignore */
16
+ ...(ngDevMode ? [{ debugName: "viewingFileId" }] : /* istanbul ignore next */ []));
17
+ getFileIcon = getFileIcon;
18
+ getProviderLabelKey = getProviderLabelKey;
19
+ getProviderSeverity = getProviderSeverity;
20
+ getResourceRoute() {
21
+ return '/storage/files';
22
+ }
23
+ getDeleteConfirmMessage(file) {
24
+ return this.translateService.translate('shared.confirm.delete.item', {
25
+ name: file.name,
26
+ });
27
+ }
28
+ async loadData() {
29
+ this.isLoading.set(true);
30
+ try {
31
+ const response = await this.fileService.getAll({
32
+ pagination: this.getPaginationParams(),
33
+ filter: {},
34
+ select: [],
35
+ sort: {},
36
+ });
37
+ if (response.success) {
38
+ this.items.set(response.data ?? []);
39
+ this.total.set(response.meta?.total ?? 0);
40
+ }
41
+ }
42
+ finally {
43
+ this.isLoading.set(false);
44
+ }
45
+ }
46
+ onUpload() {
47
+ this.navigateTo(['/storage/files/new']);
48
+ }
49
+ async onView(file) {
50
+ this.viewingFileId.set(file.id);
51
+ try {
52
+ const response = await firstValueFrom(this.fileService.getFiles([file.id]));
53
+ if (response.success && response.data?.length && response.data[0].url) {
54
+ window.open(response.data[0].url, '_blank');
55
+ }
56
+ else {
57
+ this.showError(this.translateService.translate('storage.file.url.not.available'));
58
+ }
59
+ }
60
+ finally {
61
+ this.viewingFileId.set(null);
62
+ }
63
+ }
64
+ onSoftDelete(file) {
65
+ this.confirmationService.confirm({
66
+ message: this.translateService.translate('storage.delete.move.to.trash.confirm', { name: file.name }),
67
+ header: this.translateService.translate('storage.delete.move.to.trash'),
68
+ icon: 'trash',
69
+ acceptLabel: this.translateService.translate('storage.delete.move.to.trash'),
70
+ acceptButtonStyleClass: 'p-button-warning',
71
+ accept: async () => {
72
+ try {
73
+ const response = await this.fileService.delete({
74
+ id: file.id,
75
+ type: 'delete',
76
+ });
77
+ this.showSuccess(response?.messageKey
78
+ ? this.translateService.translate(response.messageKey, response.messageVariables)
79
+ : (response?.message ?? ''));
80
+ this.loadData();
81
+ }
82
+ catch { }
83
+ },
84
+ });
85
+ }
86
+ onPermanentDelete(file) {
87
+ this.confirmationService.confirm({
88
+ message: this.translateService.translate('storage.delete.permanent.delete.confirm', { name: file.name }),
89
+ header: this.translateService.translate('storage.delete.permanent.delete'),
90
+ icon: 'exclamation-triangle',
91
+ acceptLabel: this.translateService.translate('storage.delete.permanent.delete.button'),
92
+ rejectLabel: this.translateService.translate('shared.cancel'),
93
+ acceptButtonStyleClass: 'p-button-danger',
94
+ accept: async () => {
95
+ try {
96
+ const response = await this.fileService.delete({
97
+ id: file.id,
98
+ type: 'permanent',
99
+ });
100
+ this.showSuccess(response?.messageKey
101
+ ? this.translateService.translate(response.messageKey, response.messageVariables)
102
+ : (response?.message ?? ''));
103
+ this.loadData();
104
+ }
105
+ catch { }
106
+ },
107
+ });
108
+ }
109
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileManagerListComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
110
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.6", type: FileManagerListComponent, isStandalone: true, selector: "lib-file-manager-list", usesInheritance: true, ngImport: i0, template: `
111
+ <div class="card">
112
+ <div
113
+ class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4"
114
+ >
115
+ <div>
116
+ <h3 class="text-lg sm:text-xl font-semibold">
117
+ {{ 'storage.file.manager.title' | translate }}
118
+ </h3>
119
+ @if (showCompanyInfo()) {
120
+ <p class="text-sm text-muted-color mt-1">
121
+ {{ 'shared.company' | translate }}: {{ currentCompanyName() }}
122
+ </p>
123
+ }
124
+ </div>
125
+ <button
126
+ fButton
127
+ *hasPermission="FILE_PERMISSIONS.CREATE"
128
+ (click)="onUpload()"
129
+ class="w-full sm:w-auto"
130
+ >
131
+ <ui-icon pButtonIcon name="upload"></ui-icon>
132
+ <span pButtonLabel>{{ 'storage.button.upload.file' | translate }}</span>
133
+ </button>
134
+ </div>
135
+
136
+ <div class="overflow-x-auto">
137
+ <f-table
138
+ [value]="files()"
139
+ [loading]="isLoading()"
140
+ [paginator]="totalRecords() > 0"
141
+ [rows]="pageSize()"
142
+ [totalRecords]="totalRecords()"
143
+ [lazy]="true"
144
+ (onLazyLoad)="onPageChange($event)"
145
+ [rowsPerPageOptions]="[10, 25, 50]"
146
+ [scrollable]="true"
147
+ >
148
+ <ng-template #header>
149
+ <tr>
150
+ <th>{{ 'shared.name' | translate }}</th>
151
+ <th class="hidden lg:table-cell">
152
+ {{ 'shared.type' | translate }}
153
+ </th>
154
+ <th>{{ 'storage.table.size' | translate }}</th>
155
+ <th>{{ 'storage.table.location' | translate }}</th>
156
+ <th class="hidden xl:table-cell">
157
+ {{ 'storage.table.config' | translate }}
158
+ </th>
159
+ <th>{{ 'storage.table.private' | translate }}</th>
160
+ <th class="hidden md:table-cell">
161
+ {{ 'storage.table.created' | translate }}
162
+ </th>
163
+ <th class="w-[120px]">{{ 'shared.actions' | translate }}</th>
164
+ </tr>
165
+ </ng-template>
166
+ <ng-template #body let-file>
167
+ @let isViewing = viewingFileId() === file.id;
168
+ <tr>
169
+ <td>
170
+ <div class="flex items-center gap-2">
171
+ <ui-icon [name]="getFileIcon(file.contentType)"></ui-icon>
172
+ <span class="truncate max-w-32 sm:max-w-none">{{
173
+ file.name
174
+ }}</span>
175
+ </div>
176
+ </td>
177
+ <td class="hidden lg:table-cell">
178
+ <span class="text-sm text-muted-color">{{
179
+ file.contentType
180
+ }}</span>
181
+ </td>
182
+ <td>{{ file.size }} {{ 'shared.size.kb' | translate }}</td>
183
+ <td>
184
+ <f-tag
185
+ [value]="getProviderLabelKey(file.location) | translate"
186
+ [severity]="getProviderSeverity(file.location)"
187
+ />
188
+ </td>
189
+ <td class="hidden xl:table-cell">
190
+ {{ file.providerName || '-' }}
191
+ </td>
192
+ <td>
193
+ @if (file.isPrivate) {
194
+ <f-tag
195
+ [value]="'storage.private' | translate"
196
+ severity="warn"
197
+ />
198
+ } @else {
199
+ <f-tag
200
+ [value]="'storage.public' | translate"
201
+ severity="success"
202
+ />
203
+ }
204
+ </td>
205
+ <td class="hidden md:table-cell">
206
+ {{ file.createdAt | date: 'short' }}
207
+ </td>
208
+ <td>
209
+ <div class="flex gap-1">
210
+ <button
211
+ fButton
212
+ *hasPermission="FILE_PERMISSIONS.READ"
213
+ [text]="true"
214
+ severity="secondary"
215
+ size="small"
216
+ [disabled]="isViewing"
217
+ (click)="onView(file)"
218
+ [fTooltip]="'shared.view' | translate"
219
+ tooltipPosition="top"
220
+ >
221
+ @if (isViewing) {
222
+ <ui-icon pButtonIcon name="spinner" [spin]="true"></ui-icon>
223
+ } @else {
224
+ <ui-icon pButtonIcon name="eye"></ui-icon>
225
+ }
226
+ </button>
227
+ <button
228
+ fButton
229
+ *hasPermission="FILE_PERMISSIONS.UPDATE"
230
+ [text]="true"
231
+ severity="secondary"
232
+ size="small"
233
+ (click)="onEdit(file.id)"
234
+ [fTooltip]="'shared.edit' | translate"
235
+ tooltipPosition="top"
236
+ >
237
+ <ui-icon pButtonIcon name="pencil"></ui-icon>
238
+ </button>
239
+ <button
240
+ fButton
241
+ *hasPermission="FILE_PERMISSIONS.DELETE"
242
+ [text]="true"
243
+ severity="warn"
244
+ size="small"
245
+ (click)="onSoftDelete(file)"
246
+ [fTooltip]="'storage.tooltip.trash' | translate"
247
+ tooltipPosition="top"
248
+ >
249
+ <ui-icon pButtonIcon name="trash"></ui-icon>
250
+ </button>
251
+ <button
252
+ fButton
253
+ *hasPermission="FILE_PERMISSIONS.DELETE"
254
+ [text]="true"
255
+ severity="danger"
256
+ size="small"
257
+ (click)="onPermanentDelete(file)"
258
+ [fTooltip]="'shared.delete' | translate"
259
+ tooltipPosition="top"
260
+ >
261
+ <ui-icon pButtonIcon name="times-circle"></ui-icon>
262
+ </button>
263
+ </div>
264
+ </td>
265
+ </tr>
266
+ </ng-template>
267
+ <ng-template #emptymessage>
268
+ <tr>
269
+ <td colspan="8" class="text-center py-4 text-muted-color">
270
+ @if (showCompanyInfo()) {
271
+ {{ 'storage.empty.files.in.company' | translate }}
272
+ } @else {
273
+ {{ 'storage.empty.files' | translate }}
274
+ }
275
+ </td>
276
+ </tr>
277
+ </ng-template>
278
+ </f-table>
279
+ </div>
280
+ </div>
281
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: UiModule }, { kind: "directive", type: i1.FButtonDirective, selector: "[fButton]", inputs: ["severity", "text", "outlined", "link", "variant", "rounded", "raised", "fluid", "disabled", "loading", "loadingIcon", "size", "label", "icon", "iconPos", "ariaLabel", "plain"] }, { kind: "component", type: i1.TagComponent, selector: "f-tag", inputs: ["value", "severity", "icon", "rounded", "color", "styleClass", "style"] }, { kind: "component", type: i1.TableComponent, selector: "f-table", inputs: ["value", "lazy", "loading", "rows", "totalRecords", "rowHover", "dataKey", "scrollable", "scrollHeight", "paginator", "first", "rowsPerPageOptions", "showCurrentPageReport", "currentPageReportTemplate", "tableStyle", "styleClass", "globalFilterFields", "filterDelay", "responsiveLayout", "selectionMode", "sortMode", "rowExpandMode", "resizableColumns", "rowStyleClass", "virtualScroll", "virtualScrollItemSize", "sortField", "sortOrder", "multiSortMeta", "filters", "selection", "expandedRowKeys", "contextMenuSelection"], outputs: ["sortFieldChange", "sortOrderChange", "multiSortMetaChange", "filtersChange", "selectionChange", "expandedRowKeysChange", "contextMenuSelectionChange", "onLazyLoad", "onSort", "onFilter", "onRowSelect", "onRowUnselect", "onSelectAllChange", "onRowExpand", "onRowCollapse", "onColResize", "onRowContextMenu"] }, { kind: "directive", type: i1.TooltipDirective, selector: "[fTooltip]", inputs: ["fTooltip", "tooltipPosition", "positionStyle", "tooltipStyleClass", "disabled", "tooltipEvent", "showDelay", "hideDelay", "life", "autoHide", "positionTop", "positionLeft", "escape"] }, { kind: "component", type: i1.UiIconComponent, selector: "ui-icon", inputs: ["name", "size", "spin", "fill", "severity"] }, { kind: "ngmodule", type: AngularModule }, { kind: "directive", type: HasPermissionDirective, selector: "[hasPermission]", inputs: ["hasPermission"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
282
+ }
283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: FileManagerListComponent, decorators: [{
284
+ type: Component,
285
+ args: [{
286
+ selector: 'lib-file-manager-list',
287
+ imports: [UiModule, AngularModule, HasPermissionDirective, TranslatePipe],
288
+ template: `
289
+ <div class="card">
290
+ <div
291
+ class="flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4"
292
+ >
293
+ <div>
294
+ <h3 class="text-lg sm:text-xl font-semibold">
295
+ {{ 'storage.file.manager.title' | translate }}
296
+ </h3>
297
+ @if (showCompanyInfo()) {
298
+ <p class="text-sm text-muted-color mt-1">
299
+ {{ 'shared.company' | translate }}: {{ currentCompanyName() }}
300
+ </p>
301
+ }
302
+ </div>
303
+ <button
304
+ fButton
305
+ *hasPermission="FILE_PERMISSIONS.CREATE"
306
+ (click)="onUpload()"
307
+ class="w-full sm:w-auto"
308
+ >
309
+ <ui-icon pButtonIcon name="upload"></ui-icon>
310
+ <span pButtonLabel>{{ 'storage.button.upload.file' | translate }}</span>
311
+ </button>
312
+ </div>
313
+
314
+ <div class="overflow-x-auto">
315
+ <f-table
316
+ [value]="files()"
317
+ [loading]="isLoading()"
318
+ [paginator]="totalRecords() > 0"
319
+ [rows]="pageSize()"
320
+ [totalRecords]="totalRecords()"
321
+ [lazy]="true"
322
+ (onLazyLoad)="onPageChange($event)"
323
+ [rowsPerPageOptions]="[10, 25, 50]"
324
+ [scrollable]="true"
325
+ >
326
+ <ng-template #header>
327
+ <tr>
328
+ <th>{{ 'shared.name' | translate }}</th>
329
+ <th class="hidden lg:table-cell">
330
+ {{ 'shared.type' | translate }}
331
+ </th>
332
+ <th>{{ 'storage.table.size' | translate }}</th>
333
+ <th>{{ 'storage.table.location' | translate }}</th>
334
+ <th class="hidden xl:table-cell">
335
+ {{ 'storage.table.config' | translate }}
336
+ </th>
337
+ <th>{{ 'storage.table.private' | translate }}</th>
338
+ <th class="hidden md:table-cell">
339
+ {{ 'storage.table.created' | translate }}
340
+ </th>
341
+ <th class="w-[120px]">{{ 'shared.actions' | translate }}</th>
342
+ </tr>
343
+ </ng-template>
344
+ <ng-template #body let-file>
345
+ @let isViewing = viewingFileId() === file.id;
346
+ <tr>
347
+ <td>
348
+ <div class="flex items-center gap-2">
349
+ <ui-icon [name]="getFileIcon(file.contentType)"></ui-icon>
350
+ <span class="truncate max-w-32 sm:max-w-none">{{
351
+ file.name
352
+ }}</span>
353
+ </div>
354
+ </td>
355
+ <td class="hidden lg:table-cell">
356
+ <span class="text-sm text-muted-color">{{
357
+ file.contentType
358
+ }}</span>
359
+ </td>
360
+ <td>{{ file.size }} {{ 'shared.size.kb' | translate }}</td>
361
+ <td>
362
+ <f-tag
363
+ [value]="getProviderLabelKey(file.location) | translate"
364
+ [severity]="getProviderSeverity(file.location)"
365
+ />
366
+ </td>
367
+ <td class="hidden xl:table-cell">
368
+ {{ file.providerName || '-' }}
369
+ </td>
370
+ <td>
371
+ @if (file.isPrivate) {
372
+ <f-tag
373
+ [value]="'storage.private' | translate"
374
+ severity="warn"
375
+ />
376
+ } @else {
377
+ <f-tag
378
+ [value]="'storage.public' | translate"
379
+ severity="success"
380
+ />
381
+ }
382
+ </td>
383
+ <td class="hidden md:table-cell">
384
+ {{ file.createdAt | date: 'short' }}
385
+ </td>
386
+ <td>
387
+ <div class="flex gap-1">
388
+ <button
389
+ fButton
390
+ *hasPermission="FILE_PERMISSIONS.READ"
391
+ [text]="true"
392
+ severity="secondary"
393
+ size="small"
394
+ [disabled]="isViewing"
395
+ (click)="onView(file)"
396
+ [fTooltip]="'shared.view' | translate"
397
+ tooltipPosition="top"
398
+ >
399
+ @if (isViewing) {
400
+ <ui-icon pButtonIcon name="spinner" [spin]="true"></ui-icon>
401
+ } @else {
402
+ <ui-icon pButtonIcon name="eye"></ui-icon>
403
+ }
404
+ </button>
405
+ <button
406
+ fButton
407
+ *hasPermission="FILE_PERMISSIONS.UPDATE"
408
+ [text]="true"
409
+ severity="secondary"
410
+ size="small"
411
+ (click)="onEdit(file.id)"
412
+ [fTooltip]="'shared.edit' | translate"
413
+ tooltipPosition="top"
414
+ >
415
+ <ui-icon pButtonIcon name="pencil"></ui-icon>
416
+ </button>
417
+ <button
418
+ fButton
419
+ *hasPermission="FILE_PERMISSIONS.DELETE"
420
+ [text]="true"
421
+ severity="warn"
422
+ size="small"
423
+ (click)="onSoftDelete(file)"
424
+ [fTooltip]="'storage.tooltip.trash' | translate"
425
+ tooltipPosition="top"
426
+ >
427
+ <ui-icon pButtonIcon name="trash"></ui-icon>
428
+ </button>
429
+ <button
430
+ fButton
431
+ *hasPermission="FILE_PERMISSIONS.DELETE"
432
+ [text]="true"
433
+ severity="danger"
434
+ size="small"
435
+ (click)="onPermanentDelete(file)"
436
+ [fTooltip]="'shared.delete' | translate"
437
+ tooltipPosition="top"
438
+ >
439
+ <ui-icon pButtonIcon name="times-circle"></ui-icon>
440
+ </button>
441
+ </div>
442
+ </td>
443
+ </tr>
444
+ </ng-template>
445
+ <ng-template #emptymessage>
446
+ <tr>
447
+ <td colspan="8" class="text-center py-4 text-muted-color">
448
+ @if (showCompanyInfo()) {
449
+ {{ 'storage.empty.files.in.company' | translate }}
450
+ } @else {
451
+ {{ 'storage.empty.files' | translate }}
452
+ }
453
+ </td>
454
+ </tr>
455
+ </ng-template>
456
+ </f-table>
457
+ </div>
458
+ </div>
459
+ `,
460
+ }]
461
+ }] });
462
+
463
+ export { FileManagerListComponent };
464
+ //# sourceMappingURL=flusys-ng-storage-file-manager-list.component-nZDj1UfS.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flusys-ng-storage-file-manager-list.component-nZDj1UfS.mjs","sources":["../../../projects/ng-storage/pages/file-manager/file-manager-list.component.ts"],"sourcesContent":["import { Component, inject, signal } from '@angular/core';\nimport {\n AngularModule,\n FILE_PERMISSIONS,\n HasPermissionDirective,\n TranslatePipe,\n TranslateService,\n} from '@flusys/ng-shared';\nimport { UiModule } from '@flusys/ng-ui';\nimport { firstValueFrom } from 'rxjs';\nimport { IFileManager } from '../../interfaces/file-manager.interface';\nimport { FileManagerApiService } from '../../services/file-manager-api.service';\nimport { BaseStorageListPage } from '../../utils/base-storage-page';\n\nimport {\n getFileIcon,\n getProviderLabelKey,\n getProviderSeverity,\n} from '../../utils/storage-utils';\n\n@Component({\n selector: 'lib-file-manager-list',\n imports: [UiModule, AngularModule, HasPermissionDirective, TranslatePipe],\n template: `\n <div class=\"card\">\n <div\n class=\"flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 mb-4\"\n >\n <div>\n <h3 class=\"text-lg sm:text-xl font-semibold\">\n {{ 'storage.file.manager.title' | translate }}\n </h3>\n @if (showCompanyInfo()) {\n <p class=\"text-sm text-muted-color mt-1\">\n {{ 'shared.company' | translate }}: {{ currentCompanyName() }}\n </p>\n }\n </div>\n <button\n fButton\n *hasPermission=\"FILE_PERMISSIONS.CREATE\"\n (click)=\"onUpload()\"\n class=\"w-full sm:w-auto\"\n >\n <ui-icon pButtonIcon name=\"upload\"></ui-icon>\n <span pButtonLabel>{{ 'storage.button.upload.file' | translate }}</span>\n </button>\n </div>\n\n <div class=\"overflow-x-auto\">\n <f-table\n [value]=\"files()\"\n [loading]=\"isLoading()\"\n [paginator]=\"totalRecords() > 0\"\n [rows]=\"pageSize()\"\n [totalRecords]=\"totalRecords()\"\n [lazy]=\"true\"\n (onLazyLoad)=\"onPageChange($event)\"\n [rowsPerPageOptions]=\"[10, 25, 50]\"\n [scrollable]=\"true\"\n >\n <ng-template #header>\n <tr>\n <th>{{ 'shared.name' | translate }}</th>\n <th class=\"hidden lg:table-cell\">\n {{ 'shared.type' | translate }}\n </th>\n <th>{{ 'storage.table.size' | translate }}</th>\n <th>{{ 'storage.table.location' | translate }}</th>\n <th class=\"hidden xl:table-cell\">\n {{ 'storage.table.config' | translate }}\n </th>\n <th>{{ 'storage.table.private' | translate }}</th>\n <th class=\"hidden md:table-cell\">\n {{ 'storage.table.created' | translate }}\n </th>\n <th class=\"w-[120px]\">{{ 'shared.actions' | translate }}</th>\n </tr>\n </ng-template>\n <ng-template #body let-file>\n @let isViewing = viewingFileId() === file.id;\n <tr>\n <td>\n <div class=\"flex items-center gap-2\">\n <ui-icon [name]=\"getFileIcon(file.contentType)\"></ui-icon>\n <span class=\"truncate max-w-32 sm:max-w-none\">{{\n file.name\n }}</span>\n </div>\n </td>\n <td class=\"hidden lg:table-cell\">\n <span class=\"text-sm text-muted-color\">{{\n file.contentType\n }}</span>\n </td>\n <td>{{ file.size }} {{ 'shared.size.kb' | translate }}</td>\n <td>\n <f-tag\n [value]=\"getProviderLabelKey(file.location) | translate\"\n [severity]=\"getProviderSeverity(file.location)\"\n />\n </td>\n <td class=\"hidden xl:table-cell\">\n {{ file.providerName || '-' }}\n </td>\n <td>\n @if (file.isPrivate) {\n <f-tag\n [value]=\"'storage.private' | translate\"\n severity=\"warn\"\n />\n } @else {\n <f-tag\n [value]=\"'storage.public' | translate\"\n severity=\"success\"\n />\n }\n </td>\n <td class=\"hidden md:table-cell\">\n {{ file.createdAt | date: 'short' }}\n </td>\n <td>\n <div class=\"flex gap-1\">\n <button\n fButton\n *hasPermission=\"FILE_PERMISSIONS.READ\"\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n [disabled]=\"isViewing\"\n (click)=\"onView(file)\"\n [fTooltip]=\"'shared.view' | translate\"\n tooltipPosition=\"top\"\n >\n @if (isViewing) {\n <ui-icon pButtonIcon name=\"spinner\" [spin]=\"true\"></ui-icon>\n } @else {\n <ui-icon pButtonIcon name=\"eye\"></ui-icon>\n }\n </button>\n <button\n fButton\n *hasPermission=\"FILE_PERMISSIONS.UPDATE\"\n [text]=\"true\"\n severity=\"secondary\"\n size=\"small\"\n (click)=\"onEdit(file.id)\"\n [fTooltip]=\"'shared.edit' | translate\"\n tooltipPosition=\"top\"\n >\n <ui-icon pButtonIcon name=\"pencil\"></ui-icon>\n </button>\n <button\n fButton\n *hasPermission=\"FILE_PERMISSIONS.DELETE\"\n [text]=\"true\"\n severity=\"warn\"\n size=\"small\"\n (click)=\"onSoftDelete(file)\"\n [fTooltip]=\"'storage.tooltip.trash' | translate\"\n tooltipPosition=\"top\"\n >\n <ui-icon pButtonIcon name=\"trash\"></ui-icon>\n </button>\n <button\n fButton\n *hasPermission=\"FILE_PERMISSIONS.DELETE\"\n [text]=\"true\"\n severity=\"danger\"\n size=\"small\"\n (click)=\"onPermanentDelete(file)\"\n [fTooltip]=\"'shared.delete' | translate\"\n tooltipPosition=\"top\"\n >\n <ui-icon pButtonIcon name=\"times-circle\"></ui-icon>\n </button>\n </div>\n </td>\n </tr>\n </ng-template>\n <ng-template #emptymessage>\n <tr>\n <td colspan=\"8\" class=\"text-center py-4 text-muted-color\">\n @if (showCompanyInfo()) {\n {{ 'storage.empty.files.in.company' | translate }}\n } @else {\n {{ 'storage.empty.files' | translate }}\n }\n </td>\n </tr>\n </ng-template>\n </f-table>\n </div>\n </div>\n `,\n})\nexport class FileManagerListComponent extends BaseStorageListPage<IFileManager> {\n readonly FILE_PERMISSIONS = FILE_PERMISSIONS;\n\n private readonly fileService = inject(FileManagerApiService);\n private readonly translateService = inject(TranslateService);\n\n readonly files = this.items;\n readonly viewingFileId = signal<string | null>(null);\n\n readonly getFileIcon = getFileIcon;\n readonly getProviderLabelKey = getProviderLabelKey;\n readonly getProviderSeverity = getProviderSeverity;\n\n getResourceRoute(): string {\n return '/storage/files';\n }\n\n override getDeleteConfirmMessage(file: IFileManager): string {\n return this.translateService.translate('shared.confirm.delete.item', {\n name: file.name,\n });\n }\n\n async loadData(): Promise<void> {\n this.isLoading.set(true);\n try {\n const response = await this.fileService.getAll({\n pagination: this.getPaginationParams(),\n filter: {},\n select: [],\n sort: {},\n });\n\n if (response.success) {\n this.items.set(response.data ?? []);\n this.total.set(response.meta?.total ?? 0);\n }\n } finally {\n this.isLoading.set(false);\n }\n }\n\n onUpload(): void {\n this.navigateTo(['/storage/files/new']);\n }\n\n async onView(file: IFileManager): Promise<void> {\n this.viewingFileId.set(file.id);\n try {\n const response = await firstValueFrom(\n this.fileService.getFiles([file.id]),\n );\n\n if (response.success && response.data?.length && response.data[0].url) {\n window.open(response.data[0].url, '_blank');\n } else {\n this.showError(\n this.translateService.translate('storage.file.url.not.available'),\n );\n }\n } finally {\n this.viewingFileId.set(null);\n }\n }\n\n onSoftDelete(file: IFileManager): void {\n this.confirmationService.confirm({\n message: this.translateService.translate(\n 'storage.delete.move.to.trash.confirm',\n { name: file.name },\n ),\n header: this.translateService.translate('storage.delete.move.to.trash'),\n icon: 'trash',\n acceptLabel: this.translateService.translate(\n 'storage.delete.move.to.trash',\n ),\n acceptButtonStyleClass: 'p-button-warning',\n accept: async () => {\n try {\n const response = await this.fileService.delete({\n id: file.id,\n type: 'delete',\n });\n this.showSuccess(\n response?.messageKey\n ? this.translateService.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : (response?.message ?? ''),\n );\n this.loadData();\n } catch {}\n },\n });\n }\n\n onPermanentDelete(file: IFileManager): void {\n this.confirmationService.confirm({\n message: this.translateService.translate(\n 'storage.delete.permanent.delete.confirm',\n { name: file.name },\n ),\n header: this.translateService.translate(\n 'storage.delete.permanent.delete',\n ),\n icon: 'exclamation-triangle',\n acceptLabel: this.translateService.translate(\n 'storage.delete.permanent.delete.button',\n ),\n rejectLabel: this.translateService.translate('shared.cancel'),\n acceptButtonStyleClass: 'p-button-danger',\n accept: async () => {\n try {\n const response = await this.fileService.delete({\n id: file.id,\n type: 'permanent',\n });\n this.showSuccess(\n response?.messageKey\n ? this.translateService.translate(\n response.messageKey,\n response.messageVariables as Record<string, string | number>,\n )\n : (response?.message ?? ''),\n );\n this.loadData();\n } catch {}\n },\n });\n }\n}\n"],"names":[],"mappings":"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"}