@masterteam/components 0.0.97 → 0.0.99
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/fesm2022/masterteam-components-breadcrumb.mjs +2 -2
- package/fesm2022/masterteam-components-breadcrumb.mjs.map +1 -1
- package/fesm2022/masterteam-components-entities.mjs +34 -4
- package/fesm2022/masterteam-components-entities.mjs.map +1 -1
- package/fesm2022/masterteam-components-upload-field.mjs +147 -96
- package/fesm2022/masterteam-components-upload-field.mjs.map +1 -1
- package/fesm2022/masterteam-components.mjs +2 -0
- package/fesm2022/masterteam-components.mjs.map +1 -1
- package/package.json +2 -2
- package/types/masterteam-components-entities.d.ts +28 -4
- package/types/masterteam-components-upload-field.d.ts +20 -15
- package/types/masterteam-components.d.ts +2 -0
|
@@ -3,7 +3,7 @@ import { inject, ChangeDetectorRef, Pipe, input, output, model, computed, Compon
|
|
|
3
3
|
import { Button } from '@masterteam/components/button';
|
|
4
4
|
import { distinctUntilChanged, filter, switchMap, map, catchError, finalize, tap } from 'rxjs/operators';
|
|
5
5
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
6
|
-
import { Subscription, BehaviorSubject, of,
|
|
6
|
+
import { Subscription, BehaviorSubject, of, finalize as finalize$1, catchError as catchError$1, throwError, take, forkJoin, map as map$1 } from 'rxjs';
|
|
7
7
|
import { HttpClient, HttpContext } from '@angular/common/http';
|
|
8
8
|
import { Avatar } from '@masterteam/components/avatar';
|
|
9
9
|
import * as i1 from '@jsverse/transloco';
|
|
@@ -145,11 +145,11 @@ class UploadFilePreview {
|
|
|
145
145
|
}
|
|
146
146
|
}, ...(ngDevMode ? [{ debugName: "defaultIcon" }] : []));
|
|
147
147
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UploadFilePreview, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
148
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UploadFilePreview, isStandalone: true, selector: "mt-upload-file-preview", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, imgPath: { classPropertyName: "imgPath", publicName: "imgPath", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, uploadProgress: { classPropertyName: "uploadProgress", publicName: "uploadProgress", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onUploadInputClicked: "onUploadInputClicked", ondDownloadFile: "ondDownloadFile", onDeleteFile: "onDeleteFile", disabled: "disabledChange" }, ngImport: i0, template: "<div class=\"flex items-center justify-between gap-2 w-full p-2 overflow-hidden\">\r\n <div class=\"flex gap-2 items-center flex-1 min-w-0 overflow-hidden\">\r\n <mt-avatar\r\n [size]=\"size()\"\r\n [shape]=\"'square'\"\r\n [image]=\"\r\n isImag() && imgPath() ? (imgPath() | secureImage: context()) : ''\r\n \"\r\n [icon]=\"defaultIcon()\"\r\n styleClass=\"text-2xl!\"\r\n >\r\n </mt-avatar>\r\n\r\n <span class=\"truncate\" [mtTooltip]=\"value().name\" tooltipPosition=\"top\">\r\n {{ value().name }}\r\n </span>\r\n </div>\r\n <div class=\"flex items-center justify-center shrink-0\">\r\n @if (
|
|
148
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UploadFilePreview, isStandalone: true, selector: "mt-upload-file-preview", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, imgPath: { classPropertyName: "imgPath", publicName: "imgPath", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, uploadProgress: { classPropertyName: "uploadProgress", publicName: "uploadProgress", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onUploadInputClicked: "onUploadInputClicked", ondDownloadFile: "ondDownloadFile", onDeleteFile: "onDeleteFile", disabled: "disabledChange" }, ngImport: i0, template: "<div class=\"flex items-center justify-between gap-2 w-full p-2 overflow-hidden\">\r\n <div class=\"flex gap-2 items-center flex-1 min-w-0 overflow-hidden\">\r\n <mt-avatar\r\n [size]=\"size()\"\r\n [shape]=\"'square'\"\r\n [image]=\"\r\n isImag() && imgPath() ? (imgPath() | secureImage: context()) : ''\r\n \"\r\n [icon]=\"defaultIcon()\"\r\n styleClass=\"text-2xl!\"\r\n >\r\n </mt-avatar>\r\n\r\n <span class=\"truncate\" [mtTooltip]=\"value().name\" tooltipPosition=\"top\">\r\n {{ value().name }}\r\n </span>\r\n </div>\r\n <div class=\"flex items-center justify-center shrink-0\">\r\n @if (!!value() && !loading() && (!disabled() || readonly())) {\r\n <mt-button\r\n variant=\"text\"\r\n icon=\"general.download-01\"\r\n [tooltip]=\"'components.upload.download' | transloco\"\r\n (onClick)=\"ondDownloadFile.emit(value())\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n </mt-button>\r\n }\r\n @if (!disabled() && !readonly() && !!value() && !loading()) {\r\n <mt-button\r\n variant=\"text\"\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"'components.upload.delete' | transloco\"\r\n severity=\"danger\"\r\n (onClick)=\"onDeleteFile.emit(true)\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }, { kind: "pipe", type: SecureImagePipe, name: "secureImage" }, { kind: "pipe", type: i1.TranslocoPipe, name: "transloco" }] });
|
|
149
149
|
}
|
|
150
150
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UploadFilePreview, decorators: [{
|
|
151
151
|
type: Component,
|
|
152
|
-
args: [{ selector: 'mt-upload-file-preview', standalone: true, imports: [SecureImagePipe, Button, Avatar, TranslocoModule, Tooltip], template: "<div class=\"flex items-center justify-between gap-2 w-full p-2 overflow-hidden\">\r\n <div class=\"flex gap-2 items-center flex-1 min-w-0 overflow-hidden\">\r\n <mt-avatar\r\n [size]=\"size()\"\r\n [shape]=\"'square'\"\r\n [image]=\"\r\n isImag() && imgPath() ? (imgPath() | secureImage: context()) : ''\r\n \"\r\n [icon]=\"defaultIcon()\"\r\n styleClass=\"text-2xl!\"\r\n >\r\n </mt-avatar>\r\n\r\n <span class=\"truncate\" [mtTooltip]=\"value().name\" tooltipPosition=\"top\">\r\n {{ value().name }}\r\n </span>\r\n </div>\r\n <div class=\"flex items-center justify-center shrink-0\">\r\n @if (
|
|
152
|
+
args: [{ selector: 'mt-upload-file-preview', standalone: true, imports: [SecureImagePipe, Button, Avatar, TranslocoModule, Tooltip], template: "<div class=\"flex items-center justify-between gap-2 w-full p-2 overflow-hidden\">\r\n <div class=\"flex gap-2 items-center flex-1 min-w-0 overflow-hidden\">\r\n <mt-avatar\r\n [size]=\"size()\"\r\n [shape]=\"'square'\"\r\n [image]=\"\r\n isImag() && imgPath() ? (imgPath() | secureImage: context()) : ''\r\n \"\r\n [icon]=\"defaultIcon()\"\r\n styleClass=\"text-2xl!\"\r\n >\r\n </mt-avatar>\r\n\r\n <span class=\"truncate\" [mtTooltip]=\"value().name\" tooltipPosition=\"top\">\r\n {{ value().name }}\r\n </span>\r\n </div>\r\n <div class=\"flex items-center justify-center shrink-0\">\r\n @if (!!value() && !loading() && (!disabled() || readonly())) {\r\n <mt-button\r\n variant=\"text\"\r\n icon=\"general.download-01\"\r\n [tooltip]=\"'components.upload.download' | transloco\"\r\n (onClick)=\"ondDownloadFile.emit(value())\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n </mt-button>\r\n }\r\n @if (!disabled() && !readonly() && !!value() && !loading()) {\r\n <mt-button\r\n variant=\"text\"\r\n icon=\"general.trash-01\"\r\n [tooltip]=\"'components.upload.delete' | transloco\"\r\n severity=\"danger\"\r\n (onClick)=\"onDeleteFile.emit(true)\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n </mt-button>\r\n }\r\n </div>\r\n</div>\r\n" }]
|
|
153
153
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], imgPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "imgPath", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], uploadProgress: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadProgress", required: false }] }], onUploadInputClicked: [{ type: i0.Output, args: ["onUploadInputClicked"] }], ondDownloadFile: [{ type: i0.Output, args: ["ondDownloadFile"] }], onDeleteFile: [{ type: i0.Output, args: ["onDeleteFile"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
154
154
|
|
|
155
155
|
class UploadUserPreview {
|
|
@@ -205,6 +205,7 @@ class UploadField {
|
|
|
205
205
|
size = input(...(ngDevMode ? [undefined, { debugName: "size" }] : []));
|
|
206
206
|
userImgClass = input('w-25! h-25! text-4xl! text-gray-400!', ...(ngDevMode ? [{ debugName: "userImgClass" }] : []));
|
|
207
207
|
shape = input('field', ...(ngDevMode ? [{ debugName: "shape" }] : []));
|
|
208
|
+
multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
|
|
208
209
|
accept = input('.pdf,.doc,.docx,.xlsx,image/*', ...(ngDevMode ? [{ debugName: "accept" }] : []));
|
|
209
210
|
isDragging = model(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
|
|
210
211
|
fileSizeLimit = input(...(ngDevMode ? [undefined, { debugName: "fileSizeLimit" }] : []));
|
|
@@ -213,53 +214,45 @@ class UploadField {
|
|
|
213
214
|
onChange = output();
|
|
214
215
|
requiredValidator = Validators.required;
|
|
215
216
|
value = signal(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
217
|
+
files = computed(() => {
|
|
218
|
+
const value = this.value();
|
|
219
|
+
if (Array.isArray(value)) {
|
|
220
|
+
return value.filter((item) => item != null);
|
|
221
|
+
}
|
|
222
|
+
return value ? [value] : [];
|
|
223
|
+
}, ...(ngDevMode ? [{ debugName: "files" }] : []));
|
|
224
|
+
primaryFile = computed(() => this.files()[0] ?? null, ...(ngDevMode ? [{ debugName: "primaryFile" }] : []));
|
|
225
|
+
imgPath = computed(() => this.resolveImgPath(this.primaryFile()), ...(ngDevMode ? [{ debugName: "imgPath" }] : []));
|
|
216
226
|
disabled = signal(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
217
227
|
uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : []));
|
|
218
|
-
httpClient = inject(HttpClient);
|
|
219
228
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
229
|
+
httpClient = inject(HttpClient);
|
|
230
|
+
pendingUploads = signal(0, ...(ngDevMode ? [{ debugName: "pendingUploads" }] : []));
|
|
220
231
|
onTouched = () => { };
|
|
221
232
|
onModelChange = () => { };
|
|
222
233
|
ngControl = inject(NgControl, { self: true });
|
|
223
|
-
imgPath = computed(() => {
|
|
224
|
-
if (this.value()?.fileName) {
|
|
225
|
-
return this.value()?.fileName
|
|
226
|
-
? this.endPoint() + '/' + this.value().fileName
|
|
227
|
-
: '';
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
return undefined;
|
|
231
|
-
}
|
|
232
|
-
}, ...(ngDevMode ? [{ debugName: "imgPath" }] : []));
|
|
233
234
|
constructor() {
|
|
234
235
|
if (this.ngControl) {
|
|
235
236
|
this.ngControl.valueAccessor = this;
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
239
|
writeValue(value) {
|
|
239
|
-
if (value
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
if (Array.isArray(value)) {
|
|
241
|
+
const normalized = value.filter((item) => item != null);
|
|
242
|
+
const fileIds = normalized.filter((item) => typeof item === 'string' && item.trim().length > 0);
|
|
243
|
+
const files = normalized.filter((item) => !!item && typeof item === 'object');
|
|
244
|
+
if (fileIds.length) {
|
|
245
|
+
this.fetchMetadata(fileIds, files, true);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
this.value.set(normalized);
|
|
249
|
+
return;
|
|
242
250
|
}
|
|
243
|
-
|
|
244
|
-
this.
|
|
251
|
+
if (typeof value === 'string' && value.trim().length > 0) {
|
|
252
|
+
this.fetchMetadata([value], [], false);
|
|
253
|
+
return;
|
|
245
254
|
}
|
|
246
|
-
|
|
247
|
-
fetchMetadata(fileId) {
|
|
248
|
-
this.loading.set(true);
|
|
249
|
-
const metadataUrl = `${this.endPoint()}/${fileId}/metaData`;
|
|
250
|
-
this.httpClient
|
|
251
|
-
.get(metadataUrl, {
|
|
252
|
-
context: this.context(),
|
|
253
|
-
})
|
|
254
|
-
.pipe(take(1), finalize$1(() => this.loading.set(false)), catchError$1((error) => {
|
|
255
|
-
console.error('Failed to fetch file metadata:', error);
|
|
256
|
-
// Set minimal value with just the ID so download might still work
|
|
257
|
-
this.value.set({ fileName: fileId, id: fileId });
|
|
258
|
-
return throwError(() => error);
|
|
259
|
-
}))
|
|
260
|
-
.subscribe((response) => {
|
|
261
|
-
this.value.set(response.data);
|
|
262
|
-
});
|
|
255
|
+
this.value.set(value ?? null);
|
|
263
256
|
}
|
|
264
257
|
registerOnChange(fn) {
|
|
265
258
|
this.onModelChange = fn;
|
|
@@ -271,99 +264,113 @@ class UploadField {
|
|
|
271
264
|
this.disabled.set(disabled);
|
|
272
265
|
}
|
|
273
266
|
onAdd(item) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
this.value.set(item);
|
|
277
|
-
this.onModelChange(this.value() ?? null);
|
|
278
|
-
this.onChange.emit(this.value());
|
|
267
|
+
if (this.disabled()) {
|
|
268
|
+
return;
|
|
279
269
|
}
|
|
270
|
+
const nextValue = this.multiple() ? [...this.files(), item] : item;
|
|
271
|
+
this.value.set(nextValue);
|
|
272
|
+
this.onModelChange(nextValue);
|
|
273
|
+
this.onChange.emit(nextValue);
|
|
280
274
|
}
|
|
281
|
-
onDelete() {
|
|
282
|
-
if (
|
|
283
|
-
|
|
275
|
+
onDelete(item) {
|
|
276
|
+
if (this.disabled()) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (!this.multiple()) {
|
|
284
280
|
this.value.set(null);
|
|
285
|
-
this.onModelChange(
|
|
286
|
-
this.onChange.emit(
|
|
281
|
+
this.onModelChange(null);
|
|
282
|
+
this.onChange.emit(null);
|
|
283
|
+
return;
|
|
287
284
|
}
|
|
285
|
+
const nextValue = this.files().filter((file) => !isSameFile(file, item));
|
|
286
|
+
const resolvedValue = nextValue.length ? nextValue : null;
|
|
287
|
+
this.value.set(resolvedValue);
|
|
288
|
+
this.onModelChange(resolvedValue);
|
|
289
|
+
this.onChange.emit(resolvedValue);
|
|
288
290
|
}
|
|
289
291
|
onFileSelect(event) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
+
const input = event.target;
|
|
293
|
+
const selectedFiles = Array.from(input?.files ?? []);
|
|
294
|
+
if (!selectedFiles.length) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (!this.multiple()) {
|
|
292
298
|
this.value.set(null);
|
|
293
|
-
|
|
294
|
-
|
|
299
|
+
}
|
|
300
|
+
this.prepareFiles(selectedFiles);
|
|
301
|
+
if (input) {
|
|
302
|
+
input.value = '';
|
|
295
303
|
}
|
|
296
304
|
}
|
|
297
|
-
|
|
305
|
+
prepareFiles(files) {
|
|
298
306
|
this.ngControl.control?.setErrors({ uploading: true });
|
|
299
|
-
if (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
this.uploadFile(files[0]);
|
|
307
|
+
if (this.shape() === 'circle' &&
|
|
308
|
+
files.some((file) => !file?.type.startsWith('image/'))) {
|
|
309
|
+
this.ngControl.control?.setErrors({ invalidFileType: true });
|
|
310
|
+
return;
|
|
305
311
|
}
|
|
312
|
+
const filesToUpload = this.multiple() ? files : [files[0]];
|
|
313
|
+
filesToUpload.forEach((file) => this.uploadFile(file));
|
|
306
314
|
}
|
|
307
315
|
uploadFile(file) {
|
|
316
|
+
this.pendingUploads.update((count) => count + 1);
|
|
308
317
|
this.loading.set(true);
|
|
309
318
|
this.uploadProgress.set(10);
|
|
310
319
|
const formData = new FormData();
|
|
311
320
|
formData.append('file', file);
|
|
312
321
|
this.httpClient
|
|
313
322
|
.post(this.endPoint(), formData, {
|
|
314
|
-
// 1. Crucial options to report upload progress
|
|
315
323
|
reportProgress: true,
|
|
316
324
|
observe: 'events',
|
|
317
325
|
context: this.context(),
|
|
318
326
|
})
|
|
319
327
|
.pipe(finalize$1(() => {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
328
|
+
const pending = Math.max(this.pendingUploads() - 1, 0);
|
|
329
|
+
this.pendingUploads.set(pending);
|
|
330
|
+
if (!pending) {
|
|
331
|
+
setTimeout(() => {
|
|
332
|
+
this.uploadProgress.set(0);
|
|
333
|
+
this.loading.set(false);
|
|
334
|
+
}, 700);
|
|
335
|
+
}
|
|
324
336
|
}), catchError$1(() => {
|
|
325
|
-
this.uploadProgress.set(0);
|
|
337
|
+
this.uploadProgress.set(0);
|
|
326
338
|
return throwError(() => new Error('Upload failed'));
|
|
327
339
|
}))
|
|
328
340
|
.subscribe((event) => {
|
|
329
|
-
console.log('event', event);
|
|
330
341
|
if (!event?.body) {
|
|
331
342
|
if (event.total) {
|
|
332
|
-
|
|
333
|
-
this.uploadProgress.set(percentDone);
|
|
334
|
-
console.log(`Upload Progress: ${percentDone}%`);
|
|
343
|
+
this.uploadProgress.set(Math.round((100 * event.loaded) / event.total));
|
|
335
344
|
}
|
|
345
|
+
return;
|
|
336
346
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
this.handleUploadDone({ ...event.body?.data, size: file.size });
|
|
340
|
-
console.log('Upload Complete', event.body);
|
|
341
|
-
}
|
|
347
|
+
this.uploadProgress.set(100);
|
|
348
|
+
this.handleUploadDone({ ...event.body?.data, size: file.size });
|
|
342
349
|
});
|
|
343
350
|
}
|
|
344
351
|
handleUploadDone(file) {
|
|
345
|
-
if (file) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
352
|
+
if (!file) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
this.onAdd(file);
|
|
356
|
+
if (this.fileSizeLimit() && file.size > this.fileSizeLimit()) {
|
|
357
|
+
this.ngControl.control?.setErrors({ fileSizeLimited: true });
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
if (this.pendingUploads() <= 1) {
|
|
361
|
+
this.ngControl.control?.setErrors(null);
|
|
354
362
|
}
|
|
355
|
-
console.log('handleUploadDone', this.value());
|
|
356
363
|
}
|
|
357
364
|
downloadFile(value) {
|
|
365
|
+
const downloadUrl = this.resolveImgPath(value);
|
|
358
366
|
const downloadFileName = value?.name;
|
|
359
367
|
const mimeType = value?.contentType;
|
|
360
|
-
|
|
361
|
-
if (!storedFileName || !mimeType || !downloadFileName) {
|
|
368
|
+
if (!downloadUrl || !mimeType || !downloadFileName) {
|
|
362
369
|
console.error('File metadata is incomplete. Cannot download.');
|
|
363
370
|
return;
|
|
364
371
|
}
|
|
365
372
|
this.httpClient
|
|
366
|
-
.get(
|
|
373
|
+
.get(downloadUrl, {
|
|
367
374
|
responseType: 'blob',
|
|
368
375
|
context: this.context(),
|
|
369
376
|
})
|
|
@@ -397,18 +404,52 @@ class UploadField {
|
|
|
397
404
|
if (this.disabled()) {
|
|
398
405
|
return;
|
|
399
406
|
}
|
|
400
|
-
const files = event.dataTransfer?.files;
|
|
401
|
-
if (files
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
407
|
+
const files = Array.from(event.dataTransfer?.files ?? []);
|
|
408
|
+
if (!files.length) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (!this.multiple()) {
|
|
412
|
+
this.value.set(null);
|
|
413
|
+
}
|
|
414
|
+
this.prepareFiles(files);
|
|
415
|
+
}
|
|
416
|
+
resolveImgPath(value) {
|
|
417
|
+
return value?.fileName ? `${this.endPoint()}/${value.fileName}` : undefined;
|
|
418
|
+
}
|
|
419
|
+
fetchMetadata(fileIds, existingFiles = [], forceArray = false) {
|
|
420
|
+
const normalizedIds = fileIds
|
|
421
|
+
.map((fileId) => fileId.trim())
|
|
422
|
+
.filter((fileId) => fileId.length > 0);
|
|
423
|
+
if (!normalizedIds.length) {
|
|
424
|
+
this.value.set(forceArray ? existingFiles : existingFiles[0] ?? null);
|
|
425
|
+
return;
|
|
408
426
|
}
|
|
427
|
+
this.loading.set(true);
|
|
428
|
+
forkJoin(normalizedIds.map((fileId) => this.httpClient
|
|
429
|
+
.get(`${this.endPoint()}/${fileId}/metaData`, {
|
|
430
|
+
context: this.context(),
|
|
431
|
+
})
|
|
432
|
+
.pipe(take(1), map$1((response) => response.data), catchError$1((error) => {
|
|
433
|
+
console.error('Failed to fetch file metadata:', error);
|
|
434
|
+
return of({
|
|
435
|
+
id: fileId,
|
|
436
|
+
name: fileId,
|
|
437
|
+
fileName: fileId,
|
|
438
|
+
contentType: '',
|
|
439
|
+
extension: '',
|
|
440
|
+
});
|
|
441
|
+
}))))
|
|
442
|
+
.pipe(finalize$1(() => this.loading.set(false)))
|
|
443
|
+
.subscribe((files) => {
|
|
444
|
+
const resolvedFiles = [...existingFiles, ...files];
|
|
445
|
+
const resolvedValue = forceArray || this.multiple() || resolvedFiles.length > 1
|
|
446
|
+
? resolvedFiles
|
|
447
|
+
: resolvedFiles[0] ?? null;
|
|
448
|
+
this.value.set(resolvedValue);
|
|
449
|
+
});
|
|
409
450
|
}
|
|
410
451
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UploadField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
411
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UploadField, isStandalone: true, selector: "mt-upload-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, endPoint: { classPropertyName: "endPoint", publicName: "endPoint", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, userImgClass: { classPropertyName: "userImgClass", publicName: "userImgClass", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, isDragging: { classPropertyName: "isDragging", publicName: "isDragging", isSignal: true, isRequired: false, transformFunction: null }, fileSizeLimit: { classPropertyName: "fileSizeLimit", publicName: "fileSizeLimit", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isDragging: "isDraggingChange", onChange: "onChange" }, ngImport: i0, template: "<input\
|
|
452
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: UploadField, isStandalone: true, selector: "mt-upload-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, endPoint: { classPropertyName: "endPoint", publicName: "endPoint", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, userImgClass: { classPropertyName: "userImgClass", publicName: "userImgClass", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, isDragging: { classPropertyName: "isDragging", publicName: "isDragging", isSignal: true, isRequired: false, transformFunction: null }, fileSizeLimit: { classPropertyName: "fileSizeLimit", publicName: "fileSizeLimit", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isDragging: "isDraggingChange", onChange: "onChange" }, ngImport: i0, template: "<input\n #uploadInput\n type=\"file\"\n name=\"file[]\"\n (change)=\"onFileSelect($event)\"\n style=\"display: none\"\n [multiple]=\"multiple()\"\n [accept]=\"shape() === 'circle' ? 'image/*' : accept()\"\n/>\n\n@if (shape() === \"circle\") {\n <div class=\"flex flex-col items-center gap-2 w-full\">\n <div class=\"flex\">\n <div class=\"flex flex-col items-center\">\n <mt-upload-user-preview\n [value]=\"primaryFile()\"\n [imgPath]=\"imgPath()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [size]=\"size()\"\n [context]=\"context()\"\n [userImgClass]=\"userImgClass()\"\n [isDragging]=\"isDragging()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile($event)\"\n (onDeleteFile)=\"onDelete(primaryFile())\"\n (onDragOver)=\"onDragOver($event)\"\n (onDragLeave)=\"onDragLeave($event)\"\n (onDrop)=\"onDrop($event)\"\n ></mt-upload-user-preview>\n @if (label()) {\n <label\n [class.required]=\"\n ngControl?.control?.hasValidator(requiredValidator)\n \"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n </div>\n </div>\n </div>\n} @else if (shape() === \"card\") {\n <mt-card\n headless\n class=\"border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n >\n <div class=\"content flex flex-col gap-5 items-center text-center\">\n @if (!files().length && !loading()) {\n <div class=\"flex flex-col gap-1\">\n @if (title()) {\n <div class=\"title text-lg font-semibold\">\n {{ title() }}\n </div>\n }\n @if (description()) {\n <div\n class=\"description text-sm text-muted-foreground secondary text-surface-500\"\n >\n {{ description() }}\n </div>\n }\n </div>\n }\n\n @if (files().length) {\n <div class=\"flex w-full flex-col gap-2\">\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <mt-button\n [size]=\"'small'\"\n [label]=\"'components.upload.upload' | transloco\"\n [icon]=\"'general.upload-01'\"\n (onClick)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [disabled]=\"disabled() || loading() || readonly()\"\n />\n }\n </div>\n </mt-card>\n} @else {\n <div class=\"flex flex-col items-start gap-2 w-full\">\n @if (label()) {\n <label\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n\n <div\n class=\"w-full flex gap-3 items-center justify-center border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n [class]=\"disabled() ? 'bg-gray-50' : ''\"\n (click)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [class.border-blue-500]=\"isDragging()\"\n [class.bg-blue-50]=\"isDragging()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n @if (files().length) {\n <div class=\"flex w-full flex-col gap-2 p-2\">\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <mt-icon icon=\"general.upload-01\" />\n <p class=\"text-lg text-gray-500\">\n {{ \"components.upload.clickOrDrop\" | transloco }}\n </p>\n </div>\n }\n </div>\n </div>\n}\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\n", dependencies: [{ kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: UploadUserPreview, selector: "mt-upload-user-preview", inputs: ["value", "imgPath", "context", "loading", "uploadProgress", "isDragging", "disabled", "readonly", "size", "userImgClass"], outputs: ["onUploadInputClicked", "ondDownloadFile", "onDeleteFile", "onDragOver", "onDragLeave", "onDrop", "disabledChange"] }, { kind: "component", type: UploadFilePreview, selector: "mt-upload-file-preview", inputs: ["value", "imgPath", "context", "loading", "uploadProgress", "disabled", "readonly", "size"], outputs: ["onUploadInputClicked", "ondDownloadFile", "onDeleteFile", "disabledChange"] }, { kind: "component", type: FieldValidation, selector: "mt-field-validation", inputs: ["control", "touched"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i1.TranslocoPipe, name: "transloco" }] });
|
|
412
453
|
}
|
|
413
454
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: UploadField, decorators: [{
|
|
414
455
|
type: Component,
|
|
@@ -420,8 +461,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
420
461
|
Card,
|
|
421
462
|
Button,
|
|
422
463
|
TranslocoModule,
|
|
423
|
-
], template: "<input\
|
|
424
|
-
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], endPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "endPoint", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], userImgClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "userImgClass", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], isDragging: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDragging", required: false }] }, { type: i0.Output, args: ["isDraggingChange"] }], fileSizeLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSizeLimit", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], onChange: [{ type: i0.Output, args: ["onChange"] }] } });
|
|
464
|
+
], template: "<input\n #uploadInput\n type=\"file\"\n name=\"file[]\"\n (change)=\"onFileSelect($event)\"\n style=\"display: none\"\n [multiple]=\"multiple()\"\n [accept]=\"shape() === 'circle' ? 'image/*' : accept()\"\n/>\n\n@if (shape() === \"circle\") {\n <div class=\"flex flex-col items-center gap-2 w-full\">\n <div class=\"flex\">\n <div class=\"flex flex-col items-center\">\n <mt-upload-user-preview\n [value]=\"primaryFile()\"\n [imgPath]=\"imgPath()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [size]=\"size()\"\n [context]=\"context()\"\n [userImgClass]=\"userImgClass()\"\n [isDragging]=\"isDragging()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile($event)\"\n (onDeleteFile)=\"onDelete(primaryFile())\"\n (onDragOver)=\"onDragOver($event)\"\n (onDragLeave)=\"onDragLeave($event)\"\n (onDrop)=\"onDrop($event)\"\n ></mt-upload-user-preview>\n @if (label()) {\n <label\n [class.required]=\"\n ngControl?.control?.hasValidator(requiredValidator)\n \"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n </div>\n </div>\n </div>\n} @else if (shape() === \"card\") {\n <mt-card\n headless\n class=\"border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n >\n <div class=\"content flex flex-col gap-5 items-center text-center\">\n @if (!files().length && !loading()) {\n <div class=\"flex flex-col gap-1\">\n @if (title()) {\n <div class=\"title text-lg font-semibold\">\n {{ title() }}\n </div>\n }\n @if (description()) {\n <div\n class=\"description text-sm text-muted-foreground secondary text-surface-500\"\n >\n {{ description() }}\n </div>\n }\n </div>\n }\n\n @if (files().length) {\n <div class=\"flex w-full flex-col gap-2\">\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <mt-button\n [size]=\"'small'\"\n [label]=\"'components.upload.upload' | transloco\"\n [icon]=\"'general.upload-01'\"\n (onClick)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [disabled]=\"disabled() || loading() || readonly()\"\n />\n }\n </div>\n </mt-card>\n} @else {\n <div class=\"flex flex-col items-start gap-2 w-full\">\n @if (label()) {\n <label\n [class.required]=\"ngControl?.control?.hasValidator(requiredValidator)\"\n [for]=\"ngControl?.name || label()\"\n >{{ label() }}</label\n >\n }\n\n <div\n class=\"w-full flex gap-3 items-center justify-center border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-50\"\n [class]=\"disabled() ? 'bg-gray-50' : ''\"\n (click)=\"\n !loading() && !disabled() && !readonly() ? uploadInput.click() : ''\n \"\n [class.border-blue-500]=\"isDragging()\"\n [class.bg-blue-50]=\"isDragging()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n >\n @if (files().length) {\n <div class=\"flex w-full flex-col gap-2 p-2\">\n @for (file of files(); track $index) {\n <mt-upload-file-preview\n style=\"width: 100%\"\n [value]=\"file\"\n [imgPath]=\"resolveImgPath(file)\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n [loading]=\"loading()\"\n [context]=\"context()\"\n [uploadProgress]=\"uploadProgress()\"\n (onUploadInputClicked)=\"uploadInput.click()\"\n (ondDownloadFile)=\"downloadFile(file)\"\n (onDeleteFile)=\"onDelete(file)\"\n />\n }\n </div>\n } @else if (loading()) {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <p class=\"text-lg text-gray-500\">\n {{\n (\"components.upload.uploading\" | transloco) +\n uploadProgress() +\n \"%\"\n }}\n </p>\n </div>\n } @else {\n <div class=\"w-full flex gap-3 items-center justify-center p-3\">\n <mt-icon icon=\"general.upload-01\" />\n <p class=\"text-lg text-gray-500\">\n {{ \"components.upload.clickOrDrop\" | transloco }}\n </p>\n </div>\n }\n </div>\n </div>\n}\n<mt-field-validation [control]=\"ngControl?.control\"></mt-field-validation>\n" }]
|
|
465
|
+
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], endPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "endPoint", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], userImgClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "userImgClass", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], isDragging: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDragging", required: false }] }, { type: i0.Output, args: ["isDraggingChange"] }], fileSizeLimit: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileSizeLimit", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], onChange: [{ type: i0.Output, args: ["onChange"] }] } });
|
|
466
|
+
function isSameFile(source, target) {
|
|
467
|
+
if (!source || !target) {
|
|
468
|
+
return source === target;
|
|
469
|
+
}
|
|
470
|
+
return (source === target ||
|
|
471
|
+
(source.id && target.id && source.id === target.id) ||
|
|
472
|
+
(source.fileName &&
|
|
473
|
+
target.fileName &&
|
|
474
|
+
source.fileName === target.fileName));
|
|
475
|
+
}
|
|
425
476
|
|
|
426
477
|
/**
|
|
427
478
|
* Generated bundle index. Do not edit.
|