@bnsights/bbsf-controls 1.0.175 → 1.0.177
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 +6 -1
- package/esm2022/lib/Shared/Models/FileDTO.mjs +2 -1
- package/esm2022/lib/controls/FileUpload/FileUpload.component.mjs +1048 -0
- package/esm2022/lib/controls/Repeater/repeater-field-builder/repeater-field-builder.component.mjs +2 -2
- package/esm2022/lib/controls/bbsf-controls.module.mjs +5 -3
- package/esm2022/public-api.mjs +2 -2
- package/fesm2022/bnsights-bbsf-controls.mjs +909 -446
- package/fesm2022/bnsights-bbsf-controls.mjs.map +1 -1
- package/lib/Shared/Models/FileDTO.d.ts +1 -0
- package/lib/controls/FileUpload/FileUpload.component.d.ts +162 -0
- package/lib/controls/bbsf-controls.module.d.ts +1 -1
- package/package.json +2 -2
- package/public-api.d.ts +1 -1
- package/esm2022/lib/controls/FileUplaod/FileUplaod.component.mjs +0 -588
- package/lib/controls/FileUplaod/FileUplaod.component.d.ts +0 -62
|
@@ -27,7 +27,7 @@ import * as i2$1 from 'ngx-toastr';
|
|
|
27
27
|
import { ToastrModule } from 'ngx-toastr';
|
|
28
28
|
import { OverlayModule } from '@angular/cdk/overlay';
|
|
29
29
|
import * as i5 from '@angular/common';
|
|
30
|
-
import { CommonModule, DatePipe } from '@angular/common';
|
|
30
|
+
import { CommonModule, DatePipe, KeyValuePipe } from '@angular/common';
|
|
31
31
|
import * as i1 from '@angular/common/http';
|
|
32
32
|
import { HttpHeaders, HttpParams, HttpEventType, HttpClientModule } from '@angular/common/http';
|
|
33
33
|
import * as i0 from '@angular/core';
|
|
@@ -52,7 +52,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|
|
52
52
|
import { SweetAlert2Module } from '@sweetalert2/ngx-sweetalert2';
|
|
53
53
|
import * as i3 from '@bnsights/bbsf-utilities';
|
|
54
54
|
import { RequestOptionsModel, environment as environment$1, BBSFUtilitiesModule, UtilityService, ConfigurationService, EnvironmentService, AuthService } from '@bnsights/bbsf-utilities';
|
|
55
|
-
import { Subject, Observable, noop as noop$1, of,
|
|
55
|
+
import { Subject, Observable, noop as noop$1, of, Subscription, EMPTY, switchMap as switchMap$1 } from 'rxjs';
|
|
56
56
|
import { switchMap, map, tap } from 'rxjs/operators';
|
|
57
57
|
import * as i6 from '@angular/cdk/bidi';
|
|
58
58
|
import dayGridPlugin from '@fullcalendar/daygrid';
|
|
@@ -2107,563 +2107,1023 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
2107
2107
|
}], ctorParameters: () => [{ type: i3.RequestHandlerService }] });
|
|
2108
2108
|
|
|
2109
2109
|
class FileUploadComponent {
|
|
2110
|
-
static { this.
|
|
2111
|
-
constructor(controlContainer,
|
|
2110
|
+
static { this.controlContainerStatic = null; }
|
|
2111
|
+
constructor(controlContainer, multipleFileUploadControlHost, controlUtility, utilityService, controlValidationService, globalSettings, fileUploadService) {
|
|
2112
2112
|
this.controlContainer = controlContainer;
|
|
2113
|
-
this.
|
|
2113
|
+
this.multipleFileUploadControlHost = multipleFileUploadControlHost;
|
|
2114
2114
|
this.controlUtility = controlUtility;
|
|
2115
|
-
this.
|
|
2115
|
+
this.utilityService = utilityService;
|
|
2116
2116
|
this.controlValidationService = controlValidationService;
|
|
2117
2117
|
this.globalSettings = globalSettings;
|
|
2118
2118
|
this.fileUploadService = fileUploadService;
|
|
2119
|
+
this.BYTES_TO_MB = 1024 * 1024;
|
|
2120
|
+
this.PROGRESS_COMPLETE = 100;
|
|
2121
|
+
this.PROGRESS_NEAR_COMPLETE = 95;
|
|
2122
|
+
this.ERROR_DISPLAY_DURATION = 5000;
|
|
2123
|
+
this.MAX_MEMORY_USAGE = 100 * 1024 * 1024; // 100MB limit
|
|
2124
|
+
this.currentMemoryUsage = 0;
|
|
2125
|
+
this.isSubmitted = false;
|
|
2119
2126
|
this.OnChange = new EventEmitter();
|
|
2120
2127
|
this.isUploadComplete = new EventEmitter();
|
|
2121
2128
|
this.validationMessage = '';
|
|
2122
2129
|
this.validationCountMessage = '';
|
|
2130
|
+
this.hasAnotherDropZoneOver = false;
|
|
2123
2131
|
this.acceptedType = '';
|
|
2124
2132
|
this.acceptedTypeArray = [];
|
|
2125
2133
|
this.toolTipTypeArray = [];
|
|
2126
2134
|
this.markAllAsTouched = false;
|
|
2127
2135
|
this.validationRules = [];
|
|
2128
|
-
this.
|
|
2136
|
+
this.validationRulesAsync = [];
|
|
2137
|
+
this.file = null;
|
|
2129
2138
|
this.deletedFiles = [];
|
|
2139
|
+
this.subscriptions = new Subscription();
|
|
2130
2140
|
this.resetError = () => {
|
|
2131
2141
|
this.controlValidationService.removeGlobalError();
|
|
2132
2142
|
};
|
|
2133
|
-
//External Method
|
|
2134
2143
|
this.removeRequiredValidation = () => {
|
|
2135
2144
|
this.controlUtility.removeRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
|
|
2136
2145
|
};
|
|
2137
|
-
//External Method
|
|
2138
2146
|
this.addRequiredValidation = () => {
|
|
2139
2147
|
this.controlUtility.addRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
|
|
2140
2148
|
};
|
|
2141
|
-
//External Method
|
|
2142
2149
|
this.removeCustomValidation = (customValidation) => {
|
|
2143
2150
|
this.controlUtility.removeCustomValidation(this.fileUploadFormControl, this.validationRules, customValidation);
|
|
2144
2151
|
};
|
|
2145
|
-
//External Method
|
|
2146
2152
|
this.addCustomValidation = (customValidation) => {
|
|
2147
2153
|
this.controlUtility.addCustomValidation(this.fileUploadFormControl, this.validationRules, customValidation);
|
|
2148
2154
|
};
|
|
2149
|
-
//External Method
|
|
2150
2155
|
this.isValid = () => {
|
|
2151
2156
|
this.controlUtility.isValid(this.fileUploadFormControl);
|
|
2157
|
+
return this.fileUploadFormControl.valid;
|
|
2152
2158
|
};
|
|
2153
|
-
FileUploadComponent.
|
|
2159
|
+
FileUploadComponent.controlContainerStatic = this.controlContainer;
|
|
2160
|
+
this.initializeUploader();
|
|
2161
|
+
}
|
|
2162
|
+
initializeUploader() {
|
|
2154
2163
|
this.uploader = new FileUploader({
|
|
2155
|
-
disableMultipart: false
|
|
2164
|
+
disableMultipart: false
|
|
2156
2165
|
});
|
|
2157
|
-
this.hasAnotherDropZoneOver = false;
|
|
2158
2166
|
}
|
|
2159
2167
|
ngOnInit() {
|
|
2168
|
+
this.initializeModels();
|
|
2169
|
+
this.setViewType();
|
|
2170
|
+
this.processInitialValue();
|
|
2171
|
+
this.setupLabels();
|
|
2172
|
+
this.setupFileTypeValidation();
|
|
2173
|
+
this.setupFormControl();
|
|
2174
|
+
this.setupSubscriptions();
|
|
2175
|
+
}
|
|
2176
|
+
initializeModels() {
|
|
2160
2177
|
this.fileUploadModel = new FileUploadModel();
|
|
2161
2178
|
this.multipleFileUploadModel = new MultipleFileUploadModel();
|
|
2162
|
-
|
|
2179
|
+
}
|
|
2180
|
+
setViewType() {
|
|
2181
|
+
if (!this.options.viewType) {
|
|
2163
2182
|
this.options.viewType = this.globalSettings.viewType;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
processInitialValue() {
|
|
2164
2186
|
if (this.options.value == null) {
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
// this.options.Value=this.fileUploadModel
|
|
2170
|
-
}
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
if (this.options.isMultipleFile) {
|
|
2190
|
+
this.processMultipleFileValue();
|
|
2171
2191
|
}
|
|
2172
2192
|
else {
|
|
2173
|
-
|
|
2174
|
-
let files = [];
|
|
2175
|
-
this.multipleFileUploadModel.existingFiles = this.options.value.existingFiles;
|
|
2176
|
-
this.multipleFileUploadModel.uploadedFiles = [];
|
|
2177
|
-
for (let index = 0; index < this.options.value.existingFiles.length; index++) {
|
|
2178
|
-
const element = this.options.value.existingFiles[index];
|
|
2179
|
-
var bytes = new Uint8Array(element.bytes);
|
|
2180
|
-
var base64 = btoa(String.fromCharCode(null, bytes));
|
|
2181
|
-
this.fileLikeObject = {
|
|
2182
|
-
name: element.nameWithExtension,
|
|
2183
|
-
type: element.mimeType,
|
|
2184
|
-
rawFile: base64
|
|
2185
|
-
};
|
|
2186
|
-
// let blob: any;
|
|
2187
|
-
// blob = new Blob(['']) as any;
|
|
2188
|
-
// blob.name = element.FileName;
|
|
2189
|
-
// blob.lastModifiedDate = null;
|
|
2190
|
-
// blob.webkitRelativePath = '';
|
|
2191
|
-
let file = this.fileLikeObject;
|
|
2192
|
-
file.url = element.fileURL;
|
|
2193
|
-
files.push(file);
|
|
2194
|
-
}
|
|
2195
|
-
this.uploader.addToQueue(files);
|
|
2196
|
-
console.log(this.uploader.queue);
|
|
2197
|
-
}
|
|
2198
|
-
else {
|
|
2199
|
-
const element = this.options.value.file ?? this.options.value;
|
|
2200
|
-
var bytes = new Uint8Array(element.bytes);
|
|
2201
|
-
var base64 = btoa(String.fromCharCode(null, bytes));
|
|
2202
|
-
this.fileLikeObject = {
|
|
2203
|
-
name: element.nameWithExtension,
|
|
2204
|
-
type: element.mimeType,
|
|
2205
|
-
rawFile: base64
|
|
2206
|
-
};
|
|
2207
|
-
this.file = element;
|
|
2208
|
-
let file = this.fileLikeObject;
|
|
2209
|
-
file.url = element.fileURL;
|
|
2210
|
-
this.uploader.addToQueue([file]);
|
|
2211
|
-
if (!this.options.value.file) {
|
|
2212
|
-
this.fileUploadModel = new FileUploadModel();
|
|
2213
|
-
this.fileUploadModel.file = this.options.value;
|
|
2214
|
-
}
|
|
2215
|
-
else
|
|
2216
|
-
this.fileUploadModel = this.options.value;
|
|
2217
|
-
this.options.value = this.fileUploadModel;
|
|
2218
|
-
}
|
|
2219
|
-
this.uploader.queue.forEach((element) => {
|
|
2220
|
-
element.progress = 100;
|
|
2221
|
-
});
|
|
2193
|
+
this.processSingleFileValue();
|
|
2222
2194
|
}
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
case 'application/x-rar-compressed':
|
|
2283
|
-
if (!this.toolTipTypeArray.includes('RAR'))
|
|
2284
|
-
this.toolTipTypeArray.push('RAR');
|
|
2285
|
-
break;
|
|
2286
|
-
case 'video/mp4':
|
|
2287
|
-
if (!this.toolTipTypeArray.includes('MP4'))
|
|
2288
|
-
this.toolTipTypeArray.push('MP4');
|
|
2289
|
-
break;
|
|
2290
|
-
case 'video/avi':
|
|
2291
|
-
if (!this.toolTipTypeArray.includes('AVI'))
|
|
2292
|
-
this.toolTipTypeArray.push('AVI');
|
|
2293
|
-
break;
|
|
2294
|
-
case 'video/quicktime':
|
|
2295
|
-
if (!this.toolTipTypeArray.includes('MOV'))
|
|
2296
|
-
this.toolTipTypeArray.push('MOV');
|
|
2297
|
-
break;
|
|
2298
|
-
case 'video/mpeg':
|
|
2299
|
-
if (!this.toolTipTypeArray.includes('MPEG'))
|
|
2300
|
-
this.toolTipTypeArray.push('MPEG');
|
|
2301
|
-
break;
|
|
2302
|
-
case 'audio/mpeg':
|
|
2303
|
-
if (!this.toolTipTypeArray.includes('MP3'))
|
|
2304
|
-
this.toolTipTypeArray.push('MP3');
|
|
2305
|
-
break;
|
|
2306
|
-
case 'video/x-flv':
|
|
2307
|
-
if (!this.toolTipTypeArray.includes('FLV'))
|
|
2308
|
-
this.toolTipTypeArray.push('FLV');
|
|
2309
|
-
break;
|
|
2310
|
-
case 'video/x-ms-wmv':
|
|
2311
|
-
if (!this.toolTipTypeArray.includes('WMV'))
|
|
2312
|
-
this.toolTipTypeArray.push('WMV');
|
|
2313
|
-
break;
|
|
2314
|
-
case 'image/svg+xml':
|
|
2315
|
-
if (!this.toolTipTypeArray.includes('SVG'))
|
|
2316
|
-
this.toolTipTypeArray.push('SVG');
|
|
2317
|
-
break;
|
|
2318
|
-
case 'text/plain':
|
|
2319
|
-
if (!this.toolTipTypeArray.includes('Txt'))
|
|
2320
|
-
this.toolTipTypeArray.push('Txt');
|
|
2321
|
-
break;
|
|
2322
|
-
case 'application/BN':
|
|
2323
|
-
if (!this.toolTipTypeArray.includes('License'))
|
|
2324
|
-
this.toolTipTypeArray.push('License');
|
|
2325
|
-
break;
|
|
2326
|
-
default:
|
|
2327
|
-
break;
|
|
2328
|
-
}
|
|
2329
|
-
}
|
|
2195
|
+
this.uploader.queue.forEach((element) => {
|
|
2196
|
+
element.progress = this.PROGRESS_COMPLETE;
|
|
2197
|
+
});
|
|
2198
|
+
}
|
|
2199
|
+
processMultipleFileValue() {
|
|
2200
|
+
const files = [];
|
|
2201
|
+
this.multipleFileUploadModel.existingFiles = this.options.value.existingFiles;
|
|
2202
|
+
this.multipleFileUploadModel.uploadedFiles = [];
|
|
2203
|
+
for (const element of this.options.value.existingFiles) {
|
|
2204
|
+
const fileLikeObject = this.createFileLikeObject(element);
|
|
2205
|
+
files.push(fileLikeObject);
|
|
2206
|
+
}
|
|
2207
|
+
this.uploader.addToQueue(files);
|
|
2208
|
+
}
|
|
2209
|
+
processSingleFileValue() {
|
|
2210
|
+
const element = this.options.value.file ?? this.options.value;
|
|
2211
|
+
const fileLikeObject = this.createFileLikeObject(element);
|
|
2212
|
+
this.file = element;
|
|
2213
|
+
this.uploader.addToQueue([fileLikeObject]);
|
|
2214
|
+
if (!this.options.value.file) {
|
|
2215
|
+
this.fileUploadModel = new FileUploadModel();
|
|
2216
|
+
this.fileUploadModel.file = this.options.value;
|
|
2217
|
+
}
|
|
2218
|
+
else {
|
|
2219
|
+
this.fileUploadModel = this.options.value;
|
|
2220
|
+
}
|
|
2221
|
+
this.options.value = this.fileUploadModel;
|
|
2222
|
+
}
|
|
2223
|
+
createFileLikeObject(element) {
|
|
2224
|
+
const bytes = new Uint8Array(element.bytes);
|
|
2225
|
+
const base64 = btoa(String.fromCharCode(...bytes));
|
|
2226
|
+
return {
|
|
2227
|
+
name: element.nameWithExtension || element.fileName,
|
|
2228
|
+
type: element.mimeType || element.fileType,
|
|
2229
|
+
rawFile: base64,
|
|
2230
|
+
size: element.fileSizeInMB ? element.fileSizeInMB * this.BYTES_TO_MB : 0,
|
|
2231
|
+
lastModifiedDate: new Date(),
|
|
2232
|
+
url: element.fullFileURL
|
|
2233
|
+
};
|
|
2234
|
+
}
|
|
2235
|
+
setupLabels() {
|
|
2236
|
+
if (this.options.labelKey) {
|
|
2237
|
+
this.options.labelValue = this.utilityService.getResourceValue(this.options.labelKey);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
setupFileTypeValidation() {
|
|
2241
|
+
if (this.options.fileUploadAcceptsTypes?.length) {
|
|
2242
|
+
this.processAcceptedTypes();
|
|
2243
|
+
this.buildValidationMessage();
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
processAcceptedTypes() {
|
|
2247
|
+
this.acceptedType = this.options.fileUploadAcceptsTypes.join(',');
|
|
2248
|
+
this.acceptedTypeArray = this.options.fileUploadAcceptsTypes.filter(type => type.trim());
|
|
2249
|
+
const mimeTypeMap = this.getMimeTypeMap();
|
|
2250
|
+
for (const type of this.acceptedTypeArray) {
|
|
2251
|
+
const displayType = mimeTypeMap[type];
|
|
2252
|
+
if (displayType && !this.toolTipTypeArray.includes(displayType)) {
|
|
2253
|
+
this.toolTipTypeArray.push(displayType);
|
|
2330
2254
|
}
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
getMimeTypeMap() {
|
|
2258
|
+
return {
|
|
2259
|
+
'application/pdf': 'PDF',
|
|
2260
|
+
'application/msword': 'Word',
|
|
2261
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word',
|
|
2262
|
+
'application/vnd.ms-excel': 'Excel',
|
|
2263
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'Excel',
|
|
2264
|
+
'application/vnd.ms-powerpoint': 'PowerPoint',
|
|
2265
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'PowerPoint',
|
|
2266
|
+
'image/png': 'PNG',
|
|
2267
|
+
'image/bmp': 'BMP',
|
|
2268
|
+
'image/jpeg': 'JPEG',
|
|
2269
|
+
'application/zip': 'ZIP',
|
|
2270
|
+
'application/x-rar-compressed': 'RAR',
|
|
2271
|
+
'video/mp4': 'MP4',
|
|
2272
|
+
'video/avi': 'AVI',
|
|
2273
|
+
'video/quicktime': 'MOV',
|
|
2274
|
+
'video/mpeg': 'MPEG',
|
|
2275
|
+
'audio/mpeg': 'MP3',
|
|
2276
|
+
'video/x-flv': 'FLV',
|
|
2277
|
+
'video/x-ms-wmv': 'WMV',
|
|
2278
|
+
'image/svg+xml': 'SVG',
|
|
2279
|
+
'text/plain': 'Txt',
|
|
2280
|
+
'application/BN': 'License'
|
|
2281
|
+
};
|
|
2282
|
+
}
|
|
2283
|
+
buildValidationMessage() {
|
|
2284
|
+
const messages = [];
|
|
2285
|
+
if (this.toolTipTypeArray.length) {
|
|
2286
|
+
messages.push(`${this.utilityService.getResourceValue('Extensions')} (${this.toolTipTypeArray.join(', ')})`);
|
|
2334
2287
|
}
|
|
2335
2288
|
if (this.options.fileMaxSizeInMB > 0) {
|
|
2336
|
-
this.
|
|
2337
|
-
this.validationMessage +
|
|
2338
|
-
`<br /> ${this.UtilityService.getResourceValue('FileMaxSizeInMB') + this.options.fileMaxSizeInMB} `;
|
|
2289
|
+
messages.push(`${this.utilityService.getResourceValue('FileMaxSizeInMB')}${this.options.fileMaxSizeInMB}`);
|
|
2339
2290
|
}
|
|
2340
2291
|
if (this.options.minNoOfFiles > 0) {
|
|
2341
|
-
this.
|
|
2342
|
-
this.validationMessage +
|
|
2343
|
-
`<br /> ${this.UtilityService.getResourceValue('MinFileCountValidationKey') + this.options.minNoOfFiles}`;
|
|
2292
|
+
messages.push(`${this.utilityService.getResourceValue('MinFileCountValidationKey')}${this.options.minNoOfFiles}`);
|
|
2344
2293
|
}
|
|
2345
2294
|
if (this.options.maxNoOfFiles > 0) {
|
|
2346
|
-
this.
|
|
2347
|
-
this.validationMessage +
|
|
2348
|
-
`<br /> ${this.UtilityService.getResourceValue('MaxFileCountValidationKey') + this.options.maxNoOfFiles}`;
|
|
2349
|
-
}
|
|
2350
|
-
if (this.options.fileUploadAcceptsTypes != null &&
|
|
2351
|
-
this.options.fileUploadAcceptsTypes.length > 0) {
|
|
2295
|
+
messages.push(`${this.utilityService.getResourceValue('MaxFileCountValidationKey')}${this.options.maxNoOfFiles}`);
|
|
2352
2296
|
}
|
|
2297
|
+
this.validationMessage = messages.join('<br/>');
|
|
2298
|
+
}
|
|
2299
|
+
setupFormControl() {
|
|
2353
2300
|
this.group.addControl(this.options.name, new FormControl(''));
|
|
2354
|
-
this.fileUploadFormControl = this.group.controls[this.options.name];
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2301
|
+
this.fileUploadFormControl = this.group.controls[this.options.name];
|
|
2302
|
+
this.setupValidators();
|
|
2303
|
+
this.setupCountMessage();
|
|
2304
|
+
this.applyValidatorsAndState();
|
|
2305
|
+
this.fileUploadFormControl.setValue(this.options.value, { emitEvent: false });
|
|
2306
|
+
}
|
|
2307
|
+
setupValidators() {
|
|
2308
|
+
if (this.options.customValidation?.length) {
|
|
2309
|
+
for (const validation of this.options.customValidation) {
|
|
2310
|
+
this.validationRules.push(validation.functionBody);
|
|
2360
2311
|
}
|
|
2361
2312
|
}
|
|
2362
|
-
if (this.options.isMultipleFile && this.options.maxNoOfFiles > 0) {
|
|
2363
|
-
this.validationCountMessage = `${this.UtilityService.getResourceValue('MaxFilesCount')} : ${this.options.maxNoOfFiles}`;
|
|
2364
|
-
}
|
|
2365
2313
|
if (this.options.isRequired) {
|
|
2366
2314
|
this.validationRules.push(Validators.required);
|
|
2367
2315
|
}
|
|
2316
|
+
}
|
|
2317
|
+
setupCountMessage() {
|
|
2318
|
+
if (this.options.isMultipleFile && this.options.maxNoOfFiles > 0) {
|
|
2319
|
+
this.validationCountMessage = `${this.utilityService.getResourceValue('MaxFilesCount')} : ${this.options.maxNoOfFiles}`;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
applyValidatorsAndState() {
|
|
2368
2323
|
this.fileUploadFormControl.setValidators(this.validationRules);
|
|
2369
|
-
this.
|
|
2324
|
+
if (this.validationRulesAsync.length > 0) {
|
|
2325
|
+
this.fileUploadFormControl.setAsyncValidators(this.validationRulesAsync);
|
|
2326
|
+
}
|
|
2370
2327
|
if (this.options.isDisabled) {
|
|
2371
2328
|
this.fileUploadFormControl.disable();
|
|
2372
2329
|
}
|
|
2373
|
-
|
|
2330
|
+
}
|
|
2331
|
+
setupSubscriptions() {
|
|
2332
|
+
this.multipleFileUploadControlHost.ngSubmit.subscribe(() => {
|
|
2374
2333
|
this.group.markAllAsTouched();
|
|
2375
2334
|
this.markAllAsTouched = true;
|
|
2376
2335
|
});
|
|
2377
|
-
this.fileUploadFormControl.setValue(this.options.value);
|
|
2378
2336
|
}
|
|
2379
2337
|
ngAfterViewInit() {
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2338
|
+
this.applyAttributes();
|
|
2339
|
+
}
|
|
2340
|
+
applyAttributes() {
|
|
2341
|
+
if (!this.options.attributeList?.length) {
|
|
2342
|
+
return;
|
|
2343
|
+
}
|
|
2344
|
+
const element = document.getElementById(this.options.name);
|
|
2345
|
+
if (element) {
|
|
2346
|
+
for (const attribute of this.options.attributeList) {
|
|
2347
|
+
element.setAttribute(attribute.key, attribute.value);
|
|
2384
2348
|
}
|
|
2385
2349
|
}
|
|
2386
2350
|
}
|
|
2387
2351
|
showGlobalError() {
|
|
2388
2352
|
this.controlUtility.showGlobalError();
|
|
2389
2353
|
}
|
|
2390
|
-
getErrorValidation(
|
|
2354
|
+
getErrorValidation(errorList) {
|
|
2391
2355
|
if (this.markAllAsTouched && this.group.invalid) {
|
|
2392
2356
|
this.showGlobalError();
|
|
2393
2357
|
this.markAllAsTouched = false;
|
|
2394
2358
|
}
|
|
2395
|
-
|
|
2359
|
+
if (errorList && errorList.length > 0) {
|
|
2360
|
+
for (const error of errorList) {
|
|
2361
|
+
if (error.key === 'InvalidFiles') {
|
|
2362
|
+
return error.value;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
return this.controlUtility.getErrorValidationMassage(errorList, this.group, this.options);
|
|
2396
2367
|
}
|
|
2397
2368
|
fileOverAnother(event) {
|
|
2398
|
-
this.hasAnotherDropZoneOver = event;
|
|
2369
|
+
this.hasAnotherDropZoneOver = !!event;
|
|
2399
2370
|
}
|
|
2400
2371
|
isHideInput() {
|
|
2401
2372
|
if (this.options.isMultipleFile) {
|
|
2402
|
-
|
|
2403
|
-
this.options.maxNoOfFiles
|
|
2404
|
-
|
|
2405
|
-
|
|
2373
|
+
return this.options.maxNoOfFiles > 0 &&
|
|
2374
|
+
this.options.maxNoOfFiles === this.uploader.queue.length;
|
|
2375
|
+
}
|
|
2376
|
+
return this.uploader.queue.length > 0;
|
|
2377
|
+
}
|
|
2378
|
+
onFileChange() {
|
|
2379
|
+
this.validateFileConstraints();
|
|
2380
|
+
const fileProcessingResult = this.processNewlyAddedFiles();
|
|
2381
|
+
this.handleFileValidationResults(fileProcessingResult);
|
|
2382
|
+
this.processValidFilesForUpload();
|
|
2383
|
+
}
|
|
2384
|
+
processNewlyAddedFiles() {
|
|
2385
|
+
const addedQueue = this.getNewlyAddedFiles();
|
|
2386
|
+
const validationResult = this.validateFilesInQueue(addedQueue);
|
|
2387
|
+
return {
|
|
2388
|
+
validFiles: addedQueue.filter(file => !validationResult.invalidFiles.includes(file)),
|
|
2389
|
+
invalidFiles: validationResult.invalidFiles,
|
|
2390
|
+
errors: validationResult.errors
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
getNewlyAddedFiles() {
|
|
2394
|
+
return this.uploader.queue.filter((obj) => obj['some']?.lastModified != null);
|
|
2395
|
+
}
|
|
2396
|
+
validateFilesInQueue(fileQueue) {
|
|
2397
|
+
const validationErrors = [];
|
|
2398
|
+
const invalidFiles = [];
|
|
2399
|
+
const processedDuplicateNames = new Set();
|
|
2400
|
+
for (const element of fileQueue) {
|
|
2401
|
+
const file = element.file;
|
|
2402
|
+
if (!file)
|
|
2403
|
+
continue;
|
|
2404
|
+
const fileValidation = this.validateSingleFile(file, element, processedDuplicateNames);
|
|
2405
|
+
if (!fileValidation.isValid) {
|
|
2406
|
+
invalidFiles.push(element);
|
|
2407
|
+
validationErrors.push(...fileValidation.errors);
|
|
2406
2408
|
}
|
|
2407
2409
|
}
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2410
|
+
return {
|
|
2411
|
+
isValid: invalidFiles.length === 0,
|
|
2412
|
+
errors: validationErrors,
|
|
2413
|
+
invalidFiles
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
validateSingleFile(file, element, processedDuplicateNames) {
|
|
2417
|
+
const errors = [];
|
|
2418
|
+
const sizeValid = this.validateIndividualFileSize(file);
|
|
2419
|
+
const typeValid = this.validateIndividualFileType(file);
|
|
2420
|
+
const nameValid = this.validateDuplicateFileName(file, element);
|
|
2421
|
+
if (!sizeValid) {
|
|
2422
|
+
errors.push(this.createFileSizeErrorMessage(file.name));
|
|
2423
|
+
}
|
|
2424
|
+
if (!typeValid) {
|
|
2425
|
+
errors.push(this.createFileTypeErrorMessage(file.name));
|
|
2426
|
+
}
|
|
2427
|
+
if (!nameValid) {
|
|
2428
|
+
const duplicateError = this.createDuplicateFileErrorMessage(file.name, processedDuplicateNames);
|
|
2429
|
+
if (duplicateError) {
|
|
2430
|
+
errors.push(duplicateError);
|
|
2411
2431
|
}
|
|
2412
2432
|
}
|
|
2413
|
-
return
|
|
2433
|
+
return {
|
|
2434
|
+
isValid: sizeValid && typeValid && nameValid,
|
|
2435
|
+
errors,
|
|
2436
|
+
invalidFiles: []
|
|
2437
|
+
};
|
|
2414
2438
|
}
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
this.options.
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
return;
|
|
2439
|
+
createFileSizeErrorMessage(fileName) {
|
|
2440
|
+
return this.utilityService.getResourceValue('FileExceedsMaxSize')
|
|
2441
|
+
.replace('{fileName}', fileName)
|
|
2442
|
+
.replace('{maxSize}', this.options.fileMaxSizeInMB.toString());
|
|
2443
|
+
}
|
|
2444
|
+
createFileTypeErrorMessage(fileName) {
|
|
2445
|
+
return this.utilityService.getResourceValue('FileTypeNotAccepted')
|
|
2446
|
+
.replace('{fileName}', fileName);
|
|
2447
|
+
}
|
|
2448
|
+
createDuplicateFileErrorMessage(fileName, processedDuplicateNames) {
|
|
2449
|
+
const fileNameLower = fileName.toLowerCase();
|
|
2450
|
+
if (processedDuplicateNames.has(fileNameLower)) {
|
|
2451
|
+
return null;
|
|
2452
|
+
}
|
|
2453
|
+
processedDuplicateNames.add(fileNameLower);
|
|
2454
|
+
let duplicateErrorMsg = this.utilityService.getResourceValue('DuplicateFileName');
|
|
2455
|
+
if (!duplicateErrorMsg || duplicateErrorMsg === 'DuplicateFileName') {
|
|
2456
|
+
duplicateErrorMsg = `File '{fileName}' already exists. Please choose a different file or rename it.`;
|
|
2457
|
+
}
|
|
2458
|
+
return duplicateErrorMsg.replace('{fileName}', fileName);
|
|
2459
|
+
}
|
|
2460
|
+
handleFileValidationResults(result) {
|
|
2461
|
+
if (result.invalidFiles.length > 0) {
|
|
2462
|
+
this.removeInvalidFiles(result.invalidFiles);
|
|
2463
|
+
}
|
|
2464
|
+
if (result.errors.length > 0) {
|
|
2465
|
+
this.showValidationErrors(result.errors);
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
processValidFilesForUpload() {
|
|
2469
|
+
const filesArray = [];
|
|
2470
|
+
const validQueue = this.getNewlyAddedFiles();
|
|
2471
|
+
for (const element of validQueue) {
|
|
2472
|
+
const file = element.file;
|
|
2473
|
+
if (!file)
|
|
2474
|
+
continue;
|
|
2475
|
+
if (this.shouldUseAsyncUpload(element)) {
|
|
2476
|
+
this.handleAsyncFileUpload(element, filesArray);
|
|
2477
|
+
}
|
|
2478
|
+
else {
|
|
2479
|
+
this.handleSyncFileUpload(file, filesArray);
|
|
2480
|
+
}
|
|
2428
2481
|
}
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2482
|
+
}
|
|
2483
|
+
shouldUseAsyncUpload(element) {
|
|
2484
|
+
return this.options.isUploadFileAsync && !element._file['iD_GUID'];
|
|
2485
|
+
}
|
|
2486
|
+
validateFileConstraints() {
|
|
2487
|
+
if (this.options.isMultipleFile) {
|
|
2488
|
+
if (!this.validateMinFileCount() || !this.validateMaxFileCount() || !this.validateTotalFileSize()) {
|
|
2489
|
+
return false;
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
return true;
|
|
2493
|
+
}
|
|
2494
|
+
validateMinFileCount() {
|
|
2495
|
+
if (this.options.minNoOfFiles > 0 && this.options.minNoOfFiles > this.uploader.queue.length) {
|
|
2496
|
+
const minFileMsg = this.utilityService.getResourceValue('MinimumFilesRequired')
|
|
2497
|
+
.replace('{count}', this.options.minNoOfFiles.toString());
|
|
2498
|
+
this.showFileCountError('MinFileCountValidationKey', minFileMsg);
|
|
2499
|
+
return false;
|
|
2500
|
+
}
|
|
2501
|
+
return true;
|
|
2502
|
+
}
|
|
2503
|
+
validateMaxFileCount() {
|
|
2504
|
+
if (this.options.maxNoOfFiles > 0 && this.options.maxNoOfFiles < this.uploader.queue.length) {
|
|
2505
|
+
const maxFileMsg = this.utilityService.getResourceValue('MaximumFilesExceeded') ||
|
|
2506
|
+
`Maximum {maxCount} files allowed. You have selected {currentCount} files.`;
|
|
2507
|
+
const finalMsg = maxFileMsg
|
|
2508
|
+
.replace('{maxCount}', this.options.maxNoOfFiles.toString())
|
|
2509
|
+
.replace('{currentCount}', this.uploader.queue.length.toString());
|
|
2510
|
+
this.showFileCountError('MaxFileCountValidationKey', finalMsg);
|
|
2511
|
+
return false;
|
|
2512
|
+
}
|
|
2513
|
+
return true;
|
|
2514
|
+
}
|
|
2515
|
+
showFileCountError(errorKey, message) {
|
|
2516
|
+
const currentErrors = this.fileUploadFormControl.errors || {};
|
|
2517
|
+
currentErrors[errorKey] = message;
|
|
2518
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2519
|
+
this.fileUploadFormControl.markAsTouched();
|
|
2520
|
+
}
|
|
2521
|
+
clearFileCountError(errorKey) {
|
|
2522
|
+
const currentErrors = this.fileUploadFormControl.errors;
|
|
2523
|
+
if (currentErrors && currentErrors[errorKey]) {
|
|
2524
|
+
delete currentErrors[errorKey];
|
|
2525
|
+
if (Object.keys(currentErrors).length === 0) {
|
|
2526
|
+
this.fileUploadFormControl.setErrors(null);
|
|
2527
|
+
}
|
|
2528
|
+
else {
|
|
2529
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
validateTotalFileSize() {
|
|
2534
|
+
if (this.options.maxSizeForAllFilesInMB > 0) {
|
|
2535
|
+
const totalSize = this.uploader.queue.reduce((sum, element) => sum + element.file.size, 0);
|
|
2536
|
+
const maxSizeBytes = this.options.maxSizeForAllFilesInMB * this.BYTES_TO_MB;
|
|
2537
|
+
if (totalSize > maxSizeBytes) {
|
|
2538
|
+
this.showTotalSizeError();
|
|
2539
|
+
return false;
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
return true;
|
|
2543
|
+
}
|
|
2544
|
+
showTotalSizeError() {
|
|
2545
|
+
const totalSizeMsg = this.utilityService.getResourceValue('TotalFileSizeExceeded')
|
|
2546
|
+
.replace('{maxSize}', this.options.maxSizeForAllFilesInMB.toString());
|
|
2547
|
+
const currentErrors = this.fileUploadFormControl.errors || {};
|
|
2548
|
+
currentErrors['MaxSizeForAllFilesInMB'] = totalSizeMsg;
|
|
2549
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2550
|
+
this.fileUploadFormControl.markAsTouched();
|
|
2551
|
+
}
|
|
2552
|
+
validateFileSize(file) {
|
|
2553
|
+
const maxFileSize = this.options.fileMaxSizeInMB * this.BYTES_TO_MB;
|
|
2554
|
+
if (file.size > maxFileSize) {
|
|
2555
|
+
this.setFormControlError('FileMaxSizeInMB', `${this.options.fileMaxSizeInMB}MB`);
|
|
2556
|
+
return false;
|
|
2557
|
+
}
|
|
2558
|
+
return true;
|
|
2559
|
+
}
|
|
2560
|
+
validateFileType(file) {
|
|
2561
|
+
if (this.options.fileUploadAcceptsTypes?.length) {
|
|
2562
|
+
const fileType = file.type;
|
|
2563
|
+
const isAccepted = this.acceptedTypeArray.some(type => type.toLowerCase() === fileType.toLowerCase());
|
|
2564
|
+
if (!isAccepted) {
|
|
2565
|
+
this.setFormControlError('ToolTipTypeError', this.toolTipTypeArray);
|
|
2566
|
+
return false;
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
return true;
|
|
2570
|
+
}
|
|
2571
|
+
validateIndividualFileSize(file) {
|
|
2572
|
+
const maxFileSize = this.options.fileMaxSizeInMB * this.BYTES_TO_MB;
|
|
2573
|
+
return file.size <= maxFileSize;
|
|
2574
|
+
}
|
|
2575
|
+
validateIndividualFileType(file) {
|
|
2576
|
+
if (!this.options.fileUploadAcceptsTypes?.length) {
|
|
2577
|
+
return true;
|
|
2578
|
+
}
|
|
2579
|
+
const fileType = file.type;
|
|
2580
|
+
return this.acceptedTypeArray.some(type => type.toLowerCase() === fileType.toLowerCase());
|
|
2581
|
+
}
|
|
2582
|
+
validateDuplicateFileName(file, currentElement) {
|
|
2583
|
+
if (!file?.name) {
|
|
2584
|
+
return true;
|
|
2585
|
+
}
|
|
2586
|
+
const currentFileName = file.name.toLowerCase();
|
|
2587
|
+
const existingFiles = this.uploader.queue.filter(item => item !== currentElement);
|
|
2588
|
+
const duplicateExists = existingFiles.some(item => {
|
|
2589
|
+
const existingFileName = item.file?.name || item._file?.name;
|
|
2590
|
+
return existingFileName && existingFileName.toLowerCase() === currentFileName;
|
|
2591
|
+
});
|
|
2592
|
+
if (duplicateExists) {
|
|
2593
|
+
return false;
|
|
2594
|
+
}
|
|
2595
|
+
if (this.options.value) {
|
|
2596
|
+
const uploadedFiles = Array.isArray(this.options.value) ? this.options.value : [this.options.value];
|
|
2597
|
+
const duplicateInUploaded = uploadedFiles.some(uploadedFile => {
|
|
2598
|
+
const uploadedFileName = uploadedFile?.fileName || uploadedFile?.name;
|
|
2599
|
+
return uploadedFileName && uploadedFileName.toLowerCase() === currentFileName;
|
|
2436
2600
|
});
|
|
2437
|
-
|
|
2438
|
-
this.uploader.queue = [];
|
|
2439
|
-
return;
|
|
2601
|
+
return !duplicateInUploaded;
|
|
2440
2602
|
}
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2603
|
+
return true;
|
|
2604
|
+
}
|
|
2605
|
+
removeInvalidFiles(invalidFiles) {
|
|
2606
|
+
invalidFiles.forEach(invalidFile => {
|
|
2607
|
+
const index = this.uploader.queue.indexOf(invalidFile);
|
|
2608
|
+
if (index > -1) {
|
|
2609
|
+
this.uploader.queue.splice(index, 1);
|
|
2610
|
+
}
|
|
2611
|
+
});
|
|
2612
|
+
}
|
|
2613
|
+
showValidationErrors(errors) {
|
|
2614
|
+
if (errors.length === 0)
|
|
2615
|
+
return;
|
|
2616
|
+
const errorMessage = errors.join('<br/>');
|
|
2617
|
+
this.setValidationError('InvalidFiles', errorMessage);
|
|
2618
|
+
setTimeout(() => {
|
|
2619
|
+
this.clearInvalidFilesError();
|
|
2620
|
+
}, this.ERROR_DISPLAY_DURATION);
|
|
2621
|
+
}
|
|
2622
|
+
setValidationError(errorKey, errorMessage) {
|
|
2623
|
+
const currentErrors = this.fileUploadFormControl.errors || {};
|
|
2624
|
+
currentErrors[errorKey] = errorMessage;
|
|
2625
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2626
|
+
this.fileUploadFormControl.markAsTouched();
|
|
2627
|
+
}
|
|
2628
|
+
clearInvalidFilesError() {
|
|
2629
|
+
const currentErrors = this.fileUploadFormControl.errors;
|
|
2630
|
+
if (currentErrors && currentErrors['InvalidFiles']) {
|
|
2631
|
+
delete currentErrors['InvalidFiles'];
|
|
2632
|
+
if (Object.keys(currentErrors).length === 0) {
|
|
2633
|
+
this.fileUploadFormControl.setErrors(null);
|
|
2634
|
+
}
|
|
2635
|
+
else {
|
|
2636
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2459
2637
|
}
|
|
2460
2638
|
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
});
|
|
2473
|
-
formControl.markAsTouched();
|
|
2474
|
-
this.uploader.queue = [];
|
|
2475
|
-
return;
|
|
2639
|
+
}
|
|
2640
|
+
setFormControlError(errorKey, errorValue) {
|
|
2641
|
+
this.fileUploadFormControl.setErrors({ [errorKey]: errorValue });
|
|
2642
|
+
this.fileUploadFormControl.markAsTouched();
|
|
2643
|
+
this.uploader.queue = [];
|
|
2644
|
+
}
|
|
2645
|
+
handleAsyncFileUpload(element, filesArray) {
|
|
2646
|
+
const uploadSubscription = this.fileUploadService.uploadFile(element._file).subscribe({
|
|
2647
|
+
next: (event) => {
|
|
2648
|
+
if (event.type === HttpEventType.UploadProgress) {
|
|
2649
|
+
this.handleUploadProgress(element, event);
|
|
2476
2650
|
}
|
|
2477
|
-
if (
|
|
2478
|
-
this.
|
|
2479
|
-
!(this.acceptedTypeArray.includes(fileType.toUpperCase()) ||
|
|
2480
|
-
this.acceptedTypeArray.includes(fileType.toLowerCase()))) {
|
|
2481
|
-
const formControl = this.fileUploadFormControl;
|
|
2482
|
-
formControl.setErrors({ ToolTipTypeError: this.toolTipTypeArray });
|
|
2483
|
-
formControl.markAsTouched();
|
|
2484
|
-
this.uploader.queue = [];
|
|
2485
|
-
return;
|
|
2486
|
-
}
|
|
2487
|
-
if (this.options.isUploadFileAsync && !element._file['iD_GUID']) {
|
|
2488
|
-
this.fileUploadService.uploadFile(element._file).subscribe({
|
|
2489
|
-
next: (event) => {
|
|
2490
|
-
let queueIndex = this.uploader.queue.findIndex((file) => file == element);
|
|
2491
|
-
if (event.type === HttpEventType.UploadProgress) {
|
|
2492
|
-
let value = Math.round((100 * event.loaded) / event.total);
|
|
2493
|
-
this.uploader.queue[queueIndex].progress = value >= 95 ? 95 : value;
|
|
2494
|
-
}
|
|
2495
|
-
else if (event.type === HttpEventType.Response) {
|
|
2496
|
-
this.uploader.queue[queueIndex].progress = 100;
|
|
2497
|
-
let fileID = event.body.val;
|
|
2498
|
-
this.uploader.queue[queueIndex]._file['iD_GUID'] = fileID;
|
|
2499
|
-
this.uploader.queue[queueIndex]._file['isNew'] = true;
|
|
2500
|
-
let AddedFile = {
|
|
2501
|
-
iD_GUID: fileID,
|
|
2502
|
-
fileName: this.uploader.queue[queueIndex]._file['name'],
|
|
2503
|
-
fileType: this.uploader.queue[queueIndex]._file['type'],
|
|
2504
|
-
isNew: true
|
|
2505
|
-
};
|
|
2506
|
-
if (this.options.isMultipleFile == false) {
|
|
2507
|
-
this.fileUploadModel = new FileUploadModel();
|
|
2508
|
-
this.fileUploadModel.file = AddedFile;
|
|
2509
|
-
this.fileUploadFormControl.setValue(this.fileUploadModel);
|
|
2510
|
-
this.group.get(this.options.name).setValue(this.fileUploadModel);
|
|
2511
|
-
//Use this line to enable two way binding.
|
|
2512
|
-
this.options.value = this.fileUploadModel;
|
|
2513
|
-
}
|
|
2514
|
-
else {
|
|
2515
|
-
FilesArray.push(AddedFile);
|
|
2516
|
-
this.multipleFileUploadModel.uploadedFiles = FilesArray;
|
|
2517
|
-
if (this.options.value != null && this.options.value != undefined) {
|
|
2518
|
-
if (this.options.value.correlationID_GUID == null) {
|
|
2519
|
-
this.multipleFileUploadModel.removedFiles = [];
|
|
2520
|
-
}
|
|
2521
|
-
}
|
|
2522
|
-
this.multipleFileUploadModel.correlationID_GUID =
|
|
2523
|
-
this.options.value?.correlationID_GUID;
|
|
2524
|
-
this.fileUploadFormControl.setValue(this.multipleFileUploadModel);
|
|
2525
|
-
this.group.get(this.options.name).setValue(this.multipleFileUploadModel);
|
|
2526
|
-
//Use this line to enable two way binding.
|
|
2527
|
-
this.options.value = this.multipleFileUploadModel;
|
|
2528
|
-
this.isUploadComplete.emit(true);
|
|
2529
|
-
}
|
|
2530
|
-
}
|
|
2531
|
-
}
|
|
2532
|
-
});
|
|
2533
|
-
}
|
|
2534
|
-
else {
|
|
2535
|
-
let reader = new FileReader();
|
|
2536
|
-
let fileObject = file.rawFile;
|
|
2537
|
-
reader.readAsDataURL(fileObject);
|
|
2538
|
-
reader.onload = () => {
|
|
2539
|
-
let existingID_GUID = null;
|
|
2540
|
-
if (!this.options.isMultipleFile && this.file)
|
|
2541
|
-
existingID_GUID = this.file.NameWithExtension == file.name ? this.file.iD_GUID : null;
|
|
2542
|
-
let AddedFile = {
|
|
2543
|
-
fileName: file.name,
|
|
2544
|
-
fileType: file.type,
|
|
2545
|
-
fileBase64: reader.result.toString().split(',')[1],
|
|
2546
|
-
fileSizeInMB: file.size / 1000 / 1000,
|
|
2547
|
-
nameWithExtension: file.name,
|
|
2548
|
-
iD_GUID: existingID_GUID,
|
|
2549
|
-
isNew: true
|
|
2550
|
-
};
|
|
2551
|
-
if (this.options.isMultipleFile == false) {
|
|
2552
|
-
this.fileUploadModel = new FileUploadModel();
|
|
2553
|
-
this.fileUploadModel.file = AddedFile;
|
|
2554
|
-
this.fileUploadFormControl.setValue(this.fileUploadModel);
|
|
2555
|
-
this.group.get(this.options.name).setValue(this.fileUploadModel);
|
|
2556
|
-
//Use this line to enable two way binding.
|
|
2557
|
-
this.options.value = this.fileUploadModel;
|
|
2558
|
-
}
|
|
2559
|
-
else {
|
|
2560
|
-
FilesArray.push(AddedFile);
|
|
2561
|
-
this.multipleFileUploadModel.uploadedFiles = FilesArray;
|
|
2562
|
-
if (this.options.value != null && this.options.value != undefined) {
|
|
2563
|
-
if (this.options.value.correlationID_GUID == null) {
|
|
2564
|
-
this.multipleFileUploadModel.removedFiles = [];
|
|
2565
|
-
}
|
|
2566
|
-
}
|
|
2567
|
-
this.multipleFileUploadModel.correlationID_GUID =
|
|
2568
|
-
this.options.value?.correlationID_GUID;
|
|
2569
|
-
this.fileUploadFormControl.setValue(this.multipleFileUploadModel);
|
|
2570
|
-
this.group.get(this.options.name).setValue(this.multipleFileUploadModel);
|
|
2571
|
-
//Use this line to enable two way binding.
|
|
2572
|
-
this.options.value = this.multipleFileUploadModel;
|
|
2573
|
-
}
|
|
2574
|
-
};
|
|
2575
|
-
let originalValue = this.group.get(this.options.name).value;
|
|
2576
|
-
if (this.options.patchFunction &&
|
|
2577
|
-
this.options.patchPath &&
|
|
2578
|
-
this.group.get(this.options.name).valid) {
|
|
2579
|
-
this.controlUtility.patchControlValue(originalValue, this.options.patchFunction, this.options.patchPath);
|
|
2580
|
-
}
|
|
2581
|
-
this.OnChange.emit(originalValue);
|
|
2651
|
+
else if (event.type === HttpEventType.Response) {
|
|
2652
|
+
this.handleUploadComplete(element, event, filesArray);
|
|
2582
2653
|
}
|
|
2654
|
+
},
|
|
2655
|
+
error: (error) => {
|
|
2656
|
+
console.error('Upload failed:', error);
|
|
2657
|
+
// Handle upload error - you can add custom error handling here
|
|
2583
2658
|
}
|
|
2659
|
+
});
|
|
2660
|
+
// Store subscription for cleanup
|
|
2661
|
+
this.subscriptions.add(uploadSubscription);
|
|
2662
|
+
}
|
|
2663
|
+
handleUploadProgress(element, event) {
|
|
2664
|
+
const queueIndex = this.uploader.queue.findIndex((file) => file === element);
|
|
2665
|
+
if (queueIndex === -1)
|
|
2666
|
+
return;
|
|
2667
|
+
const progress = Math.round((100 * event.loaded) / event.total);
|
|
2668
|
+
this.uploader.queue[queueIndex].progress =
|
|
2669
|
+
progress >= this.PROGRESS_NEAR_COMPLETE ? this.PROGRESS_NEAR_COMPLETE : progress;
|
|
2670
|
+
}
|
|
2671
|
+
handleUploadComplete(element, event, filesArray) {
|
|
2672
|
+
const queueIndex = this.uploader.queue.findIndex((file) => file === element);
|
|
2673
|
+
if (queueIndex === -1)
|
|
2674
|
+
return;
|
|
2675
|
+
this.uploader.queue[queueIndex].progress = this.PROGRESS_COMPLETE;
|
|
2676
|
+
const fileID = event.body.val;
|
|
2677
|
+
this.updateElementWithFileInfo(element, fileID, event.body.downloadUrl);
|
|
2678
|
+
const addedFile = this.createFileDTO(element, fileID, event.body.downloadUrl);
|
|
2679
|
+
this.updateFormValue(addedFile, filesArray);
|
|
2680
|
+
}
|
|
2681
|
+
updateElementWithFileInfo(element, fileID, downloadUrl) {
|
|
2682
|
+
element._file['iD_GUID'] = fileID;
|
|
2683
|
+
element._file['isNew'] = true;
|
|
2684
|
+
if (downloadUrl) {
|
|
2685
|
+
element._file['url'] = downloadUrl;
|
|
2686
|
+
element.file.url = downloadUrl;
|
|
2687
|
+
}
|
|
2688
|
+
}
|
|
2689
|
+
createFileDTO(element, fileID, downloadUrl) {
|
|
2690
|
+
return {
|
|
2691
|
+
iD_GUID: fileID,
|
|
2692
|
+
fileName: element._file['name'],
|
|
2693
|
+
fileType: element._file['type'],
|
|
2694
|
+
isNew: true,
|
|
2695
|
+
fileBase64: '',
|
|
2696
|
+
fileSizeInMB: element._file.size / this.BYTES_TO_MB,
|
|
2697
|
+
nameWithExtension: element._file['name'],
|
|
2698
|
+
fullFileURL: downloadUrl || null
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
handleSyncFileUpload(file, filesArray) {
|
|
2702
|
+
this.trackMemoryUsage(file.size);
|
|
2703
|
+
const reader = new FileReader();
|
|
2704
|
+
// Store reader reference for cleanup
|
|
2705
|
+
const readerRef = reader;
|
|
2706
|
+
reader.onload = () => {
|
|
2707
|
+
try {
|
|
2708
|
+
const existingGUID = this.getExistingFileGUID(file);
|
|
2709
|
+
this.updateQueueItemForSync(file);
|
|
2710
|
+
const addedFile = this.createSyncFileDTO(file, reader.result, existingGUID);
|
|
2711
|
+
this.updateFormValue(addedFile, filesArray);
|
|
2712
|
+
this.handlePatchAndEmit();
|
|
2713
|
+
}
|
|
2714
|
+
finally {
|
|
2715
|
+
// Clean up reader
|
|
2716
|
+
readerRef.onload = null;
|
|
2717
|
+
readerRef.onerror = null;
|
|
2718
|
+
readerRef.onabort = null;
|
|
2719
|
+
}
|
|
2720
|
+
};
|
|
2721
|
+
reader.onerror = () => {
|
|
2722
|
+
console.error('File reading failed');
|
|
2723
|
+
readerRef.onload = null;
|
|
2724
|
+
readerRef.onerror = null;
|
|
2725
|
+
readerRef.onabort = null;
|
|
2726
|
+
};
|
|
2727
|
+
reader.readAsDataURL(file.rawFile);
|
|
2728
|
+
}
|
|
2729
|
+
updateQueueItemForSync(file) {
|
|
2730
|
+
const queueItem = this.findQueueItemByFile(file);
|
|
2731
|
+
if (queueItem) {
|
|
2732
|
+
this.preserveFileReference(queueItem, file);
|
|
2733
|
+
queueItem.progress = this.PROGRESS_COMPLETE;
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
findQueueItemByFile(file) {
|
|
2737
|
+
return this.uploader.queue.find(item => item.file.name === file.name && item.file.size === file.size);
|
|
2738
|
+
}
|
|
2739
|
+
preserveFileReference(queueItem, file) {
|
|
2740
|
+
queueItem._file.rawFile = file.rawFile;
|
|
2741
|
+
queueItem.file.rawFile = file.rawFile;
|
|
2742
|
+
}
|
|
2743
|
+
createSyncFileDTO(file, readerResult, existingGUID) {
|
|
2744
|
+
return {
|
|
2745
|
+
fileName: file.name,
|
|
2746
|
+
fileType: file.type,
|
|
2747
|
+
fileBase64: readerResult.split(',')[1],
|
|
2748
|
+
fileSizeInMB: file.size / this.BYTES_TO_MB,
|
|
2749
|
+
nameWithExtension: file.name,
|
|
2750
|
+
iD_GUID: existingGUID,
|
|
2751
|
+
isNew: true,
|
|
2752
|
+
fullFileURL: null
|
|
2753
|
+
};
|
|
2754
|
+
}
|
|
2755
|
+
getExistingFileGUID(file) {
|
|
2756
|
+
if (!this.options.isMultipleFile && this.file) {
|
|
2757
|
+
return this.file.nameWithExtension === file.name ? this.file.iD_GUID : null;
|
|
2758
|
+
}
|
|
2759
|
+
return null;
|
|
2760
|
+
}
|
|
2761
|
+
updateFormValue(addedFile, filesArray) {
|
|
2762
|
+
if (!this.options.isMultipleFile) {
|
|
2763
|
+
this.fileUploadModel = new FileUploadModel();
|
|
2764
|
+
this.fileUploadModel.file = addedFile;
|
|
2765
|
+
this.updateFormControl(this.fileUploadModel);
|
|
2766
|
+
}
|
|
2767
|
+
else {
|
|
2768
|
+
filesArray.push(addedFile);
|
|
2769
|
+
this.multipleFileUploadModel.uploadedFiles = filesArray;
|
|
2770
|
+
this.setupMultipleFileModel();
|
|
2771
|
+
this.updateFormControl(this.multipleFileUploadModel);
|
|
2772
|
+
this.isUploadComplete.emit(true);
|
|
2584
2773
|
}
|
|
2585
2774
|
}
|
|
2775
|
+
setupMultipleFileModel() {
|
|
2776
|
+
if (this.options.value?.correlationID_GUID == null) {
|
|
2777
|
+
this.multipleFileUploadModel.removedFiles = [];
|
|
2778
|
+
}
|
|
2779
|
+
this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
|
|
2780
|
+
}
|
|
2781
|
+
updateFormControl(value) {
|
|
2782
|
+
this.preserveErrorsAndUpdateValue(value);
|
|
2783
|
+
this.options.value = value;
|
|
2784
|
+
}
|
|
2785
|
+
preserveErrorsAndUpdateValue(value) {
|
|
2786
|
+
const currentErrors = this.fileUploadFormControl.errors;
|
|
2787
|
+
this.fileUploadFormControl.setValue(value, { emitEvent: false });
|
|
2788
|
+
this.group.get(this.options.name)?.setValue(value, { emitEvent: false });
|
|
2789
|
+
if (currentErrors) {
|
|
2790
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
handlePatchAndEmit() {
|
|
2794
|
+
const originalValue = this.group.get(this.options.name)?.value;
|
|
2795
|
+
if (this.options.patchFunction && this.options.patchPath && this.group.get(this.options.name)?.valid) {
|
|
2796
|
+
this.controlUtility.patchControlValue(originalValue, this.options.patchFunction, this.options.patchPath);
|
|
2797
|
+
}
|
|
2798
|
+
this.OnChange.emit(originalValue);
|
|
2799
|
+
}
|
|
2586
2800
|
removeFromControlValue(item) {
|
|
2587
|
-
|
|
2588
|
-
|
|
2801
|
+
// Clean up blob URL before removing
|
|
2802
|
+
const downloadUrl = this.getFileDownloadUrl(item);
|
|
2803
|
+
if (downloadUrl && downloadUrl.startsWith('blob:')) {
|
|
2804
|
+
this.cleanupBlobUrl(downloadUrl);
|
|
2589
2805
|
}
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
this.fileUploadFormControl.markAsTouched();
|
|
2594
|
-
this.fileUploadFormControl.invalid;
|
|
2595
|
-
}
|
|
2596
|
-
this.group.get(this.options.name).setValue(this.fileUploadModel);
|
|
2597
|
-
this.options.value = this.fileUploadModel;
|
|
2806
|
+
this.handleAsyncFileDeletion(item);
|
|
2807
|
+
if (!this.options.isMultipleFile) {
|
|
2808
|
+
this.handleSingleFileRemoval();
|
|
2598
2809
|
}
|
|
2599
2810
|
else {
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2811
|
+
this.handleMultipleFileRemoval(item);
|
|
2812
|
+
}
|
|
2813
|
+
this.checkAndClearMaxFileCountValidation();
|
|
2814
|
+
}
|
|
2815
|
+
handleAsyncFileDeletion(item) {
|
|
2816
|
+
if (this.options.isUploadFileAsync &&
|
|
2817
|
+
item.progress === this.PROGRESS_COMPLETE &&
|
|
2818
|
+
item._file['isNew']) {
|
|
2819
|
+
const deleteSubscription = this.fileUploadService.deleteFile(item._file['iD_GUID']).subscribe({
|
|
2820
|
+
error: (error) => console.error('Delete failed:', error)
|
|
2821
|
+
});
|
|
2822
|
+
this.subscriptions.add(deleteSubscription);
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
handleSingleFileRemoval() {
|
|
2826
|
+
this.uploader.queue = [];
|
|
2827
|
+
this.fileUploadModel = null;
|
|
2828
|
+
if (this.options.isRequired) {
|
|
2829
|
+
this.fileUploadFormControl.markAsTouched();
|
|
2830
|
+
}
|
|
2831
|
+
const currentErrors = this.fileUploadFormControl.errors;
|
|
2832
|
+
this.group.get(this.options.name)?.setValue(this.fileUploadModel, { emitEvent: false });
|
|
2833
|
+
if (currentErrors) {
|
|
2834
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2835
|
+
}
|
|
2836
|
+
this.options.value = this.fileUploadModel;
|
|
2837
|
+
}
|
|
2838
|
+
handleMultipleFileRemoval(item) {
|
|
2839
|
+
// Clean up blob URL
|
|
2840
|
+
const downloadUrl = this.getFileDownloadUrl(item);
|
|
2841
|
+
if (downloadUrl && downloadUrl.startsWith('blob:')) {
|
|
2842
|
+
this.cleanupBlobUrl(downloadUrl);
|
|
2843
|
+
}
|
|
2844
|
+
const queueIndex = this.uploader.queue.indexOf(item);
|
|
2845
|
+
if (queueIndex > -1) {
|
|
2846
|
+
this.uploader.queue.splice(queueIndex, 1);
|
|
2847
|
+
}
|
|
2848
|
+
this.processFileRemovalFromExisting(item);
|
|
2849
|
+
this.removeFromUploadedFiles(item);
|
|
2850
|
+
this.validateRemainingFiles();
|
|
2851
|
+
this.updateMultipleFileModel();
|
|
2852
|
+
}
|
|
2853
|
+
processFileRemovalFromExisting(item) {
|
|
2854
|
+
if (!this.options.value) {
|
|
2855
|
+
this.resetDeletedFiles();
|
|
2856
|
+
return;
|
|
2857
|
+
}
|
|
2858
|
+
if (!this.options.value.correlationID_GUID) {
|
|
2859
|
+
this.resetDeletedFiles();
|
|
2860
|
+
}
|
|
2861
|
+
else {
|
|
2862
|
+
this.handleExistingFileRemoval(item);
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
resetDeletedFiles() {
|
|
2866
|
+
this.deletedFiles = [];
|
|
2867
|
+
this.multipleFileUploadModel.removedFiles = [];
|
|
2868
|
+
}
|
|
2869
|
+
handleExistingFileRemoval(item) {
|
|
2870
|
+
const fileName = item.file.rawFile.name;
|
|
2871
|
+
const existingFile = this.multipleFileUploadModel.existingFiles
|
|
2872
|
+
.find(obj => obj.nameWithExtension === fileName);
|
|
2873
|
+
if (existingFile && !this.deletedFiles.some(obj => obj.nameWithExtension === fileName)) {
|
|
2874
|
+
this.multipleFileUploadModel.existingFiles =
|
|
2875
|
+
this.multipleFileUploadModel.existingFiles.filter(obj => obj.nameWithExtension !== fileName);
|
|
2876
|
+
this.deletedFiles.push(existingFile);
|
|
2877
|
+
this.multipleFileUploadModel.removedFiles.push(existingFile.iD_GUID);
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
removeFromUploadedFiles(item) {
|
|
2881
|
+
const itemFileName = item._file.name || item.file.name;
|
|
2882
|
+
const itemFileSize = item._file.size || item.file.size;
|
|
2883
|
+
const itemGUID = item._file['iD_GUID'];
|
|
2884
|
+
this.multipleFileUploadModel.uploadedFiles =
|
|
2885
|
+
this.multipleFileUploadModel.uploadedFiles.filter(obj => {
|
|
2886
|
+
if (itemGUID && obj.iD_GUID) {
|
|
2887
|
+
return obj.iD_GUID !== itemGUID;
|
|
2625
2888
|
}
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
this.options.
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
this.
|
|
2889
|
+
const objFileName = obj.nameWithExtension || obj.fileName;
|
|
2890
|
+
const objFileSize = obj.fileSizeInMB ? obj.fileSizeInMB * this.BYTES_TO_MB : 0;
|
|
2891
|
+
return !(objFileName === itemFileName && Math.abs(objFileSize - itemFileSize) < 1000);
|
|
2892
|
+
});
|
|
2893
|
+
}
|
|
2894
|
+
validateRemainingFiles() {
|
|
2895
|
+
if ((!this.multipleFileUploadModel.uploadedFiles ||
|
|
2896
|
+
this.multipleFileUploadModel.uploadedFiles.length === 0) &&
|
|
2897
|
+
this.options.isRequired) {
|
|
2898
|
+
this.fileUploadFormControl.setErrors({
|
|
2899
|
+
MinFileCountValidationKey: this.options.minNoOfFiles
|
|
2900
|
+
});
|
|
2901
|
+
this.fileUploadFormControl.markAsTouched();
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
updateMultipleFileModel() {
|
|
2905
|
+
this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
|
|
2906
|
+
const currentErrors = this.fileUploadFormControl.errors;
|
|
2907
|
+
this.fileUploadFormControl.setValue(this.multipleFileUploadModel, { emitEvent: false });
|
|
2908
|
+
this.group.get(this.options.name)?.setValue(this.multipleFileUploadModel, { emitEvent: false });
|
|
2909
|
+
this.options.value = this.multipleFileUploadModel;
|
|
2910
|
+
if (currentErrors) {
|
|
2911
|
+
this.fileUploadFormControl.setErrors(currentErrors);
|
|
2649
2912
|
}
|
|
2650
2913
|
}
|
|
2651
2914
|
convertSizeToMB(size) {
|
|
2652
2915
|
if (size === 0) {
|
|
2653
2916
|
return 0;
|
|
2654
2917
|
}
|
|
2655
|
-
|
|
2656
|
-
const megabytes = size /
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2918
|
+
const BYTES_TO_MB_ACCURATE = 1024 * 1024;
|
|
2919
|
+
const megabytes = size / BYTES_TO_MB_ACCURATE;
|
|
2920
|
+
return Math.round(megabytes * 100) / 100;
|
|
2921
|
+
}
|
|
2922
|
+
trackByFunction(index, item) {
|
|
2923
|
+
return item._file ? item._file.name + item._file.size : index;
|
|
2924
|
+
}
|
|
2925
|
+
shouldShowFileList() {
|
|
2926
|
+
return this.uploader?.queue && this.uploader.queue.length > 0;
|
|
2927
|
+
}
|
|
2928
|
+
isDownloadEnabled() {
|
|
2929
|
+
return true;
|
|
2930
|
+
}
|
|
2931
|
+
isRemoveEnabled() {
|
|
2932
|
+
return !this.options.isReadonly && !this.options.isDisabled;
|
|
2933
|
+
}
|
|
2934
|
+
getFileDownloadUrl(item) {
|
|
2935
|
+
const existingUrl = this.getExistingFileUrl(item);
|
|
2936
|
+
if (existingUrl) {
|
|
2937
|
+
return existingUrl;
|
|
2938
|
+
}
|
|
2939
|
+
return this.createFileUrl(item);
|
|
2940
|
+
}
|
|
2941
|
+
getExistingFileUrl(item) {
|
|
2942
|
+
return item?.file?.url ||
|
|
2943
|
+
item?._file?.url ||
|
|
2944
|
+
item?.url ||
|
|
2945
|
+
item?.file?.rawFile?.url ||
|
|
2946
|
+
item?._file?.rawFile?.url ||
|
|
2947
|
+
null;
|
|
2948
|
+
}
|
|
2949
|
+
createFileUrl(item) {
|
|
2950
|
+
const fileName = this.getFileName(item);
|
|
2951
|
+
const fileType = item?.file?.type || item?._file?.type;
|
|
2952
|
+
const originalFile = item?._file?.rawFile || item?.file?.rawFile;
|
|
2953
|
+
if (originalFile && originalFile instanceof File) {
|
|
2954
|
+
return URL.createObjectURL(originalFile);
|
|
2955
|
+
}
|
|
2956
|
+
const base64Data = typeof originalFile === 'string' ? originalFile : null;
|
|
2957
|
+
if (base64Data && fileName) {
|
|
2958
|
+
return this.createBlobUrlWithFilename(base64Data, fileType, fileName);
|
|
2959
|
+
}
|
|
2960
|
+
const fileId = item?._file?.['iD_GUID'];
|
|
2961
|
+
if (fileId && this.options.isUploadFileAsync) {
|
|
2962
|
+
return this.constructDownloadUrl(fileId, fileName);
|
|
2963
|
+
}
|
|
2964
|
+
return null;
|
|
2965
|
+
}
|
|
2966
|
+
createBlobUrlWithFilename(base64Data, fileType, fileName) {
|
|
2967
|
+
try {
|
|
2968
|
+
const byteCharacters = atob(base64Data);
|
|
2969
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
2970
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
2971
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
2972
|
+
}
|
|
2973
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
2974
|
+
const blob = new Blob([byteArray], { type: fileType || 'application/octet-stream' });
|
|
2975
|
+
return URL.createObjectURL(blob);
|
|
2976
|
+
}
|
|
2977
|
+
catch (error) {
|
|
2978
|
+
const errorMsg = this.utilityService.getResourceValue('ErrorCreatingBlobUrl');
|
|
2979
|
+
console.error(errorMsg, error);
|
|
2980
|
+
return `data:${fileType || 'application/octet-stream'};base64,${base64Data}`;
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
constructDownloadUrl(fileId, fileName) {
|
|
2984
|
+
const downloadBaseUrl = this.options.downloadBaseUrl;
|
|
2985
|
+
let url;
|
|
2986
|
+
if (downloadBaseUrl) {
|
|
2987
|
+
url = `${downloadBaseUrl}/${fileId}`;
|
|
2988
|
+
}
|
|
2989
|
+
else {
|
|
2990
|
+
url = `/api/files/download/${fileId}`;
|
|
2991
|
+
}
|
|
2992
|
+
if (fileName) {
|
|
2993
|
+
const separator = url.includes('?') ? '&' : '?';
|
|
2994
|
+
url += `${separator}filename=${encodeURIComponent(fileName)}`;
|
|
2995
|
+
}
|
|
2996
|
+
return url;
|
|
2997
|
+
}
|
|
2998
|
+
getFileName(item) {
|
|
2999
|
+
return item?.file?.name || item?._file?.name || 'file';
|
|
3000
|
+
}
|
|
3001
|
+
downloadFile(item) {
|
|
3002
|
+
const downloadInfo = this.prepareFileDownload(item);
|
|
3003
|
+
if (!downloadInfo.url) {
|
|
3004
|
+
this.handleDownloadError(downloadInfo.fileName);
|
|
3005
|
+
return;
|
|
3006
|
+
}
|
|
3007
|
+
this.executeFileDownload(downloadInfo.url, downloadInfo.fileName);
|
|
3008
|
+
}
|
|
3009
|
+
prepareFileDownload(item) {
|
|
3010
|
+
return {
|
|
3011
|
+
url: this.getFileDownloadUrl(item),
|
|
3012
|
+
fileName: this.getFileName(item)
|
|
3013
|
+
};
|
|
3014
|
+
}
|
|
3015
|
+
handleDownloadError(fileName) {
|
|
3016
|
+
const errorMsg = this.utilityService.getResourceValue('NoDownloadUrlAvailable')
|
|
3017
|
+
.replace('{fileName}', fileName);
|
|
3018
|
+
console.error(errorMsg);
|
|
3019
|
+
}
|
|
3020
|
+
executeFileDownload(url, fileName) {
|
|
3021
|
+
const link = this.createDownloadLink(url, fileName);
|
|
3022
|
+
this.triggerDownload(link);
|
|
3023
|
+
this.cleanupBlobUrl(url);
|
|
3024
|
+
}
|
|
3025
|
+
createDownloadLink(url, fileName) {
|
|
3026
|
+
const link = document.createElement('a');
|
|
3027
|
+
link.href = url;
|
|
3028
|
+
link.download = fileName;
|
|
3029
|
+
link.style.display = 'none';
|
|
3030
|
+
return link;
|
|
3031
|
+
}
|
|
3032
|
+
triggerDownload(link) {
|
|
3033
|
+
document.body.appendChild(link);
|
|
3034
|
+
link.click();
|
|
3035
|
+
document.body.removeChild(link);
|
|
3036
|
+
}
|
|
3037
|
+
cleanupBlobUrl(url) {
|
|
3038
|
+
if (url.startsWith('blob:')) {
|
|
3039
|
+
setTimeout(() => {
|
|
3040
|
+
URL.revokeObjectURL(url);
|
|
3041
|
+
}, 100);
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
trackMemoryUsage(fileSize) {
|
|
3045
|
+
this.currentMemoryUsage += fileSize;
|
|
3046
|
+
// If memory usage exceeds limit, clean up old files
|
|
3047
|
+
if (this.currentMemoryUsage > this.MAX_MEMORY_USAGE) {
|
|
3048
|
+
this.cleanupOldFiles();
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
cleanupOldFiles() {
|
|
3052
|
+
if (this.uploader?.queue && this.uploader.queue.length > 0) {
|
|
3053
|
+
// Remove oldest files to free memory
|
|
3054
|
+
const oldestFile = this.uploader.queue.shift();
|
|
3055
|
+
if (oldestFile) {
|
|
3056
|
+
const url = this.getFileDownloadUrl(oldestFile);
|
|
3057
|
+
if (url && url.startsWith('blob:')) {
|
|
3058
|
+
this.cleanupBlobUrl(url);
|
|
3059
|
+
}
|
|
3060
|
+
this.currentMemoryUsage -= (oldestFile.file?.size || 0);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
cleanupEventListeners() {
|
|
3065
|
+
// Clear file input references
|
|
3066
|
+
if (this.fileInput?.nativeElement) {
|
|
3067
|
+
this.fileInput.nativeElement.value = '';
|
|
3068
|
+
}
|
|
3069
|
+
// Clear uploader queue to prevent memory leaks
|
|
3070
|
+
if (this.uploader?.queue) {
|
|
3071
|
+
this.uploader.queue = [];
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
cleanupUploaderQueue() {
|
|
3075
|
+
if (this.uploader?.queue) {
|
|
3076
|
+
// Clear all items and their associated resources
|
|
3077
|
+
this.uploader.queue.forEach(item => {
|
|
3078
|
+
// Clean up blob URLs
|
|
3079
|
+
const url = this.getFileDownloadUrl(item);
|
|
3080
|
+
if (url && url.startsWith('blob:')) {
|
|
3081
|
+
this.cleanupBlobUrl(url);
|
|
3082
|
+
}
|
|
3083
|
+
// Clear file references
|
|
3084
|
+
if (item._file) {
|
|
3085
|
+
item._file = null;
|
|
3086
|
+
}
|
|
3087
|
+
if (item.file) {
|
|
3088
|
+
item.file = null;
|
|
3089
|
+
}
|
|
3090
|
+
});
|
|
3091
|
+
// Clear the queue
|
|
3092
|
+
this.uploader.queue = [];
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
ngOnDestroy() {
|
|
3096
|
+
// Clean up subscriptions
|
|
3097
|
+
this.subscriptions.unsubscribe();
|
|
3098
|
+
// Clean up uploader queue
|
|
3099
|
+
this.cleanupUploaderQueue();
|
|
3100
|
+
// Clean up event listeners
|
|
3101
|
+
this.cleanupEventListeners();
|
|
3102
|
+
// Clean up blob URLs
|
|
3103
|
+
if (this.uploader?.queue) {
|
|
3104
|
+
this.uploader.queue.forEach(item => {
|
|
3105
|
+
const url = this.getFileDownloadUrl(item);
|
|
3106
|
+
if (url && url.startsWith('blob:')) {
|
|
3107
|
+
URL.revokeObjectURL(url);
|
|
3108
|
+
}
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
checkAndClearMaxFileCountValidation() {
|
|
3113
|
+
if (!this.options.maxNoOfFiles || this.options.maxNoOfFiles <= 0) {
|
|
3114
|
+
return;
|
|
3115
|
+
}
|
|
3116
|
+
const currentQueueLength = this.uploader.queue.length;
|
|
3117
|
+
if (currentQueueLength <= this.options.maxNoOfFiles) {
|
|
3118
|
+
this.clearFileCountError('MaxFileCountValidationKey');
|
|
3119
|
+
}
|
|
2660
3120
|
}
|
|
2661
3121
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadComponent, deps: [{ token: i2.ControlContainer, optional: true }, { token: i2.FormGroupDirective }, { token: ControlUtility }, { token: i3.UtilityService }, { token: i3.ControlValidationService }, { token: GlobalSettings }, { token: FileUploadService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2662
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FileUploadComponent, selector: "BBSF-FileUplaod", inputs: { group: "group", options: "options" }, outputs: { OnChange: "OnChange", isUploadComplete: "isUploadComplete" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType == 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!--label-->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!--Asterisk-->\r\n <span *ngIf=\"((options.showAsterisk && options.isRequired) || options.isRequired) && !options.isReadonly\" class=\"text-danger\">*</span>\r\n </label>\r\n <!--Allow dropZone-->\r\n <div\r\n ng2FileDrop\r\n class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !(options.isMultipleFile == false && uploader.queue.length > 0) && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\"\r\n (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\"\r\n [uploader]=\"uploader\"\r\n [accept]=\"acceptedType\"\r\n id=\"{{ options.name }}\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\"\r\n aria-describedby=\"email-error\"\r\n aria-invalid=\"true\"\r\n type=\"file\"\r\n #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ UtilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div\r\n class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input\r\n ng2FileSelect\r\n [uploader]=\"uploader\"\r\n [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\"\r\n name=\"file\"\r\n type=\"file\"\r\n value=\"\"\r\n autocomplete=\"off\"\r\n (change)=\"onFileChange()\"\r\n [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\"\r\n id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\"\r\n aria-invalid=\"true\"\r\n formControlName=\"{{ options.name }}\"\r\n #fileInputControl\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!--Not allowed dropZone-->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\" (click)=\"fileInput.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg text-center\">{{ UtilityService.getResourceValue('Upload') }}</div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div\r\n class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input\r\n ng2FileSelect\r\n [uploader]=\"uploader\"\r\n [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\"\r\n name=\"file\"\r\n type=\"file\"\r\n value=\"\"\r\n autocomplete=\"off\"\r\n (change)=\"onFileChange()\"\r\n [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\"\r\n id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\"\r\n aria-invalid=\"true\"\r\n formControlName=\"{{ options.name }}\"\r\n #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- readonly -->\r\n <div *ngIf=\"options.isReadonly && !options.value\">\r\n <span class=\"readonly-view\">{{ UtilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!--items uploaded-->\r\n <div class=\"uploaded-items\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue\">\r\n <ng-container *ngIf=\"item?.progress == 100 && options.isUploadFileAsync\">\r\n <a *ngIf=\"item?.file?.rawFile['url']\" href=\"{{ item?.file?.rawFile['url'] }}\" class=\"btn-download-file btn-sm btn-progress-upload\" download>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <a *ngIf=\"item?.file?.rawFile['url'] == null\" class=\"btn-download-file btn-sm btn-progress-upload\">\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm\" (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\"\r\n stroke-width=\"1.5\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\"\r\n stroke-width=\"1.5\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <a href=\"{{ item?.file?.rawFile['url'] }}\" class=\"btn btn-download-file btn-sm\" download>\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\"></path>\r\n </svg>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm btn-danger\" (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <i class=\"fa fa-times px-0\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!--progress bar file upload-->\r\n <div *ngFor=\"let item of uploader.queue\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile == true }\" *ngIf=\"item?.progress < 100 && options.isUploadFileAsync\">\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ item?.file?.name }}</h4>\r\n <span (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\"\r\n stroke=\"#DBE1F0\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </span>\r\n </div>\r\n <div class=\"progress\">\r\n <div\r\n class=\"progress-bar\"\r\n role=\"progressbar\"\r\n aria-valuenow=\"70\"\r\n aria-valuemin=\"0\"\r\n aria-valuemax=\"100\"\r\n [class.file-uploaded]=\"item?.progress < 100\"\r\n [style.width.%]=\"item?.progress\"\r\n *ngIf=\"item?.progress > 0\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- required text-->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n {{ getErrorValidation(fileUploadFormControl.errors | keyvalue) }}\r\n </div>\r\n <!-- LabelDescription-->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription != null\">{{ options.labelDescription }}</div>\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7$2.FileDropDirective, selector: "[ng2FileDrop]", inputs: ["uploader"], outputs: ["fileOver", "onFileDrop"] }, { kind: "directive", type: i7$2.FileSelectDirective, selector: "[ng2FileSelect]", inputs: ["uploader"], outputs: ["onFileSelected"] }, { kind: "directive", type: i7.NativeElementInjectorDirective, selector: "[ngModel], [formControl], [formControlName]" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i5.KeyValuePipe, name: "keyvalue" }] }); }
|
|
3122
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: FileUploadComponent, selector: "BBSF-FileUpload", inputs: { group: "group", options: "options" }, outputs: { OnChange: "OnChange", isUploadComplete: "isUploadComplete" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType === 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!-- Label -->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!-- Required asterisk -->\r\n <span *ngIf=\"options.isRequired && !options.isReadonly && (options.showAsterisk || true)\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <!-- Drop zone enabled -->\r\n <div ng2FileDrop class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\" (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\" [uploader]=\"uploader\" [accept]=\"acceptedType\" [id]=\"options.name\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\"\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Instruction text -->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ utilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\"\r\n #fileInputControl [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Click to upload (no drop zone) -->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Upload text -->\r\n <div class=\"bbsf-validation-msg text-center\">\r\n {{ utilityService.getResourceValue('Upload') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\" #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Read-only state with no files -->\r\n <div *ngIf=\"options.isReadonly && (!options.value || (uploader.queue && uploader.queue.length === 0))\">\r\n <span class=\"readonly-view\">{{ utilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!-- Uploaded files list -->\r\n <div class=\"uploaded-items\" *ngIf=\"shouldShowFileList()\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n\r\n <!-- Async upload completed files -->\r\n <ng-container *ngIf=\"item?.progress === 100 && options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button *ngIf=\"getFileDownloadUrl(item); else noUrlTemplate\" type=\"button\"\r\n class=\"btn-download-file btn-sm btn-progress-upload\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- File name display when no URL available -->\r\n <ng-template #noUrlTemplate>\r\n <span class=\"btn-download-file btn-sm btn-progress-upload\" [title]=\"getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </span>\r\n </ng-template>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <!-- Delete icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n\r\n <!-- Sync upload files -->\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button type=\"button\" class=\"btn btn-download-file btn-sm\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <!-- Download icon -->\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\">\r\n </path>\r\n </svg>\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm btn-danger\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <i class=\"fa fa-times px-0\" aria-hidden=\"true\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!-- File upload progress indicators -->\r\n <div *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile }\"\r\n *ngIf=\"item?.progress < 100 && options.isUploadFileAsync && !options.isReadonly\">\r\n\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ getFileName(item) }}</h4>\r\n <button *ngIf=\"isRemoveEnabled()\" type=\"button\" class=\"btn-cancel-upload\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\"\r\n [attr.aria-label]=\"'Cancel upload for ' + getFileName(item)\">\r\n <!-- Cancel icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\" stroke=\"#DBE1F0\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"progress\">\r\n <div class=\"progress-bar\" role=\"progressbar\" [attr.aria-valuenow]=\"item?.progress\" aria-valuemin=\"0\"\r\n aria-valuemax=\"100\" [class.file-uploaded]=\"item?.progress < 100\" [style.width.%]=\"item?.progress\"\r\n *ngIf=\"item?.progress > 0\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation and description section -->\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n {{ getErrorValidation(fileUploadFormControl.errors | keyvalue) }}\r\n </div>\r\n\r\n <!-- Control description -->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription\">\r\n {{ options.labelDescription }}\r\n </div>\r\n\r\n <!-- Reset error state -->\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7$2.FileDropDirective, selector: "[ng2FileDrop]", inputs: ["uploader"], outputs: ["fileOver", "onFileDrop"] }, { kind: "directive", type: i7$2.FileSelectDirective, selector: "[ng2FileSelect]", inputs: ["uploader"], outputs: ["onFileSelected"] }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: i5.KeyValuePipe, name: "keyvalue" }] }); }
|
|
2663
3123
|
}
|
|
2664
3124
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FileUploadComponent, decorators: [{
|
|
2665
3125
|
type: Component,
|
|
2666
|
-
args: [{ selector: 'BBSF-FileUplaod', template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType == 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!--label-->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!--Asterisk-->\r\n <span *ngIf=\"((options.showAsterisk && options.isRequired) || options.isRequired) && !options.isReadonly\" class=\"text-danger\">*</span>\r\n </label>\r\n <!--Allow dropZone-->\r\n <div\r\n ng2FileDrop\r\n class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !(options.isMultipleFile == false && uploader.queue.length > 0) && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\"\r\n (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\"\r\n [uploader]=\"uploader\"\r\n [accept]=\"acceptedType\"\r\n id=\"{{ options.name }}\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\"\r\n aria-describedby=\"email-error\"\r\n aria-invalid=\"true\"\r\n type=\"file\"\r\n #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ UtilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div\r\n class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input\r\n ng2FileSelect\r\n [uploader]=\"uploader\"\r\n [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\"\r\n name=\"file\"\r\n type=\"file\"\r\n value=\"\"\r\n autocomplete=\"off\"\r\n (change)=\"onFileChange()\"\r\n [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\"\r\n id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\"\r\n aria-invalid=\"true\"\r\n formControlName=\"{{ options.name }}\"\r\n #fileInputControl\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!--Not allowed dropZone-->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\" (click)=\"fileInput.click()\">\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\"\r\n stroke=\"#4B5489\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n <!--Validation text-->\r\n <div class=\"bbsf-validation-msg text-center\">{{ UtilityService.getResourceValue('Upload') }}</div>\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\"></div>\r\n <div\r\n class=\"bbsf-validation-msg ng-star-inserted text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\"></div>\r\n </div>\r\n </div>\r\n <input\r\n ng2FileSelect\r\n [uploader]=\"uploader\"\r\n [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n multiple=\"{{ options.isMultipleFile ? 'multiple' : '' }}\"\r\n name=\"file\"\r\n type=\"file\"\r\n value=\"\"\r\n autocomplete=\"off\"\r\n (change)=\"onFileChange()\"\r\n [ngClass]=\"options.viewType == 1 ? '' : 'col-md-9'\"\r\n id=\"{{ options.name }}\"\r\n aria-describedby=\"email-error\"\r\n aria-invalid=\"true\"\r\n formControlName=\"{{ options.name }}\"\r\n #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- readonly -->\r\n <div *ngIf=\"options.isReadonly && !options.value\">\r\n <span class=\"readonly-view\">{{ UtilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!--items uploaded-->\r\n <div class=\"uploaded-items\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue\">\r\n <ng-container *ngIf=\"item?.progress == 100 && options.isUploadFileAsync\">\r\n <a *ngIf=\"item?.file?.rawFile['url']\" href=\"{{ item?.file?.rawFile['url'] }}\" class=\"btn-download-file btn-sm btn-progress-upload\" download>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <a *ngIf=\"item?.file?.rawFile['url'] == null\" class=\"btn-download-file btn-sm btn-progress-upload\">\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm\" (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\"\r\n stroke-width=\"1.5\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\"\r\n stroke-width=\"1.5\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <a href=\"{{ item?.file?.rawFile['url'] }}\" class=\"btn btn-download-file btn-sm\" download>\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\"></path>\r\n </svg>\r\n <span class=\"file-name\">{{ item?.file?.name }}</span>\r\n </a>\r\n <button *ngIf=\"!options.isReadonly\" class=\"btn btn-download-file btn-sm btn-danger\" (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <i class=\"fa fa-times px-0\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!--progress bar file upload-->\r\n <div *ngFor=\"let item of uploader.queue\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile == true }\" *ngIf=\"item?.progress < 100 && options.isUploadFileAsync\">\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ item?.file?.name }}</h4>\r\n <span (click)=\"item.remove(); removeFromControlValue(item)\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path\r\n opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\"\r\n stroke=\"#DBE1F0\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </span>\r\n </div>\r\n <div class=\"progress\">\r\n <div\r\n class=\"progress-bar\"\r\n role=\"progressbar\"\r\n aria-valuenow=\"70\"\r\n aria-valuemin=\"0\"\r\n aria-valuemax=\"100\"\r\n [class.file-uploaded]=\"item?.progress < 100\"\r\n [style.width.%]=\"item?.progress\"\r\n *ngIf=\"item?.progress > 0\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- required text-->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n {{ getErrorValidation(fileUploadFormControl.errors | keyvalue) }}\r\n </div>\r\n <!-- LabelDescription-->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription != null\">{{ options.labelDescription }}</div>\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>\r\n" }]
|
|
3126
|
+
args: [{ selector: 'BBSF-FileUpload', template: "<div class=\"form-group bbsf-control bbsf-file-upload\" [formGroup]=\"group\">\r\n <div [ngClass]=\"options.viewType === 1 ? 'bbsf-vertical' : 'bbsf-horizontal'\">\r\n <!-- Label -->\r\n <label [hidden]=\"options.hideLabel\" class=\"bbsf-label {{ options.labelExtraClasses }}\">\r\n {{ options.labelValue }}\r\n <!-- Required asterisk -->\r\n <span *ngIf=\"options.isRequired && !options.isReadonly && (options.showAsterisk || true)\"\r\n class=\"text-danger\">*</span>\r\n </label>\r\n <!-- Drop zone enabled -->\r\n <div ng2FileDrop class=\"bbsf-input-container {{ options.extraClasses }}\"\r\n *ngIf=\"options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n [ngClass]=\"{ 'another-file-over-class': hasAnotherDropZoneOver }\" (onFileDrop)=\"onFileChange()\"\r\n (fileOver)=\"fileOverAnother($event)\" [uploader]=\"uploader\" [accept]=\"acceptedType\" [id]=\"options.name\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\"\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\"\r\n (click)=\"fileInputControl.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Instruction text -->\r\n <div class=\"bbsf-validation-msg validation-msg-header text-center\">\r\n {{ utilityService.getResourceValue('DragAndDropHere') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\"\r\n #fileInputControl [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Click to upload (no drop zone) -->\r\n <div class=\"bbsf-input-container\" *ngIf=\"!options.isDropZone && !isHideInput() && !options.isReadonly\"\r\n (click)=\"fileInput.click()\">\r\n\r\n <div class=\"dropzone-label\">\r\n <div class=\"svg-and-validation\">\r\n <!-- Upload icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"70\" height=\"70\" viewBox=\"0 0 70 70\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M58.333 48.8332C61.8957 45.8908 64.1663 41.4397 64.1663 36.4583C64.1663 27.5988 56.9843 20.4167 48.1247 20.4167C47.4874 20.4167 46.8912 20.0842 46.5675 19.5351C42.7641 13.0808 35.7417 8.75 27.708 8.75C15.6268 8.75 5.83301 18.5438 5.83301 30.625C5.83301 36.6511 8.26974 42.1082 12.2116 46.0644\"\r\n stroke=\"#4B5489\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M23.333 46.6667L34.9997 35M34.9997 35L46.6663 46.6667M34.9997 35V61.25\" stroke=\"#4B5489\"\r\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n\r\n <!-- Upload text -->\r\n <div class=\"bbsf-validation-msg text-center\">\r\n {{ utilityService.getResourceValue('Upload') }}\r\n </div>\r\n\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation-msg text-center\" *ngIf=\"validationMessage\" [innerHTML]=\"validationMessage\">\r\n </div>\r\n\r\n <div class=\"bbsf-validation-msg text-center text-danger\"\r\n *ngIf=\"validationCountMessage && options.isMultipleFile && options.maxNoOfFiles > 0\"\r\n [innerHTML]=\"validationCountMessage\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Hidden file input -->\r\n <input ng2FileSelect [uploader]=\"uploader\" [accept]=\"acceptedType\"\r\n class=\"fileSelector customFileUploadPlacment hidden v-required-multiplefiles d-none\"\r\n [attr.multiple]=\"options.isMultipleFile ? 'multiple' : null\" name=\"file\" type=\"file\" autocomplete=\"off\"\r\n (change)=\"onFileChange()\" [ngClass]=\"options.viewType === 1 ? '' : 'col-md-9'\" [id]=\"options.name\" #fileInput\r\n [class.is-invalid]=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\" />\r\n </div>\r\n <!-- Read-only state with no files -->\r\n <div *ngIf=\"options.isReadonly && (!options.value || (uploader.queue && uploader.queue.length === 0))\">\r\n <span class=\"readonly-view\">{{ utilityService.getResourceValue('NA') }}</span>\r\n </div>\r\n </div>\r\n <!-- Uploaded files list -->\r\n <div class=\"uploaded-items\" *ngIf=\"shouldShowFileList()\">\r\n <div class=\"btn-group\" *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n\r\n <!-- Async upload completed files -->\r\n <ng-container *ngIf=\"item?.progress === 100 && options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button *ngIf=\"getFileDownloadUrl(item); else noUrlTemplate\" type=\"button\"\r\n class=\"btn-download-file btn-sm btn-progress-upload\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- File name display when no URL available -->\r\n <ng-template #noUrlTemplate>\r\n <span class=\"btn-download-file btn-sm btn-progress-upload\" [title]=\"getFileName(item)\">\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </span>\r\n </ng-template>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <!-- Delete icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\r\n <path opacity=\"0.4\"\r\n d=\"M9.33301 3.70584V3.26663C9.33301 2.65166 9.33301 2.34419 9.20587 2.1093C9.09405 1.9027 8.91555 1.73471 8.69604 1.62944C8.44647 1.50977 8.11977 1.50977 7.46638 1.50977H6.53305C5.87965 1.50977 5.55296 1.50977 5.30339 1.62944C5.08387 1.73471 4.90539 1.9027 4.79354 2.1093C4.66638 2.34419 4.66638 2.65166 4.66638 3.26663V3.70584\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path\r\n d=\"M1.75 3.70605H12.25M11.0834 3.70605V9.8551C11.0834 10.7775 11.0834 11.2387 10.8926 11.591C10.7248 11.901 10.4571 12.1529 10.1278 12.3109C9.75345 12.4904 9.26345 12.4904 8.28334 12.4904H5.71666C4.73658 12.4904 4.24653 12.4904 3.87218 12.3109C3.5429 12.1529 3.27519 11.901 3.10741 11.591C2.91666 11.2387 2.91666 10.7775 2.91666 9.8551V3.70605\"\r\n stroke=\"#D83731\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </button>\r\n </ng-container>\r\n\r\n <!-- Sync upload files -->\r\n <ng-container *ngIf=\"!options.isUploadFileAsync\">\r\n <!-- Download link - always visible -->\r\n <button type=\"button\" class=\"btn btn-download-file btn-sm\" (click)=\"downloadFile(item)\"\r\n [title]=\"'Download ' + getFileName(item)\">\r\n <!-- Download icon -->\r\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path\r\n d=\"M21 22H3C2.4 22 2 21.6 2 21C2 20.4 2.4 20 3 20H21C21.6 20 22 20.4 22 21C22 21.6 21.6 22 21 22ZM13 13.4V3C13 2.4 12.6 2 12 2C11.4 2 11 2.4 11 3V13.4H13Z\"\r\n fill=\"currentColor\"></path>\r\n <path opacity=\"0.3\" d=\"M7 13.4H17L12.7 17.7C12.3 18.1 11.7 18.1 11.3 17.7L7 13.4Z\" fill=\"currentColor\">\r\n </path>\r\n </svg>\r\n <span class=\"file-name\">{{ getFileName(item) }}</span>\r\n </button>\r\n\r\n <!-- Remove button - only show when not readonly and not disabled -->\r\n <button *ngIf=\"isRemoveEnabled()\" class=\"btn btn-download-file btn-sm btn-danger\" type=\"button\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\" [attr.aria-label]=\"'Remove ' + getFileName(item)\"\r\n [title]=\"'Remove ' + getFileName(item)\">\r\n <i class=\"fa fa-times px-0\" aria-hidden=\"true\"></i>\r\n </button>\r\n </ng-container>\r\n </div>\r\n </div>\r\n <!-- File upload progress indicators -->\r\n <div *ngFor=\"let item of uploader.queue; trackBy: trackByFunction\">\r\n <div class=\"upload-items\" [ngClass]=\"{ 'mt-4': options.isMultipleFile }\"\r\n *ngIf=\"item?.progress < 100 && options.isUploadFileAsync && !options.isReadonly\">\r\n\r\n <div class=\"upload-items-toolbar\">\r\n <h4>{{ getFileName(item) }}</h4>\r\n <button *ngIf=\"isRemoveEnabled()\" type=\"button\" class=\"btn-cancel-upload\"\r\n (click)=\"item.remove(); removeFromControlValue(item)\"\r\n [attr.aria-label]=\"'Cancel upload for ' + getFileName(item)\">\r\n <!-- Cancel icon -->\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\">\r\n <g clip-path=\"url(#clip0_1324_13216)\">\r\n <path opacity=\"0.4\"\r\n d=\"M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z\"\r\n stroke=\"#DBE1F0\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n <path d=\"M11.25 6.75L6.75 11.25M6.75 6.75L11.25 11.25\" stroke=\"#DBE1F0\" stroke-width=\"2\"\r\n stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </g>\r\n <defs>\r\n <clipPath id=\"clip0_1324_13216\">\r\n <rect width=\"18\" height=\"18\" fill=\"white\" />\r\n </clipPath>\r\n </defs>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <div class=\"progress\">\r\n <div class=\"progress-bar\" role=\"progressbar\" [attr.aria-valuenow]=\"item?.progress\" aria-valuemin=\"0\"\r\n aria-valuemax=\"100\" [class.file-uploaded]=\"item?.progress < 100\" [style.width.%]=\"item?.progress\"\r\n *ngIf=\"item?.progress > 0\">\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Validation and description section -->\r\n <div class=\"subtext-container\" *ngIf=\"!options.isReadonly\">\r\n <!-- Validation messages -->\r\n <div class=\"bbsf-validation\" *ngIf=\"fileUploadFormControl.invalid && fileUploadFormControl.touched\">\r\n {{ getErrorValidation(fileUploadFormControl.errors | keyvalue) }}\r\n </div>\r\n\r\n <!-- Control description -->\r\n <div class=\"bbsf-control-desc\" *ngIf=\"options.labelDescription\">\r\n {{ options.labelDescription }}\r\n </div>\r\n\r\n <!-- Reset error state -->\r\n <div *ngIf=\"(group.valid && group.dirty && group.touched) || (group.untouched && group.invalid && group.dirty)\">\r\n {{ resetError() }}\r\n </div>\r\n </div>\r\n</div>" }]
|
|
2667
3127
|
}], ctorParameters: () => [{ type: i2.ControlContainer, decorators: [{
|
|
2668
3128
|
type: Optional
|
|
2669
3129
|
}] }, { type: i2.FormGroupDirective }, { type: ControlUtility }, { type: i3.UtilityService }, { type: i3.ControlValidationService }, { type: GlobalSettings }, { type: FileUploadService }], propDecorators: { fileInput: [{
|
|
@@ -9251,6 +9711,7 @@ class BBSFControlsModule {
|
|
|
9251
9711
|
NgbModal,
|
|
9252
9712
|
NgbActiveModal,
|
|
9253
9713
|
DatePipe,
|
|
9714
|
+
KeyValuePipe,
|
|
9254
9715
|
BBSFDateTimePipe,
|
|
9255
9716
|
BBSFDatePipe,
|
|
9256
9717
|
RenderComponentService,
|
|
@@ -9374,6 +9835,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
9374
9835
|
NgbModal,
|
|
9375
9836
|
NgbActiveModal,
|
|
9376
9837
|
DatePipe,
|
|
9838
|
+
KeyValuePipe,
|
|
9377
9839
|
BBSFDateTimePipe,
|
|
9378
9840
|
BBSFDatePipe,
|
|
9379
9841
|
RenderComponentService,
|
|
@@ -9748,6 +10210,7 @@ class FileDTO {
|
|
|
9748
10210
|
this.bytes = undefined;
|
|
9749
10211
|
this.fileSizeInMB = undefined;
|
|
9750
10212
|
this.fileURL = undefined;
|
|
10213
|
+
this.fullFileURL = undefined;
|
|
9751
10214
|
this.isNew = false;
|
|
9752
10215
|
}
|
|
9753
10216
|
}
|