@flusys/ng-storage 3.0.0 → 4.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 +13 -7
- package/fesm2022/{flusys-ng-storage-file-manager-form.component-CXVB9G-f.mjs → flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs} +67 -74
- package/fesm2022/flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs.map +1 -0
- package/fesm2022/{flusys-ng-storage-file-manager-list.component-0O_b4EjN.mjs → flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs} +66 -74
- package/fesm2022/flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs.map +1 -0
- package/fesm2022/{flusys-ng-storage-folder-form.component-BTQGEqNu.mjs → flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs} +25 -34
- package/fesm2022/flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs.map +1 -0
- package/fesm2022/{flusys-ng-storage-folder-list.component-B8GoIh6Z.mjs → flusys-ng-storage-folder-list.component-B2Q41I1g.mjs} +34 -39
- package/fesm2022/flusys-ng-storage-folder-list.component-B2Q41I1g.mjs.map +1 -0
- package/fesm2022/{flusys-ng-storage-storage-config-form.component-CorNWrmF.mjs → flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs} +87 -85
- package/fesm2022/flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs.map +1 -0
- package/fesm2022/{flusys-ng-storage-storage-config-list.component-YXzz3Tvo.mjs → flusys-ng-storage-storage-config-list.component-DBH_qf9o.mjs} +36 -35
- package/fesm2022/flusys-ng-storage-storage-config-list.component-DBH_qf9o.mjs.map +1 -0
- package/fesm2022/flusys-ng-storage.mjs +490 -151
- package/fesm2022/flusys-ng-storage.mjs.map +1 -1
- package/package.json +4 -4
- package/types/flusys-ng-storage.d.ts +56 -36
- package/fesm2022/flusys-ng-storage-file-manager-form.component-CXVB9G-f.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-file-manager-list.component-0O_b4EjN.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-folder-form.component-BTQGEqNu.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-folder-list.component-B8GoIh6Z.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-storage-config-form.component-CorNWrmF.mjs.map +0 -1
- package/fesm2022/flusys-ng-storage-storage-config-list.component-YXzz3Tvo.mjs.map +0 -1
|
@@ -1,15 +1,281 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, signal, computed, Directive, Injectable,
|
|
2
|
+
import { inject, signal, computed, Directive, Injectable, Component } from '@angular/core';
|
|
3
3
|
import { Router, RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
|
|
4
|
-
import { APP_CONFIG, DEFAULT_APP_NAME, BaseApiService, getDefaultStorageConfigId } from '@flusys/ng-core';
|
|
4
|
+
import { APP_CONFIG, TRANSLATE_ADAPTER, DEFAULT_APP_NAME, BaseApiService, getDefaultStorageConfigId } from '@flusys/ng-core';
|
|
5
5
|
import { LAYOUT_AUTH_STATE } from '@flusys/ng-layout';
|
|
6
|
-
import { BaseListPage, ApiResourceService,
|
|
6
|
+
import { BaseListPage, ApiResourceService, FILE_PROVIDER, permissionGuard, FILE_PERMISSIONS, FOLDER_PERMISSIONS, STORAGE_CONFIG_PERMISSIONS, resolveTranslationModule, SHARED_MESSAGES, PermissionValidatorService, TranslatePipe } from '@flusys/ng-shared';
|
|
7
7
|
import { MessageService } from 'primeng/api';
|
|
8
|
-
import { map } from 'rxjs
|
|
9
|
-
import { firstValueFrom, switchMap } from 'rxjs';
|
|
8
|
+
import { switchMap, map } from 'rxjs';
|
|
10
9
|
import { HttpClient } from '@angular/common/http';
|
|
11
10
|
import { CommonModule } from '@angular/common';
|
|
12
11
|
|
|
12
|
+
const STORAGE_MESSAGES = {
|
|
13
|
+
// Container page
|
|
14
|
+
'storage.title': 'Storage',
|
|
15
|
+
'storage.subtitle': 'Manage files, folders, and storage configurations',
|
|
16
|
+
// Tabs
|
|
17
|
+
'storage.tabs.file.manager': 'File Manager',
|
|
18
|
+
'storage.tabs.folders': 'Folders',
|
|
19
|
+
'storage.tabs.configs': 'Configurations',
|
|
20
|
+
// Page titles
|
|
21
|
+
'storage.file.title': 'Files',
|
|
22
|
+
'storage.file.manager.title': 'File Manager',
|
|
23
|
+
'storage.file.manager.upload.file': 'Upload File',
|
|
24
|
+
'storage.file.manager.edit.file': 'Edit File',
|
|
25
|
+
'storage.folder.title': 'Folder Setup',
|
|
26
|
+
'storage.folder.new.folder': 'New Folder',
|
|
27
|
+
'storage.folder.edit.folder': 'Edit Folder',
|
|
28
|
+
'storage.config.title': 'Storage Configurations',
|
|
29
|
+
'storage.config.new.config': 'New Configuration',
|
|
30
|
+
'storage.config.edit.config': 'Edit Storage Configuration',
|
|
31
|
+
// Common labels
|
|
32
|
+
'storage.company': 'Company',
|
|
33
|
+
'storage.name': 'Name',
|
|
34
|
+
'storage.type': 'Type',
|
|
35
|
+
'storage.size': 'Size',
|
|
36
|
+
'storage.location': 'Location',
|
|
37
|
+
'storage.config': 'Config',
|
|
38
|
+
'storage.private': 'Private',
|
|
39
|
+
'storage.public': 'Public',
|
|
40
|
+
'storage.created': 'Created',
|
|
41
|
+
'storage.actions': 'Actions',
|
|
42
|
+
'storage.slug': 'Slug',
|
|
43
|
+
'storage.provider': 'Provider',
|
|
44
|
+
'storage.active': 'Active',
|
|
45
|
+
'storage.set.as.default': 'Set as Default',
|
|
46
|
+
// Table headers
|
|
47
|
+
'storage.table.name': 'Name',
|
|
48
|
+
'storage.table.type': 'Type',
|
|
49
|
+
'storage.table.size': 'Size',
|
|
50
|
+
'storage.table.location': 'Location',
|
|
51
|
+
'storage.table.config': 'Config',
|
|
52
|
+
'storage.table.private': 'Private',
|
|
53
|
+
'storage.table.created': 'Created',
|
|
54
|
+
'storage.table.actions': 'Actions',
|
|
55
|
+
'storage.table.slug': 'Slug',
|
|
56
|
+
'storage.table.provider': 'Provider',
|
|
57
|
+
// Buttons
|
|
58
|
+
'storage.button.upload.file': 'Upload File',
|
|
59
|
+
'storage.button.new.folder': 'New Folder',
|
|
60
|
+
'storage.button.new.configuration': 'New Configuration',
|
|
61
|
+
'storage.button.choose.file': 'Choose File',
|
|
62
|
+
'storage.button.cancel': 'Cancel',
|
|
63
|
+
'storage.button.create': 'Create',
|
|
64
|
+
'storage.button.update': 'Update',
|
|
65
|
+
'storage.button.upload': 'Upload',
|
|
66
|
+
// Tooltips
|
|
67
|
+
'storage.tooltip.view': 'View',
|
|
68
|
+
'storage.tooltip.edit': 'Edit',
|
|
69
|
+
'storage.tooltip.trash': 'Trash',
|
|
70
|
+
'storage.tooltip.delete': 'Delete',
|
|
71
|
+
// Empty states
|
|
72
|
+
'storage.empty.files': 'No files found',
|
|
73
|
+
'storage.empty.files.in.company': 'No files found in current company',
|
|
74
|
+
'storage.empty.folders': 'No folders found',
|
|
75
|
+
'storage.empty.folders.in.company': 'No folders found in current company',
|
|
76
|
+
'storage.empty.configs': 'No storage configurations found',
|
|
77
|
+
'storage.empty.configs.in.company': 'No storage configurations found in current company',
|
|
78
|
+
// File operations
|
|
79
|
+
'storage.upload.title': 'Upload File',
|
|
80
|
+
'storage.upload.success': 'File uploaded successfully',
|
|
81
|
+
'storage.upload.failed': 'Failed to upload file',
|
|
82
|
+
'storage.upload.progress': 'Uploading... {{percent}}%',
|
|
83
|
+
'storage.upload.drag.drop': 'Drag and drop file here or click to browse',
|
|
84
|
+
'storage.upload.select.file': 'Select File',
|
|
85
|
+
'storage.upload.select.files': 'Select Files',
|
|
86
|
+
'storage.upload.max.size': 'Maximum file size: {{size}}',
|
|
87
|
+
'storage.upload.please.select': 'Please select a file to upload',
|
|
88
|
+
'storage.download.success': 'File downloaded successfully',
|
|
89
|
+
'storage.download.failed': 'Failed to download file',
|
|
90
|
+
'storage.download.progress': 'Downloading...',
|
|
91
|
+
// Delete operations
|
|
92
|
+
'storage.delete.success': 'File deleted successfully',
|
|
93
|
+
'storage.delete.failed': 'Failed to delete file',
|
|
94
|
+
'storage.delete.confirm': 'Are you sure you want to delete this file?',
|
|
95
|
+
'storage.delete.this.item': 'this item',
|
|
96
|
+
'storage.delete.confirm.named': 'Are you sure you want to delete "{{name}}"?',
|
|
97
|
+
'storage.delete.move.to.trash': 'Move to Trash',
|
|
98
|
+
'storage.delete.move.to.trash.confirm': 'Move "{{name}}" to trash? You can recover it later.',
|
|
99
|
+
'storage.delete.permanent.delete': 'Permanent Delete',
|
|
100
|
+
'storage.delete.permanent.delete.confirm': 'Permanently delete "{{name}}"? This action CANNOT be undone and will delete the file from storage.',
|
|
101
|
+
'storage.delete.permanent.delete.button': 'Delete Permanently',
|
|
102
|
+
'storage.delete.trash.success': 'File moved to trash successfully',
|
|
103
|
+
'storage.delete.trash.failed': 'Failed to move file to trash',
|
|
104
|
+
'storage.delete.permanent.success': 'File permanently deleted',
|
|
105
|
+
'storage.delete.permanent.failed': 'Failed to permanently delete file',
|
|
106
|
+
// File info
|
|
107
|
+
'storage.file.name': 'File Name',
|
|
108
|
+
'storage.file.name.required': 'File Name *',
|
|
109
|
+
'storage.file.size': 'File Size',
|
|
110
|
+
'storage.file.type': 'File Type',
|
|
111
|
+
'storage.file.extension': 'Extension',
|
|
112
|
+
'storage.file.uploaded.at': 'Uploaded At',
|
|
113
|
+
'storage.file.uploaded.by': 'Uploaded By',
|
|
114
|
+
'storage.file.path': 'File Path',
|
|
115
|
+
'storage.file.url': 'File URL',
|
|
116
|
+
'storage.file.url.not.available': 'File URL is not available',
|
|
117
|
+
'storage.file.get.url.failed': 'Failed to get file URL',
|
|
118
|
+
'storage.file.private': 'Private File',
|
|
119
|
+
'storage.file.private.hint': 'Only users with permission can access',
|
|
120
|
+
'storage.file.public.hint': 'File is publicly accessible',
|
|
121
|
+
'storage.file.placeholder': 'Will be auto-filled from selected file',
|
|
122
|
+
'storage.file.placeholder.edit': 'Enter file name',
|
|
123
|
+
'storage.file.select.required': 'Select File *',
|
|
124
|
+
// Validation
|
|
125
|
+
'storage.error.file.too.big': 'File size exceeds the maximum limit of {{maxSize}}',
|
|
126
|
+
'storage.error.invalid.type': 'Invalid file type. Allowed types: {{types}}',
|
|
127
|
+
'storage.error.too.many.files': 'Maximum {{max}} files allowed',
|
|
128
|
+
'storage.error.no.file': 'Please select a file',
|
|
129
|
+
'storage.error.no.config': 'Please select a storage configuration',
|
|
130
|
+
'storage.error.load.failed': 'Failed to load files',
|
|
131
|
+
'storage.error.load.file.failed': 'Failed to load file',
|
|
132
|
+
// Storage config
|
|
133
|
+
'storage.config.config.name': 'Configuration Name',
|
|
134
|
+
'storage.config.config.name.required': 'Configuration Name *',
|
|
135
|
+
'storage.config.config.name.placeholder': 'e.g., Production AWS S3',
|
|
136
|
+
'storage.config.provider': 'Storage Provider',
|
|
137
|
+
'storage.config.provider.required': 'Storage Provider *',
|
|
138
|
+
'storage.config.bucket': 'Bucket Name',
|
|
139
|
+
'storage.config.bucket.required': 'Bucket Name *',
|
|
140
|
+
'storage.config.region': 'Region',
|
|
141
|
+
'storage.config.region.required': 'AWS Region *',
|
|
142
|
+
'storage.config.access.key': 'Access Key',
|
|
143
|
+
'storage.config.access.key.required': 'Access Key ID *',
|
|
144
|
+
'storage.config.secret.key': 'Secret Key',
|
|
145
|
+
'storage.config.secret.key.required': 'Secret Access Key *',
|
|
146
|
+
'storage.config.endpoint': 'Endpoint URL',
|
|
147
|
+
'storage.config.endpoint.optional': 'Custom Endpoint (Optional)',
|
|
148
|
+
'storage.config.endpoint.placeholder': 'https://s3.custom-endpoint.com',
|
|
149
|
+
'storage.config.public': 'Public Access',
|
|
150
|
+
'storage.config.no.configs': 'No storage configurations found. Please create one first.',
|
|
151
|
+
'storage.config.select.config': 'Select storage configuration...',
|
|
152
|
+
'storage.config.load.failed': 'Failed to load storage configurations',
|
|
153
|
+
'storage.config.load.config.failed': 'Failed to load storage configuration',
|
|
154
|
+
'storage.config.delete.title': 'Delete Configuration',
|
|
155
|
+
'storage.config.delete.success': 'Storage configuration deleted successfully',
|
|
156
|
+
'storage.config.delete.failed': 'Failed to delete storage configuration',
|
|
157
|
+
// AWS specific
|
|
158
|
+
'storage.aws.title': 'AWS S3 Configuration',
|
|
159
|
+
'storage.aws.region': 'AWS Region',
|
|
160
|
+
'storage.aws.region.placeholder': 'us-east-1',
|
|
161
|
+
'storage.aws.bucket': 'Bucket Name',
|
|
162
|
+
'storage.aws.bucket.placeholder': 'my-bucket',
|
|
163
|
+
'storage.aws.access.key.id': 'Access Key ID',
|
|
164
|
+
'storage.aws.secret.access.key': 'Secret Access Key',
|
|
165
|
+
// Azure specific
|
|
166
|
+
'storage.azure.title': 'Azure Blob Configuration',
|
|
167
|
+
'storage.azure.account.name': 'Account Name',
|
|
168
|
+
'storage.azure.account.name.required': 'Account Name *',
|
|
169
|
+
'storage.azure.account.key': 'Account Key',
|
|
170
|
+
'storage.azure.account.key.required': 'Account Key *',
|
|
171
|
+
'storage.azure.container.name': 'Container Name',
|
|
172
|
+
'storage.azure.container.name.required': 'Container Name *',
|
|
173
|
+
// SFTP specific
|
|
174
|
+
'storage.sftp.title': 'SFTP Configuration',
|
|
175
|
+
'storage.sftp.host': 'Host',
|
|
176
|
+
'storage.sftp.host.required': 'Host *',
|
|
177
|
+
'storage.sftp.host.placeholder': 'sftp.example.com',
|
|
178
|
+
'storage.sftp.port': 'Port',
|
|
179
|
+
'storage.sftp.port.required': 'Port *',
|
|
180
|
+
'storage.sftp.username': 'Username',
|
|
181
|
+
'storage.sftp.username.required': 'Username *',
|
|
182
|
+
'storage.sftp.password': 'Password',
|
|
183
|
+
'storage.sftp.password.required': 'Password *',
|
|
184
|
+
'storage.sftp.base.path': 'Base Path',
|
|
185
|
+
'storage.sftp.base.path.required': 'Base Path *',
|
|
186
|
+
'storage.sftp.base.path.placeholder': '/uploads',
|
|
187
|
+
// Local specific
|
|
188
|
+
'storage.local.title': 'Local Storage Configuration',
|
|
189
|
+
'storage.local.base.path': 'Base Path',
|
|
190
|
+
'storage.local.base.path.required': 'Base Path *',
|
|
191
|
+
'storage.local.base.path.placeholder': '/var/www/uploads',
|
|
192
|
+
// Folder operations
|
|
193
|
+
'storage.folder.create': 'Create Folder',
|
|
194
|
+
'storage.folder.name': 'Folder Name',
|
|
195
|
+
'storage.folder.name.required': 'Folder Name *',
|
|
196
|
+
'storage.folder.name.placeholder': 'Enter folder name',
|
|
197
|
+
'storage.folder.create.success': 'Folder created successfully',
|
|
198
|
+
'storage.folder.create.failed': 'Failed to create folder',
|
|
199
|
+
'storage.folder.update.success': 'Folder updated successfully',
|
|
200
|
+
'storage.folder.update.failed': 'Failed to update folder',
|
|
201
|
+
'storage.folder.delete': 'Delete Folder',
|
|
202
|
+
'storage.folder.delete.title': 'Delete Folder',
|
|
203
|
+
'storage.folder.delete.confirm': 'Are you sure you want to delete this folder and all its contents?',
|
|
204
|
+
'storage.folder.delete.success': 'Folder deleted successfully',
|
|
205
|
+
'storage.folder.delete.failed': 'Failed to delete folder',
|
|
206
|
+
'storage.folder.optional': 'Folder (Optional)',
|
|
207
|
+
'storage.folder.no.folder': 'No folder (root level)',
|
|
208
|
+
'storage.folder.no.folders.available': 'No folders available. File will be uploaded to root level.',
|
|
209
|
+
'storage.folder.no.folders.edit': 'No folders available.',
|
|
210
|
+
'storage.folder.load.failed': 'Failed to load folder',
|
|
211
|
+
// File entity CRUD (API keys)
|
|
212
|
+
'file.create.success': 'File created successfully',
|
|
213
|
+
'file.create.many.success': '{{count}} files created successfully',
|
|
214
|
+
'file.get.success': 'File retrieved successfully',
|
|
215
|
+
'file.get.all.success': 'Files retrieved successfully',
|
|
216
|
+
'file.update.success': 'File updated successfully',
|
|
217
|
+
'file.update.many.success': '{{count}} files updated successfully',
|
|
218
|
+
'file.delete.success': 'File deleted successfully',
|
|
219
|
+
'file.restore.success': 'File restored successfully',
|
|
220
|
+
'file.not.found': 'File not found: {{path}}',
|
|
221
|
+
'file.upload.success': 'File uploaded successfully',
|
|
222
|
+
'file.upload.many.success': 'Files uploaded successfully',
|
|
223
|
+
'file.download.success': 'File downloaded successfully',
|
|
224
|
+
'file.move.success': 'File moved successfully',
|
|
225
|
+
'file.copy.success': 'File copied successfully',
|
|
226
|
+
// Folder entity CRUD (API keys)
|
|
227
|
+
'folder.create.success': 'Folder created successfully',
|
|
228
|
+
'folder.create.many.success': '{{count}} folders created successfully',
|
|
229
|
+
'folder.get.success': 'Folder retrieved successfully',
|
|
230
|
+
'folder.get.all.success': 'Folders retrieved successfully',
|
|
231
|
+
'folder.update.success': 'Folder updated successfully',
|
|
232
|
+
'folder.update.many.success': '{{count}} folders updated successfully',
|
|
233
|
+
'folder.delete.success': 'Folder deleted successfully',
|
|
234
|
+
'folder.restore.success': 'Folder restored successfully',
|
|
235
|
+
'folder.not.found': 'Folder "{{folderId}}" not found or access denied',
|
|
236
|
+
'folder.tree.success': 'Folder tree retrieved successfully',
|
|
237
|
+
'folder.contents.success': 'Folder contents retrieved successfully',
|
|
238
|
+
// Storage config CRUD (API keys)
|
|
239
|
+
'storage.config.update.success': 'Storage configuration updated successfully',
|
|
240
|
+
'storage.config.create.success': 'Storage configuration created successfully',
|
|
241
|
+
'storage.config.update.failed': 'Failed to update storage configuration',
|
|
242
|
+
'storage.config.create.failed': 'Failed to create storage configuration',
|
|
243
|
+
'storage.config.create.many.success': '{{count}} storage configurations created successfully',
|
|
244
|
+
'storage.config.get.success': 'Storage configuration retrieved successfully',
|
|
245
|
+
'storage.config.get.all.success': 'Storage configurations retrieved successfully',
|
|
246
|
+
'storage.config.update.many.success': '{{count}} storage configurations updated successfully',
|
|
247
|
+
'storage.config.restore.success': 'Storage configuration restored successfully',
|
|
248
|
+
'storage.config.not.found': 'Storage configuration not found',
|
|
249
|
+
'storage.config.active.success': 'Active storage configuration retrieved successfully',
|
|
250
|
+
'storage.config.test.success': 'Storage configuration test successful',
|
|
251
|
+
'storage.config.test.failed': 'Storage configuration test failed',
|
|
252
|
+
// Upload messages (API keys)
|
|
253
|
+
'upload.success': 'File uploaded successfully',
|
|
254
|
+
'upload.many.success': 'Files uploaded successfully',
|
|
255
|
+
'upload.failed': 'Failed to upload file',
|
|
256
|
+
'upload.file.too.large': 'File size ({{fileSize}}MB) exceeds maximum {{maxSize}}MB',
|
|
257
|
+
'upload.invalid.type': 'File type "{{mimeType}}" not allowed. Allowed: {{allowedTypes}}',
|
|
258
|
+
'upload.chunk.success': 'Chunk uploaded successfully',
|
|
259
|
+
'upload.complete.success': 'Upload completed successfully',
|
|
260
|
+
'upload.no.files.provided': 'No files provided',
|
|
261
|
+
'upload.no.file.path': 'File path is required',
|
|
262
|
+
'upload.invalid.file.path': 'Invalid file path',
|
|
263
|
+
'upload.config.not.found': 'Upload configuration not found',
|
|
264
|
+
// Validation messages
|
|
265
|
+
'storage.validation.file.name.required': 'File name is required',
|
|
266
|
+
'storage.validation.folder.name.required': 'Folder name is required',
|
|
267
|
+
'storage.validation.config.name.required': 'Configuration name is required',
|
|
268
|
+
// Additional missing keys
|
|
269
|
+
'storage.unit.kb': 'KB',
|
|
270
|
+
'storage.unit.mb': 'MB',
|
|
271
|
+
'storage.unit.gb': 'GB',
|
|
272
|
+
'storage.sftp.port.placeholder': '22',
|
|
273
|
+
'storage.file.update.success': 'File updated successfully',
|
|
274
|
+
'storage.pagination.files.template': 'Showing {first} to {last} of {totalRecords} files',
|
|
275
|
+
'storage.pagination.folders.template': 'Showing {first} to {last} of {totalRecords} folders',
|
|
276
|
+
'storage.pagination.configs.template': 'Showing {first} to {last} of {totalRecords} configurations',
|
|
277
|
+
};
|
|
278
|
+
|
|
13
279
|
/**
|
|
14
280
|
* File Location Enum
|
|
15
281
|
* Storage provider types (matches backend FileLocationEnum)
|
|
@@ -33,37 +299,46 @@ var ImageFormat;
|
|
|
33
299
|
ImageFormat["WEBP"] = "webp";
|
|
34
300
|
})(ImageFormat || (ImageFormat = {}));
|
|
35
301
|
|
|
302
|
+
/**
|
|
303
|
+
* Provider label translation keys
|
|
304
|
+
*/
|
|
305
|
+
const PROVIDER_LABEL_KEYS = {
|
|
306
|
+
[FileLocationEnum.LOCAL]: 'storage.local.title',
|
|
307
|
+
[FileLocationEnum.AWS]: 'storage.aws.title',
|
|
308
|
+
[FileLocationEnum.AZURE]: 'storage.azure.title',
|
|
309
|
+
[FileLocationEnum.SFTP]: 'storage.sftp.title',
|
|
310
|
+
};
|
|
36
311
|
/**
|
|
37
312
|
* Provider configurations for all storage types
|
|
38
313
|
*/
|
|
39
314
|
const PROVIDER_CONFIGS = {
|
|
40
315
|
[FileLocationEnum.LOCAL]: {
|
|
41
|
-
|
|
316
|
+
labelKey: 'storage.local.title',
|
|
42
317
|
icon: 'pi pi-folder',
|
|
43
318
|
severity: 'secondary',
|
|
44
319
|
},
|
|
45
320
|
[FileLocationEnum.AWS]: {
|
|
46
|
-
|
|
321
|
+
labelKey: 'storage.aws.title',
|
|
47
322
|
icon: 'pi pi-cloud',
|
|
48
323
|
severity: 'warn',
|
|
49
324
|
},
|
|
50
325
|
[FileLocationEnum.AZURE]: {
|
|
51
|
-
|
|
326
|
+
labelKey: 'storage.azure.title',
|
|
52
327
|
icon: 'pi pi-cloud',
|
|
53
328
|
severity: 'info',
|
|
54
329
|
},
|
|
55
330
|
[FileLocationEnum.SFTP]: {
|
|
56
|
-
|
|
331
|
+
labelKey: 'storage.sftp.title',
|
|
57
332
|
icon: 'pi pi-server',
|
|
58
333
|
severity: 'contrast',
|
|
59
334
|
},
|
|
60
335
|
};
|
|
61
336
|
/**
|
|
62
|
-
* Get provider label
|
|
337
|
+
* Get provider label translation key
|
|
63
338
|
*/
|
|
64
|
-
function
|
|
339
|
+
function getProviderLabelKey(storage) {
|
|
65
340
|
const enumValue = storage;
|
|
66
|
-
return PROVIDER_CONFIGS[enumValue]?.
|
|
341
|
+
return PROVIDER_CONFIGS[enumValue]?.labelKey ?? storage;
|
|
67
342
|
}
|
|
68
343
|
/**
|
|
69
344
|
* Get provider icon class
|
|
@@ -97,25 +372,44 @@ function getFileIcon(contentType) {
|
|
|
97
372
|
return 'pi pi-file-excel';
|
|
98
373
|
return 'pi pi-file';
|
|
99
374
|
}
|
|
375
|
+
/** File size unit keys for translation */
|
|
376
|
+
const FILE_SIZE_UNIT_KEYS = ['storage.size.bytes', 'storage.size.kb', 'storage.size.mb', 'storage.size.gb'];
|
|
100
377
|
/**
|
|
101
|
-
* Format file size from bytes to human readable
|
|
378
|
+
* Format file size from bytes to human readable format
|
|
379
|
+
* Returns an object with value and unitKey for translation
|
|
102
380
|
*/
|
|
103
|
-
function
|
|
381
|
+
function formatFileSizeWithKey(bytes) {
|
|
104
382
|
if (bytes <= 0)
|
|
105
|
-
return '0
|
|
383
|
+
return { value: '0', unitKey: 'storage.size.bytes' };
|
|
106
384
|
const k = 1024;
|
|
107
|
-
const
|
|
108
|
-
const
|
|
109
|
-
return
|
|
385
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), FILE_SIZE_UNIT_KEYS.length - 1);
|
|
386
|
+
const value = (Math.round((bytes / Math.pow(k, i)) * 100) / 100).toString();
|
|
387
|
+
return { value, unitKey: FILE_SIZE_UNIT_KEYS[i] };
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Format file size from bytes to human readable string
|
|
391
|
+
* @deprecated Use formatFileSizeWithKey for localization support
|
|
392
|
+
*/
|
|
393
|
+
function formatFileSize(bytes) {
|
|
394
|
+
const { value, unitKey } = formatFileSizeWithKey(bytes);
|
|
395
|
+
// Fallback to non-translated units for backward compatibility
|
|
396
|
+
const unitMap = {
|
|
397
|
+
'storage.size.bytes': 'Bytes',
|
|
398
|
+
'storage.size.kb': 'KB',
|
|
399
|
+
'storage.size.mb': 'MB',
|
|
400
|
+
'storage.size.gb': 'GB',
|
|
401
|
+
};
|
|
402
|
+
return `${value} ${unitMap[unitKey]}`;
|
|
110
403
|
}
|
|
111
404
|
/**
|
|
112
405
|
* Storage provider options for dropdown selects
|
|
406
|
+
* Labels are translation keys - components should translate them
|
|
113
407
|
*/
|
|
114
|
-
const
|
|
115
|
-
{
|
|
116
|
-
{
|
|
117
|
-
{
|
|
118
|
-
{
|
|
408
|
+
const STORAGE_PROVIDER_OPTIONS = [
|
|
409
|
+
{ labelKey: 'storage.aws.title', value: FileLocationEnum.AWS },
|
|
410
|
+
{ labelKey: 'storage.azure.title', value: FileLocationEnum.AZURE },
|
|
411
|
+
{ labelKey: 'storage.sftp.title', value: FileLocationEnum.SFTP },
|
|
412
|
+
{ labelKey: 'storage.local.title', value: FileLocationEnum.LOCAL },
|
|
119
413
|
];
|
|
120
414
|
|
|
121
415
|
class BaseStoragePage {
|
|
@@ -123,13 +417,16 @@ class BaseStoragePage {
|
|
|
123
417
|
messageService = inject(MessageService);
|
|
124
418
|
appConfig = inject(APP_CONFIG);
|
|
125
419
|
companyContext = inject(LAYOUT_AUTH_STATE);
|
|
420
|
+
translateAdapter = inject(TRANSLATE_ADAPTER);
|
|
126
421
|
isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
|
|
127
422
|
showCompanyInfo = computed(() => this.appConfig.enableCompanyFeature, ...(ngDevMode ? [{ debugName: "showCompanyInfo" }] : []));
|
|
128
423
|
currentCompanyName = computed(() => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME, ...(ngDevMode ? [{ debugName: "currentCompanyName" }] : []));
|
|
129
|
-
showSuccess(detail,
|
|
424
|
+
showSuccess(detail, summaryKey = 'shared.success') {
|
|
425
|
+
const summary = this.translateAdapter.translate(summaryKey);
|
|
130
426
|
this.messageService.add({ severity: 'success', summary, detail });
|
|
131
427
|
}
|
|
132
|
-
showError(detail,
|
|
428
|
+
showError(detail, summaryKey = 'shared.error') {
|
|
429
|
+
const summary = this.translateAdapter.translate(summaryKey);
|
|
133
430
|
this.messageService.add({ severity: 'error', summary, detail });
|
|
134
431
|
}
|
|
135
432
|
navigateTo(path) {
|
|
@@ -143,12 +440,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
143
440
|
}] });
|
|
144
441
|
class BaseStorageListPage extends BaseListPage {
|
|
145
442
|
companyContext = inject(LAYOUT_AUTH_STATE);
|
|
443
|
+
translateAdapter = inject(TRANSLATE_ADAPTER);
|
|
146
444
|
pageSize = signal(50, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
|
|
147
445
|
totalRecords = this.total;
|
|
148
446
|
currentCompanyName = computed(() => this.companyContext.currentCompanyInfo()?.name ?? DEFAULT_APP_NAME, ...(ngDevMode ? [{ debugName: "currentCompanyName" }] : []));
|
|
149
447
|
getDeleteConfirmMessage(item) {
|
|
150
|
-
const
|
|
151
|
-
|
|
448
|
+
const itemName = item.name;
|
|
449
|
+
const name = itemName ?? this.translateAdapter.translate('storage.delete.this.item');
|
|
450
|
+
return this.translateAdapter.translate('storage.delete.confirm.named', { name });
|
|
152
451
|
}
|
|
153
452
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: BaseStorageListPage, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
154
453
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.5", type: BaseStorageListPage, isStandalone: true, usesInheritance: true, ngImport: i0 });
|
|
@@ -168,8 +467,8 @@ class FileManagerApiService extends ApiResourceService {
|
|
|
168
467
|
createFile(dto) {
|
|
169
468
|
return this.http.post(`${this.baseUrl}/insert`, dto);
|
|
170
469
|
}
|
|
171
|
-
|
|
172
|
-
return
|
|
470
|
+
createFiles(dtos) {
|
|
471
|
+
return this.http.post(`${this.baseUrl}/insert-many`, dtos);
|
|
173
472
|
}
|
|
174
473
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileManagerApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
175
474
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileManagerApiService, providedIn: 'root' });
|
|
@@ -179,6 +478,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
179
478
|
args: [{ providedIn: 'root' }]
|
|
180
479
|
}], ctorParameters: () => [] });
|
|
181
480
|
|
|
481
|
+
/**
|
|
482
|
+
* Folder API Service
|
|
483
|
+
* Handles folder CRUD operations
|
|
484
|
+
* Endpoint: POST /storage/folder/*
|
|
485
|
+
*
|
|
486
|
+
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
487
|
+
*/
|
|
488
|
+
class FolderApiService extends ApiResourceService {
|
|
489
|
+
constructor() {
|
|
490
|
+
super('folder', inject(HttpClient), 'storage');
|
|
491
|
+
}
|
|
492
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FolderApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
493
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FolderApiService, providedIn: 'root' });
|
|
494
|
+
}
|
|
495
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FolderApiService, decorators: [{
|
|
496
|
+
type: Injectable,
|
|
497
|
+
args: [{
|
|
498
|
+
providedIn: 'root',
|
|
499
|
+
}]
|
|
500
|
+
}], ctorParameters: () => [] });
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Storage Config API Service
|
|
504
|
+
* Handles storage configuration CRUD operations
|
|
505
|
+
* Endpoint: POST /storage/storage-config/*
|
|
506
|
+
*
|
|
507
|
+
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
508
|
+
*/
|
|
509
|
+
class StorageConfigApiService extends ApiResourceService {
|
|
510
|
+
constructor() {
|
|
511
|
+
super('storage-config', inject(HttpClient), 'storage');
|
|
512
|
+
}
|
|
513
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageConfigApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
514
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageConfigApiService, providedIn: 'root' });
|
|
515
|
+
}
|
|
516
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageConfigApiService, decorators: [{
|
|
517
|
+
type: Injectable,
|
|
518
|
+
args: [{
|
|
519
|
+
providedIn: 'root',
|
|
520
|
+
}]
|
|
521
|
+
}], ctorParameters: () => [] });
|
|
522
|
+
|
|
182
523
|
/**
|
|
183
524
|
* Upload Service - File upload/delete operations
|
|
184
525
|
* Endpoint: POST /storage/upload/*
|
|
@@ -220,23 +561,40 @@ class UploadService extends BaseApiService {
|
|
|
220
561
|
uploadAndRegister(file, options) {
|
|
221
562
|
return this.uploadSingleFile(file, options).pipe(switchMap((response) => {
|
|
222
563
|
if (!response.success || !response.data) {
|
|
223
|
-
throw new Error(response.message || '
|
|
564
|
+
throw new Error(response.message || 'upload.failed');
|
|
224
565
|
}
|
|
225
|
-
return this.fileManagerApi.createFile(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
566
|
+
return this.fileManagerApi.createFile(this.toCreateFileDto(response.data, options));
|
|
567
|
+
}));
|
|
568
|
+
}
|
|
569
|
+
/** Upload multiple files and register in file manager - batch upload (2 API calls total) */
|
|
570
|
+
uploadAndRegisterMultiple(files, options) {
|
|
571
|
+
return this.uploadMultipleFiles(files, options).pipe(switchMap((response) => {
|
|
572
|
+
if (!response.success || !response.data) {
|
|
573
|
+
throw new Error(response.message || 'upload.failed');
|
|
574
|
+
}
|
|
575
|
+
const dtos = response.data.map((fileInfo) => this.toCreateFileDto(fileInfo, options));
|
|
576
|
+
return this.fileManagerApi.createFiles(dtos).pipe(map((bulkResponse) => ({
|
|
577
|
+
success: bulkResponse.success,
|
|
578
|
+
data: bulkResponse.data ?? [],
|
|
579
|
+
message: bulkResponse.message,
|
|
580
|
+
})));
|
|
234
581
|
}));
|
|
235
582
|
}
|
|
236
583
|
// ─── Private Helpers ───────────────────────────────────────────────────────
|
|
237
584
|
resolveConfigId(storageConfigId) {
|
|
238
585
|
return storageConfigId ?? this.getDefaultConfigId();
|
|
239
586
|
}
|
|
587
|
+
toCreateFileDto(fileInfo, options) {
|
|
588
|
+
return {
|
|
589
|
+
name: fileInfo.name,
|
|
590
|
+
key: fileInfo.key,
|
|
591
|
+
size: String(fileInfo.size),
|
|
592
|
+
contentType: fileInfo.contentType,
|
|
593
|
+
isPrivate: options?.isPrivate ?? false,
|
|
594
|
+
folderId: options?.folderId,
|
|
595
|
+
storageConfigId: this.resolveConfigId(options?.storageConfigId),
|
|
596
|
+
};
|
|
597
|
+
}
|
|
240
598
|
buildUploadUrl(endpoint, options) {
|
|
241
599
|
const params = this.buildQueryParams(options);
|
|
242
600
|
const baseUrl = this.getUrl(`upload/${endpoint}`);
|
|
@@ -273,50 +631,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
273
631
|
args: [{ providedIn: 'root' }]
|
|
274
632
|
}], ctorParameters: () => [] });
|
|
275
633
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
*
|
|
279
|
-
* Implements IProfileUploadProvider interface for ng-auth profile page.
|
|
280
|
-
* Uses UploadService.uploadAndRegister() to upload files and register in file manager.
|
|
281
|
-
*
|
|
282
|
-
* @example
|
|
283
|
-
* // In app.config.ts
|
|
284
|
-
* providers: [
|
|
285
|
-
* ...provideStorageProviders(),
|
|
286
|
-
* ]
|
|
287
|
-
*/
|
|
288
|
-
class ProfileUploadProviderAdapter {
|
|
634
|
+
class FileProviderAdapter {
|
|
635
|
+
fileManagerApi = inject(FileManagerApiService);
|
|
289
636
|
uploadService = inject(UploadService);
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
.
|
|
297
|
-
|
|
298
|
-
compress: options?.compress ?? true,
|
|
299
|
-
maxWidth: options?.maxWidth ?? 400,
|
|
300
|
-
maxHeight: options?.maxHeight ?? 400,
|
|
637
|
+
folderApi = inject(FolderApiService);
|
|
638
|
+
storageConfigApi = inject(StorageConfigApiService);
|
|
639
|
+
loadFiles(filter) {
|
|
640
|
+
const filterObj = this.buildFileFilter(filter);
|
|
641
|
+
return this.fileManagerApi
|
|
642
|
+
.getAll(filter.search || '', {
|
|
643
|
+
pagination: { currentPage: filter.page, pageSize: filter.pageSize },
|
|
644
|
+
filter: Object.keys(filterObj).length > 0 ? filterObj : undefined,
|
|
301
645
|
})
|
|
302
|
-
.pipe(map((
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
646
|
+
.pipe(map((res) => ({ ...res, data: res.data?.map(this.mapToFileBasicInfo) })));
|
|
647
|
+
}
|
|
648
|
+
uploadFile(file, options) {
|
|
649
|
+
return this.uploadService
|
|
650
|
+
.uploadAndRegister(file, options)
|
|
651
|
+
.pipe(map((res) => ({ ...res, data: res.data ? this.mapToUploadedFile(res.data) : undefined })));
|
|
652
|
+
}
|
|
653
|
+
uploadMultipleFiles(files, options) {
|
|
654
|
+
return this.uploadService
|
|
655
|
+
.uploadAndRegisterMultiple(files, options)
|
|
656
|
+
.pipe(map((res) => ({ ...res, data: res.data?.map(this.mapToUploadedFile) })));
|
|
657
|
+
}
|
|
658
|
+
getFileUrls(fileIds) {
|
|
659
|
+
return this.fileManagerApi.getFiles(fileIds).pipe(map((res) => ({
|
|
660
|
+
...res,
|
|
661
|
+
data: res.data?.map((f) => ({ id: f.id, name: f.name, contentType: f.contentType, size: '0', url: f.url })),
|
|
314
662
|
})));
|
|
315
663
|
}
|
|
316
|
-
|
|
317
|
-
|
|
664
|
+
loadFolders(filter) {
|
|
665
|
+
return this.folderApi
|
|
666
|
+
.getAll(filter.search || '', {
|
|
667
|
+
pagination: { currentPage: filter.page, pageSize: filter.pageSize },
|
|
668
|
+
})
|
|
669
|
+
.pipe(map((res) => ({ ...res, data: res.data?.map((f) => ({ id: f.id, name: f.name, slug: f.slug })) })));
|
|
670
|
+
}
|
|
671
|
+
loadStorageConfigs(filter) {
|
|
672
|
+
return this.storageConfigApi
|
|
673
|
+
.getAll(filter.search || '', {
|
|
674
|
+
pagination: { currentPage: filter.page, pageSize: filter.pageSize },
|
|
675
|
+
})
|
|
676
|
+
.pipe(map((res) => ({ ...res, data: res.data?.map((c) => ({ id: c.id, name: c.name, isDefault: c.isDefault })) })));
|
|
677
|
+
}
|
|
678
|
+
// ─── Private Helpers ────────────────────────────────────────────────────────
|
|
679
|
+
buildFileFilter(filter) {
|
|
680
|
+
const filterObj = {};
|
|
681
|
+
if (filter.folderId)
|
|
682
|
+
filterObj['folderId'] = filter.folderId;
|
|
683
|
+
if (filter.storageConfigId)
|
|
684
|
+
filterObj['storageConfigId'] = filter.storageConfigId;
|
|
685
|
+
if (filter.contentTypes?.length)
|
|
686
|
+
filterObj['contentType'] = filter.contentTypes.join(',');
|
|
687
|
+
return filterObj;
|
|
688
|
+
}
|
|
689
|
+
mapToFileBasicInfo = (f) => ({
|
|
690
|
+
id: f.id,
|
|
691
|
+
name: f.name,
|
|
692
|
+
contentType: f.contentType,
|
|
693
|
+
size: f.size,
|
|
694
|
+
url: f.url,
|
|
695
|
+
});
|
|
696
|
+
mapToUploadedFile = (f) => ({
|
|
697
|
+
id: f.id,
|
|
698
|
+
name: f.name,
|
|
699
|
+
key: f.key,
|
|
700
|
+
size: parseFloat(f.size) * 1024,
|
|
701
|
+
contentType: f.contentType,
|
|
702
|
+
});
|
|
703
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileProviderAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
704
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileProviderAdapter });
|
|
318
705
|
}
|
|
319
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type:
|
|
706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FileProviderAdapter, decorators: [{
|
|
320
707
|
type: Injectable
|
|
321
708
|
}] });
|
|
322
709
|
|
|
@@ -339,54 +726,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
339
726
|
function provideStorageProviders() {
|
|
340
727
|
return [
|
|
341
728
|
{
|
|
342
|
-
provide:
|
|
343
|
-
useClass:
|
|
729
|
+
provide: FILE_PROVIDER,
|
|
730
|
+
useClass: FileProviderAdapter,
|
|
344
731
|
},
|
|
345
732
|
];
|
|
346
733
|
}
|
|
347
734
|
|
|
348
|
-
/**
|
|
349
|
-
* Folder API Service
|
|
350
|
-
* Handles folder CRUD operations
|
|
351
|
-
* Endpoint: POST /storage/folder/*
|
|
352
|
-
*
|
|
353
|
-
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
354
|
-
*/
|
|
355
|
-
class FolderApiService extends ApiResourceService {
|
|
356
|
-
constructor() {
|
|
357
|
-
super('folder', inject(HttpClient), 'storage');
|
|
358
|
-
}
|
|
359
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FolderApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
360
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FolderApiService, providedIn: 'root' });
|
|
361
|
-
}
|
|
362
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: FolderApiService, decorators: [{
|
|
363
|
-
type: Injectable,
|
|
364
|
-
args: [{
|
|
365
|
-
providedIn: 'root',
|
|
366
|
-
}]
|
|
367
|
-
}], ctorParameters: () => [] });
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Storage Config API Service
|
|
371
|
-
* Handles storage configuration CRUD operations
|
|
372
|
-
* Endpoint: POST /storage/storage-config/*
|
|
373
|
-
*
|
|
374
|
-
* Note: Company feature enabled - all queries automatically scoped to user's company
|
|
375
|
-
*/
|
|
376
|
-
class StorageConfigApiService extends ApiResourceService {
|
|
377
|
-
constructor() {
|
|
378
|
-
super('storage-config', inject(HttpClient), 'storage');
|
|
379
|
-
}
|
|
380
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageConfigApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
381
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageConfigApiService, providedIn: 'root' });
|
|
382
|
-
}
|
|
383
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageConfigApiService, decorators: [{
|
|
384
|
-
type: Injectable,
|
|
385
|
-
args: [{
|
|
386
|
-
providedIn: 'root',
|
|
387
|
-
}]
|
|
388
|
-
}], ctorParameters: () => [] });
|
|
389
|
-
|
|
390
735
|
/**
|
|
391
736
|
* Storage Module Routes
|
|
392
737
|
* All routes protected by permission guards
|
|
@@ -394,6 +739,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
394
739
|
const STORAGE_ROUTES = [
|
|
395
740
|
{
|
|
396
741
|
path: '',
|
|
742
|
+
resolve: { translations: resolveTranslationModule({ modules: ['storage'], fallbackMessages: { ...STORAGE_MESSAGES, ...SHARED_MESSAGES } }) },
|
|
397
743
|
loadComponent: () => Promise.resolve().then(function () { return storageContainer_component; }).then((m) => m.StorageContainerComponent),
|
|
398
744
|
children: [
|
|
399
745
|
// File Manager Routes
|
|
@@ -403,17 +749,17 @@ const STORAGE_ROUTES = [
|
|
|
403
749
|
children: [
|
|
404
750
|
{
|
|
405
751
|
path: '',
|
|
406
|
-
loadComponent: () => import('./flusys-ng-storage-file-manager-list.component-
|
|
752
|
+
loadComponent: () => import('./flusys-ng-storage-file-manager-list.component-bj6oOzOL.mjs').then((m) => m.FileManagerListComponent),
|
|
407
753
|
},
|
|
408
754
|
{
|
|
409
755
|
path: 'new',
|
|
410
756
|
canActivate: [permissionGuard(FILE_PERMISSIONS.CREATE)],
|
|
411
|
-
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-
|
|
757
|
+
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs').then((m) => m.FileManagerFormComponent),
|
|
412
758
|
},
|
|
413
759
|
{
|
|
414
760
|
path: ':id',
|
|
415
761
|
canActivate: [permissionGuard(FILE_PERMISSIONS.UPDATE)],
|
|
416
|
-
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-
|
|
762
|
+
loadComponent: () => import('./flusys-ng-storage-file-manager-form.component-AM7JE-s5.mjs').then((m) => m.FileManagerFormComponent),
|
|
417
763
|
},
|
|
418
764
|
],
|
|
419
765
|
},
|
|
@@ -424,17 +770,17 @@ const STORAGE_ROUTES = [
|
|
|
424
770
|
children: [
|
|
425
771
|
{
|
|
426
772
|
path: '',
|
|
427
|
-
loadComponent: () => import('./flusys-ng-storage-folder-list.component-
|
|
773
|
+
loadComponent: () => import('./flusys-ng-storage-folder-list.component-B2Q41I1g.mjs').then((m) => m.FolderListComponent),
|
|
428
774
|
},
|
|
429
775
|
{
|
|
430
776
|
path: 'new',
|
|
431
777
|
canActivate: [permissionGuard(FOLDER_PERMISSIONS.CREATE)],
|
|
432
|
-
loadComponent: () => import('./flusys-ng-storage-folder-form.component-
|
|
778
|
+
loadComponent: () => import('./flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs').then((m) => m.FolderFormComponent),
|
|
433
779
|
},
|
|
434
780
|
{
|
|
435
781
|
path: ':id',
|
|
436
782
|
canActivate: [permissionGuard(FOLDER_PERMISSIONS.UPDATE)],
|
|
437
|
-
loadComponent: () => import('./flusys-ng-storage-folder-form.component-
|
|
783
|
+
loadComponent: () => import('./flusys-ng-storage-folder-form.component-Cc2ybTwu.mjs').then((m) => m.FolderFormComponent),
|
|
438
784
|
},
|
|
439
785
|
],
|
|
440
786
|
},
|
|
@@ -445,17 +791,17 @@ const STORAGE_ROUTES = [
|
|
|
445
791
|
children: [
|
|
446
792
|
{
|
|
447
793
|
path: '',
|
|
448
|
-
loadComponent: () => import('./flusys-ng-storage-storage-config-list.component-
|
|
794
|
+
loadComponent: () => import('./flusys-ng-storage-storage-config-list.component-DBH_qf9o.mjs').then((m) => m.StorageConfigListComponent),
|
|
449
795
|
},
|
|
450
796
|
{
|
|
451
797
|
path: 'new',
|
|
452
798
|
canActivate: [permissionGuard(STORAGE_CONFIG_PERMISSIONS.CREATE)],
|
|
453
|
-
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-
|
|
799
|
+
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs').then((m) => m.StorageConfigFormComponent),
|
|
454
800
|
},
|
|
455
801
|
{
|
|
456
802
|
path: ':id',
|
|
457
803
|
canActivate: [permissionGuard(STORAGE_CONFIG_PERMISSIONS.UPDATE)],
|
|
458
|
-
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-
|
|
804
|
+
loadComponent: () => import('./flusys-ng-storage-storage-config-form.component-a88XhuPH.mjs').then((m) => m.StorageConfigFormComponent),
|
|
459
805
|
},
|
|
460
806
|
],
|
|
461
807
|
},
|
|
@@ -478,21 +824,21 @@ class StorageContainerComponent {
|
|
|
478
824
|
allTabs = [
|
|
479
825
|
{
|
|
480
826
|
id: 'files',
|
|
481
|
-
|
|
827
|
+
labelKey: 'storage.file.title',
|
|
482
828
|
icon: 'pi pi-file',
|
|
483
829
|
route: 'files',
|
|
484
830
|
permission: FILE_PERMISSIONS.READ,
|
|
485
831
|
},
|
|
486
832
|
{
|
|
487
833
|
id: 'folders',
|
|
488
|
-
|
|
834
|
+
labelKey: 'storage.folder.title',
|
|
489
835
|
icon: 'pi pi-folder',
|
|
490
836
|
route: 'folders',
|
|
491
837
|
permission: FOLDER_PERMISSIONS.READ,
|
|
492
838
|
},
|
|
493
839
|
{
|
|
494
840
|
id: 'configs',
|
|
495
|
-
|
|
841
|
+
labelKey: 'storage.config.title',
|
|
496
842
|
icon: 'pi pi-cog',
|
|
497
843
|
route: 'configs',
|
|
498
844
|
permission: STORAGE_CONFIG_PERMISSIONS.READ,
|
|
@@ -500,19 +846,12 @@ class StorageContainerComponent {
|
|
|
500
846
|
];
|
|
501
847
|
/** Visible tabs based on user permissions */
|
|
502
848
|
visibleTabs = computed(() => this.allTabs.filter((tab) => this.permissionValidator.hasPermission(tab.permission)), ...(ngDevMode ? [{ debugName: "visibleTabs" }] : []));
|
|
503
|
-
/** Dynamic subtitle based on visible tabs */
|
|
504
|
-
subtitle = computed(() => {
|
|
505
|
-
const tabs = this.visibleTabs();
|
|
506
|
-
if (tabs.length === 0)
|
|
507
|
-
return 'No permissions available';
|
|
508
|
-
return `Manage ${tabs.map((t) => t.label.toLowerCase()).join(', ')}`;
|
|
509
|
-
}, ...(ngDevMode ? [{ debugName: "subtitle" }] : []));
|
|
510
849
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
511
850
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.5", type: StorageContainerComponent, isStandalone: true, selector: "lib-storage-container", ngImport: i0, template: `
|
|
512
851
|
<div class="p-2 sm:p-4">
|
|
513
852
|
<div class="mb-4">
|
|
514
|
-
<h1 class="text-xl sm:text-2xl font-bold m-0">
|
|
515
|
-
<p class="text-muted-color mt-1 text-sm sm:text-base">{{ subtitle
|
|
853
|
+
<h1 class="text-xl sm:text-2xl font-bold m-0">{{ 'storage.title' | translate }}</h1>
|
|
854
|
+
<p class="text-muted-color mt-1 text-sm sm:text-base">{{ 'storage.subtitle' | translate }}</p>
|
|
516
855
|
</div>
|
|
517
856
|
|
|
518
857
|
<div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
|
|
@@ -523,22 +862,22 @@ class StorageContainerComponent {
|
|
|
523
862
|
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"
|
|
524
863
|
>
|
|
525
864
|
<i [class]="tab.icon"></i>
|
|
526
|
-
<span>{{ tab.
|
|
865
|
+
<span>{{ tab.labelKey | translate }}</span>
|
|
527
866
|
</a>
|
|
528
867
|
}
|
|
529
868
|
</div>
|
|
530
869
|
|
|
531
870
|
<router-outlet />
|
|
532
871
|
</div>
|
|
533
|
-
`, 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"] }
|
|
872
|
+
`, 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"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
|
|
534
873
|
}
|
|
535
874
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImport: i0, type: StorageContainerComponent, decorators: [{
|
|
536
875
|
type: Component,
|
|
537
|
-
args: [{ selector: 'lib-storage-container',
|
|
876
|
+
args: [{ selector: 'lib-storage-container', imports: [CommonModule, RouterOutlet, RouterLink, RouterLinkActive, TranslatePipe], template: `
|
|
538
877
|
<div class="p-2 sm:p-4">
|
|
539
878
|
<div class="mb-4">
|
|
540
|
-
<h1 class="text-xl sm:text-2xl font-bold m-0">
|
|
541
|
-
<p class="text-muted-color mt-1 text-sm sm:text-base">{{ subtitle
|
|
879
|
+
<h1 class="text-xl sm:text-2xl font-bold m-0">{{ 'storage.title' | translate }}</h1>
|
|
880
|
+
<p class="text-muted-color mt-1 text-sm sm:text-base">{{ 'storage.subtitle' | translate }}</p>
|
|
542
881
|
</div>
|
|
543
882
|
|
|
544
883
|
<div class="scrollbar-hide flex gap-1 mb-4 border-b border-surface overflow-x-auto flex-nowrap">
|
|
@@ -549,7 +888,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.5", ngImpor
|
|
|
549
888
|
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"
|
|
550
889
|
>
|
|
551
890
|
<i [class]="tab.icon"></i>
|
|
552
|
-
<span>{{ tab.
|
|
891
|
+
<span>{{ tab.labelKey | translate }}</span>
|
|
553
892
|
</a>
|
|
554
893
|
}
|
|
555
894
|
</div>
|
|
@@ -567,11 +906,11 @@ var storageContainer_component = /*#__PURE__*/Object.freeze({
|
|
|
567
906
|
// =============================================================================
|
|
568
907
|
// @flusys/ng-storage - Storage Package
|
|
569
908
|
// =============================================================================
|
|
570
|
-
//
|
|
909
|
+
// Constants
|
|
571
910
|
|
|
572
911
|
/**
|
|
573
912
|
* Generated bundle index. Do not edit.
|
|
574
913
|
*/
|
|
575
914
|
|
|
576
|
-
export { BaseStorageListPage, BaseStoragePage, FileLocationEnum, FileManagerApiService, FolderApiService, ImageFormat,
|
|
915
|
+
export { BaseStorageListPage, BaseStoragePage, FILE_SIZE_UNIT_KEYS, FileLocationEnum, FileManagerApiService, FileProviderAdapter, FolderApiService, ImageFormat, PROVIDER_LABEL_KEYS, STORAGE_MESSAGES, STORAGE_PROVIDER_OPTIONS, STORAGE_ROUTES, StorageConfigApiService, StorageContainerComponent, UploadService, formatFileSize, formatFileSizeWithKey, getFileIcon, getProviderIcon, getProviderLabelKey, getProviderSeverity, provideStorageProviders };
|
|
577
916
|
//# sourceMappingURL=flusys-ng-storage.mjs.map
|