@flusys/ng-storage 4.1.0 → 5.0.0

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 (24) hide show
  1. package/README.md +17 -382
  2. package/fesm2022/{flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs → flusys-ng-storage-file-manager-form.component-BLJDAvBX.mjs} +287 -74
  3. package/fesm2022/flusys-ng-storage-file-manager-form.component-BLJDAvBX.mjs.map +1 -0
  4. package/fesm2022/{flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs → flusys-ng-storage-file-manager-list.component-Dn5hVksO.mjs} +210 -70
  5. package/fesm2022/flusys-ng-storage-file-manager-list.component-Dn5hVksO.mjs.map +1 -0
  6. package/fesm2022/{flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs → flusys-ng-storage-folder-form.component-B8vRSb1T.mjs} +88 -31
  7. package/fesm2022/flusys-ng-storage-folder-form.component-B8vRSb1T.mjs.map +1 -0
  8. package/fesm2022/{flusys-ng-storage-folder-list.component-B2Q41I1g.mjs → flusys-ng-storage-folder-list.component-B4yCKvAV.mjs} +96 -30
  9. package/fesm2022/flusys-ng-storage-folder-list.component-B4yCKvAV.mjs.map +1 -0
  10. package/fesm2022/flusys-ng-storage-storage-config-form.component-CMeTif8p.mjs +880 -0
  11. package/fesm2022/flusys-ng-storage-storage-config-form.component-CMeTif8p.mjs.map +1 -0
  12. package/fesm2022/{flusys-ng-storage-storage-config-list.component-DBH_qf9o.mjs → flusys-ng-storage-storage-config-list.component-C7OYYyrQ.mjs} +126 -33
  13. package/fesm2022/flusys-ng-storage-storage-config-list.component-C7OYYyrQ.mjs.map +1 -0
  14. package/fesm2022/flusys-ng-storage.mjs +143 -256
  15. package/fesm2022/flusys-ng-storage.mjs.map +1 -1
  16. package/package.json +4 -4
  17. package/types/flusys-ng-storage.d.ts +4 -2
  18. package/fesm2022/flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs.map +0 -1
  19. package/fesm2022/flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs.map +0 -1
  20. package/fesm2022/flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs.map +0 -1
  21. package/fesm2022/flusys-ng-storage-folder-list.component-B2Q41I1g.mjs.map +0 -1
  22. package/fesm2022/flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs +0 -465
  23. package/fesm2022/flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs.map +0 -1
  24. package/fesm2022/flusys-ng-storage-storage-config-list.component-DBH_qf9o.mjs.map +0 -1
package/README.md CHANGED
@@ -1,69 +1,9 @@
1
1
  # @flusys/ng-storage
2
2
 
3
- > File storage UI library for the FLUSYS Angular platform — file upload, folder management, file browser, presigned URL fetching, and provider adapter registration.
3
+ File storage UI for FLUSYS Angular apps — upload, file manager pages, presigned URL fetching, and provider adapter registration for Local, S3, Azure, and SFTP backends.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@flusys/ng-storage.svg)](https://www.npmjs.com/package/@flusys/ng-storage)
6
- [![Angular](https://img.shields.io/badge/Angular-21-red.svg)](https://angular.io)
7
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org)
8
- [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
9
-
10
- ---
11
-
12
- ## Table of Contents
13
-
14
- - [Overview](#overview)
15
- - [Features](#features)
16
- - [Compatibility](#compatibility)
17
- - [Installation](#installation)
18
- - [Quick Start](#quick-start)
19
- - [Module Registration](#module-registration)
20
- - [File URL Rule](#file-url-rule)
21
- - [Services](#services)
22
- - [FileManagerApiService](#filemanagerapiservice)
23
- - [FolderApiService](#folderapiservice)
24
- - [UploadService](#uploadservice)
25
- - [Components](#components)
26
- - [FileManagerComponent](#filemanagercomponent)
27
- - [FileSelectorDialogComponent](#fileselectordialogcomponent)
28
- - [FileUploaderComponent](#fileuploadercomponent)
29
- - [Storage Routes](#storage-routes)
30
- - [File Location Enum](#file-location-enum)
31
- - [API Endpoints](#api-endpoints)
32
- - [Configuration Reference](#configuration-reference)
33
- - [Troubleshooting](#troubleshooting)
34
- - [License](#license)
35
-
36
- ---
37
-
38
- ## Overview
39
-
40
- `@flusys/ng-storage` provides the complete file management UI for FLUSYS applications. It supports all four storage backends (Local, S3, Azure Blob, SFTP) transparently — the backend generates the correct presigned URLs for each provider.
41
-
42
- **Critical rule:** Never construct file URLs manually. Always use `FileUrlService` (from `ng-shared`) or the `FILE_PROVIDER` token. The backend generates presigned URLs that are provider-agnostic and access-controlled.
43
-
44
- ---
45
-
46
- ## Features
47
-
48
- - ✅ File browser with folder navigation
49
- - ✅ Drag-and-drop upload with progress
50
- - ✅ Multi-file selection dialog (`FileSelectorDialogComponent`)
51
- - ✅ Image preview thumbnails
52
- - ✅ Download and delete actions
53
- - ✅ `UploadService` — typed multi-part file upload
54
- - ✅ `provideStorageProviders()` — registers `FILE_PROVIDER` for shared components
55
- - ✅ Presigned URL fetching via `FileUrlService`
56
- - ✅ Support for `LOCAL`, `S3`, `AZURE`, `SFTP` backends
57
-
58
- ---
59
-
60
- ## Compatibility
61
-
62
- | Package | Version |
63
- |---------|---------|
64
- | Angular | 21+ |
65
- | @flusys/ng-core | 4.x |
66
- | @flusys/ng-shared | 4.x |
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
67
7
 
68
8
  ---
69
9
 
@@ -73,22 +13,7 @@
73
13
  npm install @flusys/ng-storage @flusys/ng-core @flusys/ng-shared
74
14
  ```
75
15
 
76
- ---
77
-
78
- ## Quick Start
79
-
80
- ### 1. Enable Storage in Config
81
-
82
- ```typescript
83
- // environments/environment.ts
84
- export const environment = {
85
- services: {
86
- storage: { enabled: true },
87
- },
88
- };
89
- ```
90
-
91
- ### 2. Register Storage Providers
16
+ ## 1. Register Providers
92
17
 
93
18
  ```typescript
94
19
  // app.config.ts
@@ -96,13 +21,14 @@ import { provideStorageProviders } from '@flusys/ng-storage';
96
21
 
97
22
  export const appConfig: ApplicationConfig = {
98
23
  providers: [
99
- ...provideStorageProviders(),
100
- // Provides: FILE_PROVIDER (IFileProvider) — used by FileSelectorDialogComponent, FileUrlService
24
+ ...provideStorageProviders(), // registers FILE_PROVIDER for ng-shared's file picker and FileUrlService
101
25
  ],
102
26
  };
103
27
  ```
104
28
 
105
- ### 3. Add Storage Routes (Optional)
29
+ `FILE_PROVIDER` is consumed by `FileSelectorComponent` and `FileUrlService` in `ng-shared`. Without this, file pickers in other packages (e.g., ng-form-builder, ng-email) will not work.
30
+
31
+ ## 2. Add Storage Routes (Optional)
106
32
 
107
33
  ```typescript
108
34
  // app.routes.ts
@@ -116,319 +42,28 @@ export const routes: Routes = [
116
42
  ];
117
43
  ```
118
44
 
119
- ---
120
-
121
- ## Module Registration
45
+ Routes included (all protected by `permissionGuard`):
122
46
 
123
- ### `provideStorageProviders()`
47
+ ## 4. Fetch File URLs (Critical Rule)
124
48
 
125
- Registers the storage adapter against the `FILE_PROVIDER` token from `ng-shared`:
49
+ Never construct file URLs manually. Always use `FileUrlService` from `ng-shared` — the backend generates presigned, access-controlled URLs for all storage providers.
126
50
 
127
51
  ```typescript
128
- import { provideStorageProviders } from '@flusys/ng-storage';
129
-
130
- providers: [
131
- ...provideStorageProviders(),
132
- ]
133
- ```
134
-
135
- This enables:
136
- - `FileSelectorDialogComponent` (from `ng-shared`) to list/browse files
137
- - `FileUrlService.fetchSingleFileUrl()` to work correctly
138
- - `HasPermissionDirective` to show storage-gated content
139
-
140
- ---
141
-
142
- ## File URL Rule
143
-
144
- **CRITICAL:** Never construct file URLs manually. The backend handles URL generation for all storage providers (Local, S3, Azure, SFTP) including presigned URL rotation.
145
-
146
- ```typescript
147
- // ❌ WRONG — breaks with S3, Azure, SFTP
148
- const url = `${apiBaseUrl}/uploads/${fileId}`;
149
- const url = `https://my-bucket.s3.amazonaws.com/${path}`;
150
-
151
- // ✅ CORRECT — always use FileUrlService
152
52
  import { FileUrlService } from '@flusys/ng-shared';
153
53
 
154
- const file = await this.fileUrlService.fetchSingleFileUrl(fileId);
155
- const url = file?.url ?? null; // Presigned, access-controlled, provider-agnostic
156
- ```
157
-
158
- **Why backend URLs:**
159
- - S3/Azure require presigned URLs that expire
160
- - URLs are access-controlled (user must have permission)
161
- - Works transparently across all 4 storage providers
162
- - Automatic URL refresh on expiry
163
-
164
- ---
165
-
166
- ## Services
167
-
168
- ### FileManagerApiService
169
-
170
- Typed API client for file management operations:
171
-
172
- ```typescript
173
- import { FileManagerApiService } from '@flusys/ng-storage';
174
-
175
- @Injectable({ ... })
176
- export class MyService {
177
- private fileApi = inject(FileManagerApiService);
178
-
179
- getFiles(folderId?: string): Observable<IListResponse<IFile>> {
180
- return this.fileApi.getAll({ filters: { folderId } });
181
- }
182
-
183
- getFileUrls(fileIds: string[]): Observable<ISingleResponse<IFileWithUrl[]>> {
184
- return this.fileApi.getFiles(fileIds);
185
- }
186
-
187
- deleteFile(id: string): Observable<IMessageResponse> {
188
- return this.fileApi.delete(id);
189
- }
190
- }
191
- ```
192
-
193
- **FileManagerApiService Methods:**
194
-
195
- | Method | Endpoint | Description |
196
- |--------|----------|-------------|
197
- | `getAll(params)` | `POST /file-manager/get-all` | List files with pagination |
198
- | `getById(id)` | `POST /file-manager/get/:id` | Get file metadata |
199
- | `getFiles(ids[])` | `POST /file-manager/get-files` | Batch fetch with presigned URLs |
200
- | `delete(id)` | `POST /file-manager/delete` | Delete file |
201
- | `bulkDelete(ids[])` | `POST /file-manager/bulk-delete` | Delete multiple files |
202
- | `move(id, folderId)` | `POST /file-manager/move` | Move file to folder |
203
-
204
- ### FolderApiService
205
-
206
- Typed API client for folder management:
207
-
208
- ```typescript
209
- import { FolderApiService } from '@flusys/ng-storage';
210
-
211
- @Injectable({ ... })
212
- export class MyService {
213
- private folderApi = inject(FolderApiService);
214
-
215
- getFolders(parentId?: string): Observable<IListResponse<IFolder>> {
216
- return this.folderApi.getAll({ filters: { parentId } });
217
- }
218
-
219
- createFolder(name: string, parentId?: string): Observable<ISingleResponse<IFolder>> {
220
- return this.folderApi.insert({ name, parentId });
221
- }
222
- }
223
- ```
224
-
225
- **FolderApiService Methods:**
226
-
227
- | Method | Endpoint | Description |
228
- |--------|----------|-------------|
229
- | `getAll(params)` | `POST /folder/get-all` | List folders |
230
- | `getById(id)` | `POST /folder/get/:id` | Get folder |
231
- | `insert(dto)` | `POST /folder/insert` | Create folder |
232
- | `update(dto)` | `POST /folder/update` | Rename folder |
233
- | `delete(id)` | `POST /folder/delete` | Delete folder |
234
-
235
- ### UploadService
236
-
237
- Handles multi-part file uploads with progress tracking:
238
-
239
- ```typescript
240
- import { UploadService } from '@flusys/ng-storage';
241
-
242
54
  @Component({ ... })
243
- export class UploadComponent {
244
- private uploadService = inject(UploadService);
55
+ export class MyComponent {
56
+ private readonly fileUrlService = inject(FileUrlService);
245
57
 
246
- uploadFile(file: File, folderId?: string): void {
247
- this.uploadService.upload(file, { folderId }).subscribe({
248
- next: (event) => {
249
- if (event.type === 'progress') {
250
- console.log(`Progress: ${event.percent}%`);
251
- }
252
- if (event.type === 'complete') {
253
- console.log('Uploaded:', event.file);
254
- }
255
- },
256
- error: (err) => console.error('Upload failed:', err),
257
- });
58
+ async loadAvatar(fileId: string) {
59
+ // POST /file-manager/get-files → returns presigned URL
60
+ const files = await firstValueFrom(this.fileUrlService.getFileUrls([fileId]));
61
+ const url = files?.data?.[0]?.url ?? null;
258
62
  }
259
-
260
- uploadMultiple(files: File[]): void {
261
- this.uploadService.uploadBatch(files).subscribe(results => {
262
- console.log(`Uploaded ${results.length} files`);
263
- });
264
- }
265
- }
266
- ```
267
-
268
- **UploadService API:**
269
-
270
- | Method | Description |
271
- |--------|-------------|
272
- | `upload(file, options?)` | Single file upload with progress events |
273
- | `uploadBatch(files, options?)` | Multiple file upload (sequential) |
274
- | `cancel(uploadId)` | Cancel in-progress upload |
275
-
276
- ---
277
-
278
- ## Components
279
-
280
- ### FileManagerComponent
281
-
282
- Full-page file browser with folder tree, grid/list view, upload, and actions.
283
-
284
- ```html
285
- <!-- Full file manager -->
286
- <flusys-file-manager />
287
-
288
- <!-- With pre-selected folder -->
289
- <flusys-file-manager [initialFolderId]="rootFolderId" />
290
- ```
291
-
292
- Features:
293
- - Folder tree (left panel)
294
- - File grid with thumbnails (right panel)
295
- - Drag-and-drop upload zone
296
- - Right-click context menu (rename, move, delete)
297
- - Breadcrumb navigation
298
- - Search files
299
-
300
- ### FileSelectorDialogComponent
301
-
302
- Dialog for selecting one or multiple files. Used by other packages (`ng-form-builder`, `ng-email`) to pick files.
303
-
304
- ```html
305
- <flusys-file-selector-dialog
306
- [visible]="showPicker"
307
- [multiple]="true"
308
- [accept]="'image/*'"
309
- (fileSelected)="onFilesSelected($event)"
310
- (cancel)="showPicker = false"
311
- />
312
- ```
313
-
314
- | Input | Type | Description |
315
- |-------|------|-------------|
316
- | `visible` | `boolean` | Show/hide dialog |
317
- | `multiple` | `boolean` | Allow multi-select (default: false) |
318
- | `accept` | `string` | MIME type filter |
319
- | `folderId` | `string` | Pre-open specific folder |
320
-
321
- | Output | Type | Description |
322
- |--------|------|-------------|
323
- | `fileSelected` | `IFile \| IFile[]` | Selected file(s) |
324
- | `cancel` | `void` | Dialog dismissed |
325
-
326
- ### FileUploaderComponent
327
-
328
- Lightweight standalone upload component (without the full browser):
329
-
330
- ```html
331
- <flusys-file-uploader
332
- [multiple]="false"
333
- [accept]="'image/jpeg,image/png'"
334
- [maxSizeMb]="5"
335
- [folderId]="profilePicturesFolderId"
336
- (uploaded)="onAvatarUploaded($event)"
337
- />
338
- ```
339
-
340
- ---
341
-
342
- ## Storage Routes
343
-
344
- Lazy-loaded pages for the full file manager:
345
-
346
- ```typescript
347
- import { STORAGE_ROUTES } from '@flusys/ng-storage';
348
-
349
- { path: 'storage', loadChildren: () => STORAGE_ROUTES }
350
- ```
351
-
352
- | Route | Component | Description |
353
- |-------|-----------|-------------|
354
- | `/storage` | `FileManagerPageComponent` | Full file manager page |
355
- | `/storage/folder/:id` | `FileManagerPageComponent` | Open specific folder |
356
-
357
- ---
358
-
359
- ## File Location Enum
360
-
361
- ```typescript
362
- import { FileLocationEnum } from '@flusys/ng-storage';
363
-
364
- enum FileLocationEnum {
365
- LOCAL = 'LOCAL',
366
- S3 = 'S3',
367
- AZURE = 'AZURE',
368
- SFTP = 'SFTP',
369
63
  }
370
64
  ```
371
65
 
372
- Use `FileLocationEnum` when filtering or categorizing files by their storage backend.
373
-
374
- ---
375
-
376
- ## API Endpoints
377
-
378
- | Method | Endpoint | Description |
379
- |--------|----------|-------------|
380
- | POST | `/file-manager/get-all` | List files with pagination |
381
- | POST | `/file-manager/get/:id` | Get file metadata |
382
- | POST | `/file-manager/get-files` | Batch fetch with presigned URLs |
383
- | POST | `/file-manager/upload` | Upload file (multipart) |
384
- | POST | `/file-manager/delete` | Delete file |
385
- | POST | `/file-manager/bulk-delete` | Delete multiple files |
386
- | POST | `/file-manager/move` | Move file to folder |
387
- | POST | `/folder/get-all` | List folders |
388
- | POST | `/folder/get/:id` | Get folder metadata |
389
- | POST | `/folder/insert` | Create folder |
390
- | POST | `/folder/update` | Rename folder |
391
- | POST | `/folder/delete` | Delete folder |
392
-
393
- ---
394
-
395
- ## Configuration Reference
396
-
397
- | Config Key | Type | Default | Description |
398
- |------------|------|---------|-------------|
399
- | `services.storage.enabled` | `boolean` | `false` | Enable storage module |
400
-
401
- The storage backend (LOCAL/S3/AZURE/SFTP) is configured server-side in `nestjs-storage`. The Angular client doesn't need to know which provider is active.
402
-
403
- ---
404
-
405
- ## Troubleshooting
406
-
407
- **File thumbnails don't load**
408
-
409
- Images are loaded via presigned URLs. Ensure `FileUrlService.fetchSingleFileUrl()` is used (not manual URL construction). Check the browser network tab — are the URLs returning 403?
410
-
411
- **Upload fails with 413 Payload Too Large**
412
-
413
- The backend has a file size limit. Configure `maxBodySize` in `nestjs-storage` on the server. On the Angular side, validate client-side before upload:
414
-
415
- ```html
416
- <flusys-file-uploader [maxSizeMb]="10" />
417
- ```
418
-
419
- **`No provider for FILE_PROVIDER`**
420
-
421
- Add `provideStorageProviders()` to `app.config.ts` providers.
422
-
423
- **FileSelectorDialog is empty (no files)**
424
-
425
- Ensure the user has permission to list files (`file:read`) and the backend storage is configured. Check the network tab for errors on `POST /file-manager/get-all`.
426
-
427
- **Files visible but download fails**
428
-
429
- The presigned URL may have expired. Call `FileUrlService.clearCache(fileId)` to force a fresh URL fetch.
430
-
431
- ---
66
+ Manual URL construction breaks with S3/Azure (presigned URLs expire) and does not enforce access control.
432
67
 
433
68
  ## License
434
69