@flusys/ng-storage 0.1.0-beta.3 → 1.0.0-rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +209 -5
- package/fesm2022/flusys-ng-storage-file-manager-form.component-CMS_ddbs.mjs +485 -0
- package/fesm2022/flusys-ng-storage-file-manager-form.component-CMS_ddbs.mjs.map +1 -0
- package/fesm2022/flusys-ng-storage-file-manager-list.component-DDOFAPRD.mjs +305 -0
- package/fesm2022/flusys-ng-storage-file-manager-list.component-DDOFAPRD.mjs.map +1 -0
- package/fesm2022/flusys-ng-storage-folder-form.component-ClYATZkh.mjs +157 -0
- package/fesm2022/flusys-ng-storage-folder-form.component-ClYATZkh.mjs.map +1 -0
- package/fesm2022/flusys-ng-storage-folder-list.component-CzONANHt.mjs +200 -0
- package/fesm2022/flusys-ng-storage-folder-list.component-CzONANHt.mjs.map +1 -0
- package/fesm2022/{flusys-ng-storage-storage-config-form.component-DHzsQ2Mc.mjs → flusys-ng-storage-storage-config-form.component-CODLLCtg.mjs} +211 -238
- package/fesm2022/flusys-ng-storage-storage-config-form.component-CODLLCtg.mjs.map +1 -0
- package/fesm2022/flusys-ng-storage-storage-config-list.component-BbBx0iSL.mjs +213 -0
- package/fesm2022/flusys-ng-storage-storage-config-list.component-BbBx0iSL.mjs.map +1 -0
- package/fesm2022/flusys-ng-storage.mjs +391 -103
- package/fesm2022/flusys-ng-storage.mjs.map +1 -1
- package/package.json +5 -5
- package/types/flusys-ng-storage.d.ts +187 -8
- package/fesm2022/flusys-ng-storage-file-manager-form.component-BI0hgXeI.mjs +0 -716
- package/fesm2022/flusys-ng-storage-file-manager-form.component-BI0hgXeI.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-file-manager-list.component-5gqfPzR3.mjs +0 -475
- package/fesm2022/flusys-ng-storage-file-manager-list.component-5gqfPzR3.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-folder-form.component-Cw2aLZkb.mjs +0 -253
- package/fesm2022/flusys-ng-storage-folder-form.component-Cw2aLZkb.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-folder-list.component-CN_mTtS5.mjs +0 -267
- package/fesm2022/flusys-ng-storage-folder-list.component-CN_mTtS5.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-storage-config-form.component-DHzsQ2Mc.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-storage-config-list.component-tmiE2CpM.mjs +0 -328
- package/fesm2022/flusys-ng-storage-storage-config-list.component-tmiE2CpM.mjs.map +0 -1
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, Injectable, Component } from '@angular/core';
|
|
2
|
+
import { inject, signal, computed, Directive, Injectable, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { Router, RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
|
|
4
|
+
import { APP_CONFIG, DEFAULT_APP_NAME, BaseApiService, getDefaultStorageConfigId } from '@flusys/ng-core';
|
|
5
|
+
import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
|
|
6
|
+
import { BaseListPage, ApiResourceService, PROFILE_UPLOAD_PROVIDER } from '@flusys/ng-shared';
|
|
7
|
+
import { MessageService } from 'primeng/api';
|
|
8
|
+
import { map } from 'rxjs/operators';
|
|
9
|
+
import { firstValueFrom, switchMap } from 'rxjs';
|
|
3
10
|
import { HttpClient } from '@angular/common/http';
|
|
4
|
-
import { ApiResourceService } from '@flusys/ng-shared';
|
|
5
|
-
import { BaseApiService } from '@flusys/ng-core';
|
|
6
11
|
import { CommonModule } from '@angular/common';
|
|
7
|
-
import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* File Location Enum
|
|
@@ -29,6 +33,166 @@ var ImageFormat;
|
|
|
29
33
|
ImageFormat["WEBP"] = "webp";
|
|
30
34
|
})(ImageFormat || (ImageFormat = {}));
|
|
31
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Provider configurations for all storage types
|
|
38
|
+
*/
|
|
39
|
+
const PROVIDER_CONFIGS = {
|
|
40
|
+
[FileLocationEnum.LOCAL]: {
|
|
41
|
+
label: 'Local',
|
|
42
|
+
icon: 'pi pi-folder',
|
|
43
|
+
severity: 'secondary',
|
|
44
|
+
},
|
|
45
|
+
[FileLocationEnum.AWS]: {
|
|
46
|
+
label: 'AWS S3',
|
|
47
|
+
icon: 'pi pi-cloud',
|
|
48
|
+
severity: 'warn',
|
|
49
|
+
},
|
|
50
|
+
[FileLocationEnum.AZURE]: {
|
|
51
|
+
label: 'Azure Blob',
|
|
52
|
+
icon: 'pi pi-cloud',
|
|
53
|
+
severity: 'info',
|
|
54
|
+
},
|
|
55
|
+
[FileLocationEnum.SFTP]: {
|
|
56
|
+
label: 'SFTP',
|
|
57
|
+
icon: 'pi pi-server',
|
|
58
|
+
severity: 'contrast',
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Get provider label for display
|
|
63
|
+
*/
|
|
64
|
+
function getProviderLabel(storage) {
|
|
65
|
+
const enumValue = storage;
|
|
66
|
+
return PROVIDER_CONFIGS[enumValue]?.label ?? storage;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get provider icon class
|
|
70
|
+
*/
|
|
71
|
+
function getProviderIcon(storage) {
|
|
72
|
+
const enumValue = storage;
|
|
73
|
+
return PROVIDER_CONFIGS[enumValue]?.icon ?? 'pi pi-database';
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get provider severity for p-tag
|
|
77
|
+
*/
|
|
78
|
+
function getProviderSeverity(storage) {
|
|
79
|
+
const enumValue = storage;
|
|
80
|
+
return PROVIDER_CONFIGS[enumValue]?.severity ?? 'secondary';
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get file icon based on content type
|
|
84
|
+
*/
|
|
85
|
+
function getFileIcon(contentType) {
|
|
86
|
+
if (contentType.startsWith('image/'))
|
|
87
|
+
return 'pi pi-image';
|
|
88
|
+
if (contentType.startsWith('video/'))
|
|
89
|
+
return 'pi pi-video';
|
|
90
|
+
if (contentType.startsWith('audio/'))
|
|
91
|
+
return 'pi pi-volume-up';
|
|
92
|
+
if (contentType.includes('pdf'))
|
|
93
|
+
return 'pi pi-file-pdf';
|
|
94
|
+
if (contentType.includes('word') || contentType.includes('document'))
|
|
95
|
+
return 'pi pi-file-word';
|
|
96
|
+
if (contentType.includes('excel') || contentType.includes('spreadsheet'))
|
|
97
|
+
return 'pi pi-file-excel';
|
|
98
|
+
return 'pi pi-file';
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Format file size from bytes to human readable string
|
|
102
|
+
*/
|
|
103
|
+
function formatFileSize(bytes) {
|
|
104
|
+
if (bytes <= 0)
|
|
105
|
+
return '0 Bytes';
|
|
106
|
+
const k = 1024;
|
|
107
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
108
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
|
|
109
|
+
return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Storage provider options for dropdown selects
|
|
113
|
+
*/
|
|
114
|
+
const STORAGE_PROVIDERS = [
|
|
115
|
+
{ label: 'AWS S3', value: FileLocationEnum.AWS },
|
|
116
|
+
{ label: 'Azure Blob Storage', value: FileLocationEnum.AZURE },
|
|
117
|
+
{ label: 'SFTP', value: FileLocationEnum.SFTP },
|
|
118
|
+
{ label: 'Local Storage', value: FileLocationEnum.LOCAL },
|
|
119
|
+
];
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Base Storage Page
|
|
123
|
+
*
|
|
124
|
+
* Provides common signals, computed values, and utilities for storage pages.
|
|
125
|
+
* Used by form components that need company context and message utilities.
|
|
126
|
+
*/
|
|
127
|
+
class BaseStoragePage {
|
|
128
|
+
router = inject(Router);
|
|
129
|
+
messageService = inject(MessageService);
|
|
130
|
+
appConfig = inject(APP_CONFIG);
|
|
131
|
+
companyContext = inject(LAYOUT_AUTH_STATE);
|
|
132
|
+
/** Loading state */
|
|
133
|
+
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
134
|
+
/** Show company info if company feature enabled */
|
|
135
|
+
showCompanyInfo = computed(() => this.appConfig.enableCompanyFeature, ...(ngDevMode ? [{ debugName: "showCompanyInfo" }] : []));
|
|
136
|
+
/** Current company name */
|
|
137
|
+
currentCompanyName = computed(() => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME, ...(ngDevMode ? [{ debugName: "currentCompanyName" }] : []));
|
|
138
|
+
/** Show success message */
|
|
139
|
+
showSuccess(detail, summary = 'Success') {
|
|
140
|
+
this.messageService.add({ severity: 'success', summary, detail });
|
|
141
|
+
}
|
|
142
|
+
/** Show error message */
|
|
143
|
+
showError(detail, summary = 'Error') {
|
|
144
|
+
this.messageService.add({ severity: 'error', summary, detail });
|
|
145
|
+
}
|
|
146
|
+
/** Navigate to a route */
|
|
147
|
+
navigateTo(path) {
|
|
148
|
+
this.router.navigate(path);
|
|
149
|
+
}
|
|
150
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: BaseStoragePage, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
151
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: BaseStoragePage, isStandalone: true, ngImport: i0 });
|
|
152
|
+
}
|
|
153
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: BaseStoragePage, decorators: [{
|
|
154
|
+
type: Directive
|
|
155
|
+
}] });
|
|
156
|
+
/**
|
|
157
|
+
* Base Storage List Page
|
|
158
|
+
*
|
|
159
|
+
* Extends the shared BaseListPage with storage-specific functionality:
|
|
160
|
+
* - Company context integration via LAYOUT_AUTH_STATE
|
|
161
|
+
* - Current company name computed signal
|
|
162
|
+
* - Storage-specific defaults (pageSize: 50)
|
|
163
|
+
*
|
|
164
|
+
* Usage:
|
|
165
|
+
* ```typescript
|
|
166
|
+
* @Component({ ... })
|
|
167
|
+
* export class FolderListComponent extends BaseStorageListPage<IFolder> {
|
|
168
|
+
* getResourceRoute(): string { return '/storage/folders'; }
|
|
169
|
+
* getDeleteConfirmMessage(folder: IFolder): string { return `Delete "${folder.name}"?`; }
|
|
170
|
+
* async loadData(): Promise<void> { ... }
|
|
171
|
+
* }
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
class BaseStorageListPage extends BaseListPage {
|
|
175
|
+
companyContext = inject(LAYOUT_AUTH_STATE);
|
|
176
|
+
/** Override default page size for storage pages */
|
|
177
|
+
pageSize = signal(50, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
|
|
178
|
+
/** Total records alias for backward compatibility */
|
|
179
|
+
totalRecords = this.total;
|
|
180
|
+
/** Current company name */
|
|
181
|
+
currentCompanyName = computed(() => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME, ...(ngDevMode ? [{ debugName: "currentCompanyName" }] : []));
|
|
182
|
+
/**
|
|
183
|
+
* Default implementation - subclasses should override if needed
|
|
184
|
+
*/
|
|
185
|
+
getDeleteConfirmMessage(item) {
|
|
186
|
+
const name = item.name ?? 'this item';
|
|
187
|
+
return `Are you sure you want to delete "${name}"?`;
|
|
188
|
+
}
|
|
189
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: BaseStorageListPage, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
190
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.3", type: BaseStorageListPage, isStandalone: true, usesInheritance: true, ngImport: i0 });
|
|
191
|
+
}
|
|
192
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: BaseStorageListPage, decorators: [{
|
|
193
|
+
type: Directive
|
|
194
|
+
}] });
|
|
195
|
+
|
|
32
196
|
/**
|
|
33
197
|
* File Manager API Service
|
|
34
198
|
* Handles file metadata CRUD operations
|
|
@@ -53,7 +217,7 @@ class FileManagerApiService extends ApiResourceService {
|
|
|
53
217
|
/**
|
|
54
218
|
* Get files by folder
|
|
55
219
|
* POST /storage/file-manager/get-all
|
|
56
|
-
* Filtered by folder ID and company (if enabled)
|
|
220
|
+
* Filtered by folder ID (UUID) and company (if enabled)
|
|
57
221
|
*/
|
|
58
222
|
getFilesByFolder(folderId, page = 1, limit = 50) {
|
|
59
223
|
return this.getAll('', {
|
|
@@ -76,54 +240,25 @@ class FileManagerApiService extends ApiResourceService {
|
|
|
76
240
|
sort: {},
|
|
77
241
|
});
|
|
78
242
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}]
|
|
87
|
-
}], ctorParameters: () => [] });
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Folder API Service
|
|
91
|
-
* Handles folder CRUD operations
|
|
92
|
-
* Endpoint: POST /storage/folder/*
|
|
93
|
-
*
|
|
94
|
-
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
95
|
-
*/
|
|
96
|
-
class FolderApiService extends ApiResourceService {
|
|
97
|
-
constructor() {
|
|
98
|
-
const http = inject(HttpClient);
|
|
99
|
-
super('storage/folder', http);
|
|
243
|
+
/**
|
|
244
|
+
* Create a new file record
|
|
245
|
+
* POST /storage/file-manager/insert
|
|
246
|
+
* Uses ICreateFileManagerDto which has different required fields than update
|
|
247
|
+
*/
|
|
248
|
+
createFile(dto) {
|
|
249
|
+
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
100
250
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
providedIn: 'root',
|
|
108
|
-
}]
|
|
109
|
-
}], ctorParameters: () => [] });
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Storage Config API Service
|
|
113
|
-
* Handles storage configuration CRUD operations
|
|
114
|
-
* Endpoint: POST /storage/storage-config/*
|
|
115
|
-
*
|
|
116
|
-
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
117
|
-
*/
|
|
118
|
-
class StorageConfigApiService extends ApiResourceService {
|
|
119
|
-
constructor() {
|
|
120
|
-
const http = inject(HttpClient);
|
|
121
|
-
super('storage/storage-config', http);
|
|
251
|
+
/**
|
|
252
|
+
* Create a new file record (async/await version)
|
|
253
|
+
* POST /storage/file-manager/insert
|
|
254
|
+
*/
|
|
255
|
+
async createFileAsync(dto) {
|
|
256
|
+
return firstValueFrom(this.createFile(dto));
|
|
122
257
|
}
|
|
123
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
124
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.
|
|
258
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileManagerApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
259
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileManagerApiService, providedIn: 'root' });
|
|
125
260
|
}
|
|
126
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
261
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileManagerApiService, decorators: [{
|
|
127
262
|
type: Injectable,
|
|
128
263
|
args: [{
|
|
129
264
|
providedIn: 'root',
|
|
@@ -140,11 +275,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
140
275
|
* - Image compression
|
|
141
276
|
* - Multiple storage providers
|
|
142
277
|
* - File validation (size, type)
|
|
278
|
+
* - Default storage config from environment (services.storage.defaultStorageConfigId)
|
|
143
279
|
*/
|
|
144
280
|
class UploadService extends BaseApiService {
|
|
281
|
+
fileManagerApi = inject(FileManagerApiService);
|
|
145
282
|
constructor() {
|
|
146
283
|
super('storage');
|
|
147
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Get default storage config ID from app config
|
|
287
|
+
* Used when no storageConfigId is provided in upload options
|
|
288
|
+
*/
|
|
289
|
+
getDefaultConfigId() {
|
|
290
|
+
return getDefaultStorageConfigId(this.appConfig);
|
|
291
|
+
}
|
|
148
292
|
/**
|
|
149
293
|
* Upload single file
|
|
150
294
|
* POST /storage/upload/single-file?storageConfigId=x&folderPath=y
|
|
@@ -179,24 +323,25 @@ class UploadService extends BaseApiService {
|
|
|
179
323
|
}
|
|
180
324
|
/**
|
|
181
325
|
* Build query string from upload options
|
|
326
|
+
* Uses default storageConfigId from app config if not provided in options
|
|
182
327
|
*/
|
|
183
328
|
buildQueryParams(options) {
|
|
184
|
-
if (!options)
|
|
185
|
-
return '';
|
|
186
329
|
const params = new URLSearchParams();
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (
|
|
330
|
+
// Use provided storageConfigId or fall back to default from config
|
|
331
|
+
const storageConfigId = options?.storageConfigId ?? this.getDefaultConfigId();
|
|
332
|
+
if (storageConfigId)
|
|
333
|
+
params.append('storageConfigId', storageConfigId);
|
|
334
|
+
if (options?.folderPath)
|
|
190
335
|
params.append('folderPath', options.folderPath);
|
|
191
|
-
if (options
|
|
336
|
+
if (options?.maxWidth)
|
|
192
337
|
params.append('maxWidth', options.maxWidth.toString());
|
|
193
|
-
if (options
|
|
338
|
+
if (options?.maxHeight)
|
|
194
339
|
params.append('maxHeight', options.maxHeight.toString());
|
|
195
|
-
if (options
|
|
340
|
+
if (options?.quality)
|
|
196
341
|
params.append('quality', options.quality.toString());
|
|
197
|
-
if (options
|
|
342
|
+
if (options?.format)
|
|
198
343
|
params.append('format', options.format);
|
|
199
|
-
if (options
|
|
344
|
+
if (options?.compress !== undefined)
|
|
200
345
|
params.append('compress', options.compress.toString());
|
|
201
346
|
return params.toString();
|
|
202
347
|
}
|
|
@@ -205,20 +350,22 @@ class UploadService extends BaseApiService {
|
|
|
205
350
|
* POST /storage/upload/delete-single-file
|
|
206
351
|
*
|
|
207
352
|
* @param key - File key/path to delete
|
|
208
|
-
* @param storageConfigId - Optional storage config ID (uses default if not provided)
|
|
353
|
+
* @param storageConfigId - Optional storage config ID (uses default from config if not provided)
|
|
209
354
|
*/
|
|
210
355
|
deleteSingleFile(key, storageConfigId) {
|
|
211
|
-
|
|
356
|
+
const configId = storageConfigId ?? this.getDefaultConfigId();
|
|
357
|
+
return this.http.post(this.getUrl('upload/delete-single-file'), { key, ...(configId && { storageConfigId: configId }) });
|
|
212
358
|
}
|
|
213
359
|
/**
|
|
214
360
|
* Delete multiple files
|
|
215
361
|
* POST /storage/upload/delete-multiple-file
|
|
216
362
|
*
|
|
217
363
|
* @param keys - Array of file keys/paths to delete
|
|
218
|
-
* @param storageConfigId - Optional storage config ID (uses default if not provided)
|
|
364
|
+
* @param storageConfigId - Optional storage config ID (uses default from config if not provided)
|
|
219
365
|
*/
|
|
220
366
|
deleteMultipleFiles(keys, storageConfigId) {
|
|
221
|
-
|
|
367
|
+
const configId = storageConfigId ?? this.getDefaultConfigId();
|
|
368
|
+
return this.http.post(this.getUrl('upload/delete-multiple-file'), { keys, ...(configId && { storageConfigId: configId }) });
|
|
222
369
|
}
|
|
223
370
|
/**
|
|
224
371
|
* Get file download URL
|
|
@@ -230,10 +377,153 @@ class UploadService extends BaseApiService {
|
|
|
230
377
|
getFileUrl(key) {
|
|
231
378
|
return this.getUrl(`upload/file/${key}`);
|
|
232
379
|
}
|
|
233
|
-
|
|
234
|
-
|
|
380
|
+
/**
|
|
381
|
+
* Upload file and register in file manager
|
|
382
|
+
* Returns file manager ID (UUID) for storing in references like profilePictureId
|
|
383
|
+
*
|
|
384
|
+
* @param file - File to upload
|
|
385
|
+
* @param options - Upload options (storage config, compression, etc.)
|
|
386
|
+
* @returns Observable with file manager record (id is the UUID to store)
|
|
387
|
+
*/
|
|
388
|
+
uploadAndRegister(file, options) {
|
|
389
|
+
return this.uploadSingleFile(file, options).pipe(switchMap((uploadResponse) => {
|
|
390
|
+
if (!uploadResponse.success || !uploadResponse.data) {
|
|
391
|
+
throw new Error(uploadResponse.message || 'Upload failed');
|
|
392
|
+
}
|
|
393
|
+
const uploadedFile = uploadResponse.data;
|
|
394
|
+
const storageConfigId = options?.storageConfigId ?? this.getDefaultConfigId();
|
|
395
|
+
// Create file manager record using proper DTO
|
|
396
|
+
return this.fileManagerApi.createFile({
|
|
397
|
+
name: uploadedFile.name,
|
|
398
|
+
key: uploadedFile.key,
|
|
399
|
+
size: String(uploadedFile.size),
|
|
400
|
+
contentType: uploadedFile.contentType,
|
|
401
|
+
isPrivate: options?.isPrivate ?? false,
|
|
402
|
+
folderId: options?.folderId,
|
|
403
|
+
storageConfigId,
|
|
404
|
+
});
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
407
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
408
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UploadService, providedIn: 'root' });
|
|
409
|
+
}
|
|
410
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UploadService, decorators: [{
|
|
411
|
+
type: Injectable,
|
|
412
|
+
args: [{
|
|
413
|
+
providedIn: 'root',
|
|
414
|
+
}]
|
|
415
|
+
}], ctorParameters: () => [] });
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Profile Upload Provider Adapter
|
|
419
|
+
*
|
|
420
|
+
* Implements IProfileUploadProvider interface for ng-auth profile page.
|
|
421
|
+
* Uses UploadService.uploadAndRegister() to upload files and register in file manager.
|
|
422
|
+
*
|
|
423
|
+
* @example
|
|
424
|
+
* // In app.config.ts
|
|
425
|
+
* providers: [
|
|
426
|
+
* ...provideStorageProviders(),
|
|
427
|
+
* ]
|
|
428
|
+
*/
|
|
429
|
+
class ProfileUploadProviderAdapter {
|
|
430
|
+
uploadService = inject(UploadService);
|
|
431
|
+
/**
|
|
432
|
+
* Upload profile picture and register in file manager
|
|
433
|
+
* Returns file manager ID (UUID) for storing in user.profilePictureId
|
|
434
|
+
*/
|
|
435
|
+
uploadProfilePicture(file, options) {
|
|
436
|
+
return this.uploadService
|
|
437
|
+
.uploadAndRegister(file, {
|
|
438
|
+
folderPath: options?.folderPath ?? 'profile-pictures',
|
|
439
|
+
compress: options?.compress ?? true,
|
|
440
|
+
maxWidth: options?.maxWidth ?? 400,
|
|
441
|
+
maxHeight: options?.maxHeight ?? 400,
|
|
442
|
+
})
|
|
443
|
+
.pipe(map((response) => ({
|
|
444
|
+
success: response.success,
|
|
445
|
+
message: response.message,
|
|
446
|
+
data: response.data
|
|
447
|
+
? {
|
|
448
|
+
id: response.data.id,
|
|
449
|
+
name: response.data.name,
|
|
450
|
+
key: response.data.key,
|
|
451
|
+
size: parseFloat(response.data.size) * 1024, // Convert KB to bytes
|
|
452
|
+
contentType: response.data.contentType,
|
|
453
|
+
}
|
|
454
|
+
: undefined,
|
|
455
|
+
})));
|
|
456
|
+
}
|
|
457
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ProfileUploadProviderAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
458
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ProfileUploadProviderAdapter });
|
|
459
|
+
}
|
|
460
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: ProfileUploadProviderAdapter, decorators: [{
|
|
461
|
+
type: Injectable
|
|
462
|
+
}] });
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Provide Storage Providers
|
|
466
|
+
*
|
|
467
|
+
* Registers storage-related provider implementations.
|
|
468
|
+
* Call this in app.config.ts to enable storage features in other packages.
|
|
469
|
+
*
|
|
470
|
+
* @example
|
|
471
|
+
* // In app.config.ts
|
|
472
|
+
* export const appConfig: ApplicationConfig = {
|
|
473
|
+
* providers: [
|
|
474
|
+
* ...provideStorageProviders(),
|
|
475
|
+
* ],
|
|
476
|
+
* };
|
|
477
|
+
*
|
|
478
|
+
* @returns Array of providers for storage functionality
|
|
479
|
+
*/
|
|
480
|
+
function provideStorageProviders() {
|
|
481
|
+
return [
|
|
482
|
+
{
|
|
483
|
+
provide: PROFILE_UPLOAD_PROVIDER,
|
|
484
|
+
useClass: ProfileUploadProviderAdapter,
|
|
485
|
+
},
|
|
486
|
+
];
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Folder API Service
|
|
491
|
+
* Handles folder CRUD operations
|
|
492
|
+
* Endpoint: POST /storage/folder/*
|
|
493
|
+
*
|
|
494
|
+
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
495
|
+
*/
|
|
496
|
+
class FolderApiService extends ApiResourceService {
|
|
497
|
+
constructor() {
|
|
498
|
+
const http = inject(HttpClient);
|
|
499
|
+
super('storage/folder', http);
|
|
500
|
+
}
|
|
501
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FolderApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
502
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FolderApiService, providedIn: 'root' });
|
|
503
|
+
}
|
|
504
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FolderApiService, decorators: [{
|
|
505
|
+
type: Injectable,
|
|
506
|
+
args: [{
|
|
507
|
+
providedIn: 'root',
|
|
508
|
+
}]
|
|
509
|
+
}], ctorParameters: () => [] });
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Storage Config API Service
|
|
513
|
+
* Handles storage configuration CRUD operations
|
|
514
|
+
* Endpoint: POST /storage/storage-config/*
|
|
515
|
+
*
|
|
516
|
+
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
517
|
+
*/
|
|
518
|
+
class StorageConfigApiService extends ApiResourceService {
|
|
519
|
+
constructor() {
|
|
520
|
+
const http = inject(HttpClient);
|
|
521
|
+
super('storage/storage-config', http);
|
|
522
|
+
}
|
|
523
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StorageConfigApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
524
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StorageConfigApiService, providedIn: 'root' });
|
|
235
525
|
}
|
|
236
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
526
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StorageConfigApiService, decorators: [{
|
|
237
527
|
type: Injectable,
|
|
238
528
|
args: [{
|
|
239
529
|
providedIn: 'root',
|
|
@@ -257,15 +547,15 @@ const STORAGE_ROUTES = [
|
|
|
257
547
|
children: [
|
|
258
548
|
{
|
|
259
549
|
path: '',
|
|
260
|
-
loadComponent: () => import('./flusys-ng-storage-file-manager-list.component-
|
|
550
|
+
loadComponent: () => import('./flusys-ng-storage-file-manager-list.component-DDOFAPRD.mjs').then((m) => m.FileManagerListComponent),
|
|
261
551
|
},
|
|
262
552
|
{
|
|
263
553
|
path: 'new',
|
|
264
|
-
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-
|
|
554
|
+
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-CMS_ddbs.mjs').then((m) => m.FileManagerFormComponent),
|
|
265
555
|
},
|
|
266
556
|
{
|
|
267
557
|
path: ':id',
|
|
268
|
-
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-
|
|
558
|
+
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-CMS_ddbs.mjs').then((m) => m.FileManagerFormComponent),
|
|
269
559
|
},
|
|
270
560
|
],
|
|
271
561
|
},
|
|
@@ -275,15 +565,15 @@ const STORAGE_ROUTES = [
|
|
|
275
565
|
children: [
|
|
276
566
|
{
|
|
277
567
|
path: '',
|
|
278
|
-
loadComponent: () => import('./flusys-ng-storage-folder-list.component-
|
|
568
|
+
loadComponent: () => import('./flusys-ng-storage-folder-list.component-CzONANHt.mjs').then((m) => m.FolderListComponent),
|
|
279
569
|
},
|
|
280
570
|
{
|
|
281
571
|
path: 'new',
|
|
282
|
-
loadComponent: () => import('./flusys-ng-storage-folder-form.component-
|
|
572
|
+
loadComponent: () => import('./flusys-ng-storage-folder-form.component-ClYATZkh.mjs').then((m) => m.FolderFormComponent),
|
|
283
573
|
},
|
|
284
574
|
{
|
|
285
575
|
path: ':id',
|
|
286
|
-
loadComponent: () => import('./flusys-ng-storage-folder-form.component-
|
|
576
|
+
loadComponent: () => import('./flusys-ng-storage-folder-form.component-ClYATZkh.mjs').then((m) => m.FolderFormComponent),
|
|
287
577
|
},
|
|
288
578
|
],
|
|
289
579
|
},
|
|
@@ -293,15 +583,15 @@ const STORAGE_ROUTES = [
|
|
|
293
583
|
children: [
|
|
294
584
|
{
|
|
295
585
|
path: '',
|
|
296
|
-
loadComponent: () => import('./flusys-ng-storage-storage-config-list.component-
|
|
586
|
+
loadComponent: () => import('./flusys-ng-storage-storage-config-list.component-BbBx0iSL.mjs').then((m) => m.StorageConfigListComponent),
|
|
297
587
|
},
|
|
298
588
|
{
|
|
299
589
|
path: 'new',
|
|
300
|
-
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-
|
|
590
|
+
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-CODLLCtg.mjs').then((m) => m.StorageConfigFormComponent),
|
|
301
591
|
},
|
|
302
592
|
{
|
|
303
593
|
path: ':id',
|
|
304
|
-
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-
|
|
594
|
+
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-CODLLCtg.mjs').then((m) => m.StorageConfigFormComponent),
|
|
305
595
|
},
|
|
306
596
|
],
|
|
307
597
|
},
|
|
@@ -343,58 +633,56 @@ class StorageContainerComponent {
|
|
|
343
633
|
route: 'configs',
|
|
344
634
|
},
|
|
345
635
|
];
|
|
346
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.
|
|
347
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.
|
|
348
|
-
<div class="
|
|
349
|
-
<div class="
|
|
350
|
-
<h1 class="text-2xl font-bold m-0">Storage</h1>
|
|
351
|
-
<p class="text-
|
|
636
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StorageContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
637
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: StorageContainerComponent, isStandalone: true, selector: "lib-storage-container", ngImport: i0, template: `
|
|
638
|
+
<div class="p-2 sm:p-4">
|
|
639
|
+
<div class="mb-4">
|
|
640
|
+
<h1 class="text-xl sm:text-2xl font-bold m-0">Storage</h1>
|
|
641
|
+
<p class="text-muted-color mt-1 text-sm sm:text-base">Manage files, folders, and storage configurations</p>
|
|
352
642
|
</div>
|
|
353
643
|
|
|
354
|
-
<div class="
|
|
644
|
+
<div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
|
|
355
645
|
@for (tab of tabs; track tab.id) {
|
|
356
646
|
<a
|
|
357
647
|
[routerLink]="tab.route"
|
|
358
|
-
routerLinkActive="active"
|
|
359
|
-
class="
|
|
648
|
+
routerLinkActive="tab-active"
|
|
649
|
+
class="flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors text-muted-color no-underline border-b-2 border-transparent -mb-px hover:bg-surface-hover [&.tab-active]:text-primary [&.tab-active]:border-primary [&.tab-active]:bg-surface-ground whitespace-nowrap shrink-0"
|
|
650
|
+
>
|
|
360
651
|
<i [class]="tab.icon"></i>
|
|
361
652
|
<span>{{ tab.label }}</span>
|
|
362
653
|
</a>
|
|
363
654
|
}
|
|
364
655
|
</div>
|
|
365
656
|
|
|
366
|
-
<
|
|
367
|
-
<router-outlet />
|
|
368
|
-
</div>
|
|
657
|
+
<router-outlet />
|
|
369
658
|
</div>
|
|
370
|
-
`, isInline: true, styles: [".
|
|
659
|
+
`, isInline: true, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
371
660
|
}
|
|
372
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.
|
|
661
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: StorageContainerComponent, decorators: [{
|
|
373
662
|
type: Component,
|
|
374
|
-
args: [{ selector: 'lib-storage-container', standalone: true, imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive], template: `
|
|
375
|
-
<div class="
|
|
376
|
-
<div class="
|
|
377
|
-
<h1 class="text-2xl font-bold m-0">Storage</h1>
|
|
378
|
-
<p class="text-
|
|
663
|
+
args: [{ selector: 'lib-storage-container', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive], template: `
|
|
664
|
+
<div class="p-2 sm:p-4">
|
|
665
|
+
<div class="mb-4">
|
|
666
|
+
<h1 class="text-xl sm:text-2xl font-bold m-0">Storage</h1>
|
|
667
|
+
<p class="text-muted-color mt-1 text-sm sm:text-base">Manage files, folders, and storage configurations</p>
|
|
379
668
|
</div>
|
|
380
669
|
|
|
381
|
-
<div class="
|
|
670
|
+
<div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
|
|
382
671
|
@for (tab of tabs; track tab.id) {
|
|
383
672
|
<a
|
|
384
673
|
[routerLink]="tab.route"
|
|
385
|
-
routerLinkActive="active"
|
|
386
|
-
class="
|
|
674
|
+
routerLinkActive="tab-active"
|
|
675
|
+
class="flex items-center gap-2 px-4 py-2 rounded-t-lg cursor-pointer transition-colors text-muted-color no-underline border-b-2 border-transparent -mb-px hover:bg-surface-hover [&.tab-active]:text-primary [&.tab-active]:border-primary [&.tab-active]:bg-surface-ground whitespace-nowrap shrink-0"
|
|
676
|
+
>
|
|
387
677
|
<i [class]="tab.icon"></i>
|
|
388
678
|
<span>{{ tab.label }}</span>
|
|
389
679
|
</a>
|
|
390
680
|
}
|
|
391
681
|
</div>
|
|
392
682
|
|
|
393
|
-
<
|
|
394
|
-
<router-outlet />
|
|
395
|
-
</div>
|
|
683
|
+
<router-outlet />
|
|
396
684
|
</div>
|
|
397
|
-
`, styles: [".
|
|
685
|
+
`, styles: [".scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none}.scrollbar-hide::-webkit-scrollbar{display:none}\n"] }]
|
|
398
686
|
}] });
|
|
399
687
|
|
|
400
688
|
var storageContainer_component = /*#__PURE__*/Object.freeze({
|
|
@@ -411,5 +699,5 @@ var storageContainer_component = /*#__PURE__*/Object.freeze({
|
|
|
411
699
|
* Generated bundle index. Do not edit.
|
|
412
700
|
*/
|
|
413
701
|
|
|
414
|
-
export { FileLocationEnum, FileManagerApiService, FolderApiService, ImageFormat, STORAGE_ROUTES, StorageConfigApiService, StorageContainerComponent, UploadService };
|
|
702
|
+
export { BaseStorageListPage, BaseStoragePage, FileLocationEnum, FileManagerApiService, FolderApiService, ImageFormat, ProfileUploadProviderAdapter, STORAGE_PROVIDERS, STORAGE_ROUTES, StorageConfigApiService, StorageContainerComponent, UploadService, formatFileSize, getFileIcon, getProviderIcon, getProviderLabel, getProviderSeverity, provideStorageProviders };
|
|
415
703
|
//# sourceMappingURL=flusys-ng-storage.mjs.map
|