cat-documents-ng 0.2.62 → 0.2.64
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/Shared/constant/SHARED.d.ts +2 -0
- package/fesm2022/cat-documents-ng.mjs +231 -29
- package/fesm2022/cat-documents-ng.mjs.map +1 -1
- package/lib/document/components/document-search/document-search.component.d.ts +4 -0
- package/lib/document/components/document-upload/document-upload.component.d.ts +27 -3
- package/lib/document/services/document-upload.service.d.ts +14 -3
- package/package.json +1 -1
- package/src/assets/config/api.config.json +20 -0
|
@@ -284,6 +284,8 @@ class SHARED {
|
|
|
284
284
|
static CATAGORIES = 'catagories';
|
|
285
285
|
static DOCUMENTS = 'Documents';
|
|
286
286
|
static UPLOAD_FAILED = 'Upload failed';
|
|
287
|
+
static USER_LIST = 'userList';
|
|
288
|
+
static CATEGORIES = 'categories';
|
|
287
289
|
static DOCUMENT_DELETED_SUCCESSFULLY = 'Document deleted successfully';
|
|
288
290
|
static Menu = [
|
|
289
291
|
{
|
|
@@ -2264,10 +2266,9 @@ class DocumentUploadService {
|
|
|
2264
2266
|
*/
|
|
2265
2267
|
uploadCompleted = new EventEmitter();
|
|
2266
2268
|
/**
|
|
2267
|
-
*
|
|
2268
|
-
* @type {*}
|
|
2269
|
+
* Map to track upload progress for multiple files
|
|
2269
2270
|
*/
|
|
2270
|
-
|
|
2271
|
+
uploadProgress = new Map();
|
|
2271
2272
|
/**
|
|
2272
2273
|
* Represent contextId
|
|
2273
2274
|
* @type {string}
|
|
@@ -2301,16 +2302,24 @@ class DocumentUploadService {
|
|
|
2301
2302
|
* @returns {void}
|
|
2302
2303
|
*/
|
|
2303
2304
|
handleTemplatedUpload(file, contextId) {
|
|
2305
|
+
console.log(`=== DOCUMENT UPLOAD SERVICE: STARTING UPLOAD ===`);
|
|
2306
|
+
console.log(`File: ${file.name}, Size: ${file.size}, ContextId: ${contextId}`);
|
|
2307
|
+
// Track this file's upload progress
|
|
2308
|
+
this.uploadProgress.set(file, 10);
|
|
2309
|
+
console.log(`Upload progress tracking started for: ${file.name}`);
|
|
2304
2310
|
let formsData = this.handleCreateFormData(file, contextId);
|
|
2305
2311
|
if (!formsData) {
|
|
2312
|
+
console.error(`Failed to create FormData for file: ${file.name}`);
|
|
2306
2313
|
this.messageService.add({ severity: SHARED.SEVERITY, summary: SHARED.UPLOAD_ERROR_SUMMERY, detail: SHARED.UPLOAD_ERROR_DETAILS });
|
|
2314
|
+
this.uploadProgress.delete(file);
|
|
2307
2315
|
return;
|
|
2308
2316
|
}
|
|
2309
|
-
|
|
2317
|
+
console.log(`FormData created successfully for file: ${file.name}`);
|
|
2310
2318
|
this.documentUploadStore.setMessage([{
|
|
2311
2319
|
severity: 'info',
|
|
2312
|
-
detail:
|
|
2320
|
+
detail: `Uploading document: ${file.name}...`
|
|
2313
2321
|
}]);
|
|
2322
|
+
console.log(`Calling document service create method for file: ${file.name}`);
|
|
2314
2323
|
this.documentService.create(formsData)
|
|
2315
2324
|
.subscribe({
|
|
2316
2325
|
/**
|
|
@@ -2319,16 +2328,17 @@ class DocumentUploadService {
|
|
|
2319
2328
|
* @returns {void}
|
|
2320
2329
|
*/
|
|
2321
2330
|
next: (event) => {
|
|
2331
|
+
console.log(`=== UPLOAD SUCCESS FOR FILE: ${file.name} ===`);
|
|
2332
|
+
console.log(`Response received:`, event);
|
|
2322
2333
|
this.documentUploadStore.setUploadedDocumentFiles(event);
|
|
2323
2334
|
this.documentUploadStore.setMessage([{
|
|
2324
2335
|
severity: SHARED.SUCCESS_SEVERITY,
|
|
2325
|
-
detail:
|
|
2336
|
+
detail: `Successfully uploaded: ${file.name}`
|
|
2326
2337
|
}]);
|
|
2327
|
-
|
|
2338
|
+
console.log(`Emitting uploadCompleted event for file: ${file.name}`);
|
|
2328
2339
|
this.uploadCompleted.emit({ file: file, response: event });
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
}
|
|
2340
|
+
this.uploadProgress.delete(file);
|
|
2341
|
+
console.log(`Upload completed and cleaned up for file: ${file.name}`);
|
|
2332
2342
|
},
|
|
2333
2343
|
/**
|
|
2334
2344
|
* Handles the error event during file upload.
|
|
@@ -2336,9 +2346,13 @@ class DocumentUploadService {
|
|
|
2336
2346
|
* @param {any} error - The error object returned by the upload service.
|
|
2337
2347
|
*/
|
|
2338
2348
|
error: (error) => {
|
|
2349
|
+
console.error(`=== UPLOAD ERROR FOR FILE: ${file.name} ===`);
|
|
2350
|
+
console.error('Error details:', error);
|
|
2339
2351
|
this.messageService.add({ severity: SHARED.SEVERITY, summary: SHARED.UPLOAD_SUMMERY, detail: error?.message });
|
|
2352
|
+
this.uploadProgress.delete(file);
|
|
2340
2353
|
},
|
|
2341
2354
|
});
|
|
2355
|
+
console.log(`=== DOCUMENT UPLOAD SERVICE: UPLOAD INITIATED FOR: ${file.name} ===`);
|
|
2342
2356
|
}
|
|
2343
2357
|
/**
|
|
2344
2358
|
* Get the file and contextId
|
|
@@ -2347,7 +2361,6 @@ class DocumentUploadService {
|
|
|
2347
2361
|
*/
|
|
2348
2362
|
getUploadFileData(file, contextId) {
|
|
2349
2363
|
if (file && contextId) {
|
|
2350
|
-
this.uploadedFile = file;
|
|
2351
2364
|
this.contextId = contextId;
|
|
2352
2365
|
}
|
|
2353
2366
|
}
|
|
@@ -2369,13 +2382,29 @@ class DocumentUploadService {
|
|
|
2369
2382
|
if (uploadedFile) {
|
|
2370
2383
|
let formData = new FormData();
|
|
2371
2384
|
formData.append(SHARED.FILE, uploadedFile, uploadedFile.name);
|
|
2372
|
-
formData.append(SHARED.CONTEXT_ID, this.contextId);
|
|
2385
|
+
formData.append(SHARED.CONTEXT_ID, contextId || this.contextId);
|
|
2373
2386
|
return formData;
|
|
2374
2387
|
}
|
|
2375
2388
|
else {
|
|
2376
2389
|
return null;
|
|
2377
2390
|
}
|
|
2378
2391
|
}
|
|
2392
|
+
/**
|
|
2393
|
+
* Get upload progress for a specific file
|
|
2394
|
+
* @param file - The file to get progress for
|
|
2395
|
+
* @returns The upload progress percentage or undefined if not tracked
|
|
2396
|
+
*/
|
|
2397
|
+
getUploadProgress(file) {
|
|
2398
|
+
return this.uploadProgress.get(file);
|
|
2399
|
+
}
|
|
2400
|
+
/**
|
|
2401
|
+
* Check if a file is currently being uploaded
|
|
2402
|
+
* @param file - The file to check
|
|
2403
|
+
* @returns True if the file is being uploaded
|
|
2404
|
+
*/
|
|
2405
|
+
isFileUploading(file) {
|
|
2406
|
+
return this.uploadProgress.has(file);
|
|
2407
|
+
}
|
|
2379
2408
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DocumentUploadService, deps: [{ token: DocumentService }, { token: DocumentStore }, { token: i3.MessageService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2380
2409
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DocumentUploadService, providedIn: 'root' });
|
|
2381
2410
|
}
|
|
@@ -2896,6 +2925,24 @@ class DocumentUploadComponent {
|
|
|
2896
2925
|
this.businessService = businessService;
|
|
2897
2926
|
this.formService = formService;
|
|
2898
2927
|
this.dataService = dataService;
|
|
2928
|
+
// Set up global upload completion listener for debugging
|
|
2929
|
+
this.setupGlobalUploadListener();
|
|
2930
|
+
}
|
|
2931
|
+
/**
|
|
2932
|
+
* Sets up a global listener for all upload completion events.
|
|
2933
|
+
* This helps debug issues with multiple file uploads.
|
|
2934
|
+
*/
|
|
2935
|
+
setupGlobalUploadListener() {
|
|
2936
|
+
this.documentUpload.uploadCompleted
|
|
2937
|
+
.pipe(takeUntil(this.destroy$))
|
|
2938
|
+
.subscribe(({ file, response }) => {
|
|
2939
|
+
console.log(`=== GLOBAL UPLOAD COMPLETION EVENT ===`);
|
|
2940
|
+
console.log(`File: ${file?.name}`);
|
|
2941
|
+
console.log(`Response:`, response);
|
|
2942
|
+
console.log(`Current time: ${new Date().toISOString()}`);
|
|
2943
|
+
// Log current upload status
|
|
2944
|
+
this.logUploadStatus();
|
|
2945
|
+
});
|
|
2899
2946
|
}
|
|
2900
2947
|
/**
|
|
2901
2948
|
* Handles changes in assignment type selection.
|
|
@@ -2935,8 +2982,21 @@ class DocumentUploadComponent {
|
|
|
2935
2982
|
* @param event - Event containing the selected files
|
|
2936
2983
|
*/
|
|
2937
2984
|
onSelectedFiles(event) {
|
|
2938
|
-
|
|
2985
|
+
console.log('=== FILE SELECTION EVENT ===');
|
|
2986
|
+
console.log('Number of files selected:', event.currentFiles.length);
|
|
2987
|
+
console.log('Files:', event.currentFiles.map(f => ({ name: f.name, size: f.size })));
|
|
2988
|
+
// Process each file immediately without delays
|
|
2989
|
+
event.currentFiles.forEach((file, index) => {
|
|
2990
|
+
console.log(`Processing file ${index + 1}/${event.currentFiles.length}: ${file.name}`);
|
|
2991
|
+
this.handleTemplatedUpload(file);
|
|
2992
|
+
});
|
|
2993
|
+
console.log('All files processed, clearing file uploader');
|
|
2939
2994
|
this.fileUploader.clear();
|
|
2995
|
+
// Log upload status after processing all files
|
|
2996
|
+
setTimeout(() => {
|
|
2997
|
+
console.log('=== STATUS AFTER PROCESSING ALL FILES ===');
|
|
2998
|
+
this.logUploadStatus();
|
|
2999
|
+
}, 1000);
|
|
2940
3000
|
}
|
|
2941
3001
|
/**
|
|
2942
3002
|
* Loads the list of applicants for the current context.
|
|
@@ -2992,16 +3052,32 @@ class DocumentUploadComponent {
|
|
|
2992
3052
|
* @param file - The file to be uploaded
|
|
2993
3053
|
*/
|
|
2994
3054
|
handleTemplatedUpload(file) {
|
|
2995
|
-
|
|
3055
|
+
console.log(`=== STARTING UPLOAD FOR FILE: ${file.name} ===`);
|
|
3056
|
+
if (!this.formService.validateContextId(this.contextId, 'Context ID is required for upload.')) {
|
|
3057
|
+
console.error(`Context ID validation failed for file: ${file.name}`);
|
|
2996
3058
|
return;
|
|
3059
|
+
}
|
|
3060
|
+
console.log(`File validation passed for: ${file.name}`);
|
|
3061
|
+
console.log(`Context ID: ${this.contextId}`);
|
|
3062
|
+
// Set initial progress
|
|
2997
3063
|
this.fileProgress.set(file, SHARED.UPLOAD_PROGRESS_10);
|
|
3064
|
+
console.log(`Progress set to 10% for file: ${file.name}`);
|
|
3065
|
+
// Set up upload listener before starting upload
|
|
3066
|
+
console.log(`Setting up upload listener for file: ${file.name}`);
|
|
2998
3067
|
this.setupFileUploadListener(file);
|
|
3068
|
+
// Start the upload
|
|
3069
|
+
console.log(`Initiating upload service call for file: ${file.name}`);
|
|
2999
3070
|
this.documentUpload.handleTemplatedUpload(file, this.contextId);
|
|
3071
|
+
// Create uploaded file object
|
|
3000
3072
|
const formattedSize = this.businessService.formatFileSize(file.size, this.config);
|
|
3001
3073
|
const uploadedFile = this.businessService.createUploadedFile(file, formattedSize);
|
|
3002
3074
|
uploadedFile.progress = SHARED.UPLOAD_PROGRESS_10;
|
|
3003
3075
|
this.uploadedFiles.push(uploadedFile);
|
|
3076
|
+
console.log(`Uploaded file object created for: ${file.name}`);
|
|
3077
|
+
console.log(`Total uploaded files count: ${this.uploadedFiles.length}`);
|
|
3004
3078
|
this.validateForm();
|
|
3079
|
+
this.cdr.detectChanges();
|
|
3080
|
+
console.log(`=== UPLOAD INITIATED SUCCESSFULLY FOR: ${file.name} ===`);
|
|
3005
3081
|
}
|
|
3006
3082
|
/**
|
|
3007
3083
|
* Removes a document from the uploaded files list.
|
|
@@ -3033,6 +3109,58 @@ class DocumentUploadComponent {
|
|
|
3033
3109
|
const isDisabled = this.businessService.isSaveButtonDisabled(this.selectedAssignmentType, this.selectedCategory, this.selectedDocumentType, this.selectedApplicant, this.uploadedFiles, this.isSaving);
|
|
3034
3110
|
return isDisabled;
|
|
3035
3111
|
}
|
|
3112
|
+
/**
|
|
3113
|
+
* Checks the upload service status for debugging purposes.
|
|
3114
|
+
*/
|
|
3115
|
+
checkUploadServiceStatus() {
|
|
3116
|
+
console.log('=== UPLOAD SERVICE STATUS ===');
|
|
3117
|
+
console.log('Document upload service:', this.documentUpload);
|
|
3118
|
+
console.log('Upload completed event emitter:', this.documentUpload.uploadCompleted);
|
|
3119
|
+
// Check if the service has any active uploads
|
|
3120
|
+
if (this.documentUpload.getUploadProgress) {
|
|
3121
|
+
this.uploadedFiles.forEach(uploadedFile => {
|
|
3122
|
+
const serviceProgress = this.documentUpload.getUploadProgress(uploadedFile.file);
|
|
3123
|
+
const isUploading = this.documentUpload.isFileUploading(uploadedFile.file);
|
|
3124
|
+
console.log(`File: ${uploadedFile.file.name}`);
|
|
3125
|
+
console.log(` - Service progress: ${serviceProgress}`);
|
|
3126
|
+
console.log(` - Service isUploading: ${isUploading}`);
|
|
3127
|
+
});
|
|
3128
|
+
}
|
|
3129
|
+
console.log('=== END SERVICE STATUS ===');
|
|
3130
|
+
}
|
|
3131
|
+
/**
|
|
3132
|
+
* Logs the current upload status for debugging purposes.
|
|
3133
|
+
*/
|
|
3134
|
+
logUploadStatus() {
|
|
3135
|
+
console.log('=== CURRENT UPLOAD STATUS ===');
|
|
3136
|
+
console.log('Total uploaded files:', this.uploadedFiles.length);
|
|
3137
|
+
console.log('File progress map size:', this.fileProgress.size);
|
|
3138
|
+
this.uploadedFiles.forEach((uploadedFile, index) => {
|
|
3139
|
+
const progress = this.fileProgress.get(uploadedFile.file);
|
|
3140
|
+
console.log(`File ${index + 1}: ${uploadedFile.file.name}`);
|
|
3141
|
+
console.log(` - Progress: ${progress}%`);
|
|
3142
|
+
console.log(` - Uploaded file progress: ${uploadedFile.progress}%`);
|
|
3143
|
+
console.log(` - Has response: ${!!uploadedFile.uploadResponse}`);
|
|
3144
|
+
});
|
|
3145
|
+
// Check for orphaned progress entries
|
|
3146
|
+
const orphanedFiles = Array.from(this.fileProgress.keys()).filter(file => !this.uploadedFiles.some(uf => uf.file === file));
|
|
3147
|
+
if (orphanedFiles.length > 0) {
|
|
3148
|
+
console.warn('=== ORPHANED PROGRESS ENTRIES ===');
|
|
3149
|
+
orphanedFiles.forEach(file => {
|
|
3150
|
+
console.warn(`Orphaned file: ${file.name} with progress: ${this.fileProgress.get(file)}%`);
|
|
3151
|
+
});
|
|
3152
|
+
}
|
|
3153
|
+
console.log('=== END UPLOAD STATUS ===');
|
|
3154
|
+
}
|
|
3155
|
+
/**
|
|
3156
|
+
* Checks if all files have completed uploading.
|
|
3157
|
+
* @returns True if all files have completed uploading, false otherwise
|
|
3158
|
+
*/
|
|
3159
|
+
areAllFilesUploaded() {
|
|
3160
|
+
if (this.uploadedFiles.length === 0)
|
|
3161
|
+
return false;
|
|
3162
|
+
return this.uploadedFiles.every(file => this.fileProgress.get(file.file) === SHARED.UPLOAD_PROGRESS_100);
|
|
3163
|
+
}
|
|
3036
3164
|
/**
|
|
3037
3165
|
* Gets the upload progress for a specific file.
|
|
3038
3166
|
* @param file - The file to get progress for
|
|
@@ -3142,11 +3270,11 @@ class DocumentUploadComponent {
|
|
|
3142
3270
|
this.onUploadSuccess.emit();
|
|
3143
3271
|
}
|
|
3144
3272
|
/**
|
|
3145
|
-
* Handles
|
|
3273
|
+
* Handles save operation error.
|
|
3146
3274
|
* Resets saving state.
|
|
3147
|
-
* @param error - The error that occurred during
|
|
3275
|
+
* @param error - The error that occurred during save operation
|
|
3148
3276
|
*/
|
|
3149
|
-
|
|
3277
|
+
handleSaveError(error) {
|
|
3150
3278
|
this.isSaving = false;
|
|
3151
3279
|
}
|
|
3152
3280
|
/**
|
|
@@ -3179,7 +3307,7 @@ class DocumentUploadComponent {
|
|
|
3179
3307
|
.pipe(takeUntil(this.destroy$))
|
|
3180
3308
|
.subscribe({
|
|
3181
3309
|
next: (response) => this.handleUploadSuccess(response),
|
|
3182
|
-
error: (error) => this.
|
|
3310
|
+
error: (error) => this.handleSaveError(error)
|
|
3183
3311
|
});
|
|
3184
3312
|
}
|
|
3185
3313
|
/**
|
|
@@ -3188,20 +3316,75 @@ class DocumentUploadComponent {
|
|
|
3188
3316
|
* @param file - The file to monitor for upload completion
|
|
3189
3317
|
*/
|
|
3190
3318
|
setupFileUploadListener(file) {
|
|
3191
|
-
|
|
3192
|
-
|
|
3319
|
+
console.log(`=== SETTING UP UPLOAD LISTENER FOR: ${file.name} ===`);
|
|
3320
|
+
// Create a unique identifier for this file to avoid conflicts
|
|
3321
|
+
const fileId = `${file.name}-${file.size}-${file.lastModified}`;
|
|
3322
|
+
console.log(`File ID created: ${fileId}`);
|
|
3323
|
+
// Store the file ID in the file object for tracking
|
|
3324
|
+
file.fileId = fileId;
|
|
3325
|
+
// Set up a one-time listener for this specific file
|
|
3326
|
+
const subscription = this.documentUpload.uploadCompleted
|
|
3327
|
+
.pipe(takeUntil(this.destroy$))
|
|
3328
|
+
.subscribe(({ file: uploadedFile, response }) => {
|
|
3329
|
+
console.log(`=== UPLOAD COMPLETION EVENT RECEIVED ===`);
|
|
3330
|
+
console.log(`Event file: ${uploadedFile?.name}`);
|
|
3331
|
+
console.log(`Tracking file: ${file.name}`);
|
|
3332
|
+
console.log(`File ID match: ${uploadedFile?.fileId === fileId}`);
|
|
3333
|
+
console.log(`Direct file match: ${uploadedFile === file}`);
|
|
3334
|
+
// Check if this is the file we're tracking
|
|
3335
|
+
if (uploadedFile === file || uploadedFile.fileId === fileId) {
|
|
3336
|
+
console.log(`=== MATCH FOUND - UPDATING PROGRESS FOR: ${file.name} ===`);
|
|
3337
|
+
// Update progress to 100%
|
|
3193
3338
|
this.fileProgress.set(file, SHARED.UPLOAD_PROGRESS_100);
|
|
3339
|
+
console.log(`Progress updated to 100% for file: ${file.name}`);
|
|
3340
|
+
// Find and update the uploaded file object
|
|
3194
3341
|
const uploadedFileObj = this.uploadedFiles.find(uf => uf.file === file);
|
|
3195
3342
|
if (uploadedFileObj) {
|
|
3196
3343
|
uploadedFileObj.uploadResponse = response;
|
|
3197
3344
|
uploadedFileObj.progress = SHARED.UPLOAD_PROGRESS_100;
|
|
3198
3345
|
uploadedFileObj.url = response?.url;
|
|
3199
3346
|
uploadedFileObj.contentType = response?.contentType;
|
|
3347
|
+
console.log(`Uploaded file object updated for: ${file.name}`);
|
|
3348
|
+
}
|
|
3349
|
+
else {
|
|
3350
|
+
console.warn(`Could not find uploaded file object for: ${file.name}`);
|
|
3200
3351
|
}
|
|
3352
|
+
// Trigger change detection and emit validation change
|
|
3201
3353
|
this.cdr.detectChanges();
|
|
3202
3354
|
this.onFormValidationChange.emit();
|
|
3355
|
+
// Unsubscribe from this specific file's upload completion
|
|
3356
|
+
subscription.unsubscribe();
|
|
3357
|
+
console.log(`Subscription unsubscribed for file: ${file.name}`);
|
|
3358
|
+
console.log(`=== FILE UPLOAD COMPLETED SUCCESSFULLY: ${file.name} ===`);
|
|
3359
|
+
}
|
|
3360
|
+
else {
|
|
3361
|
+
console.log(`Event not for this file: ${file.name}`);
|
|
3203
3362
|
}
|
|
3204
3363
|
});
|
|
3364
|
+
console.log(`Upload listener setup completed for file: ${file.name}`);
|
|
3365
|
+
}
|
|
3366
|
+
/**
|
|
3367
|
+
* Handles upload error for a specific file.
|
|
3368
|
+
* @param file - The file that encountered an error
|
|
3369
|
+
* @param errorMessage - The error message
|
|
3370
|
+
*/
|
|
3371
|
+
handleUploadError(file, errorMessage) {
|
|
3372
|
+
console.error(`Upload error for file: ${file.name}: ${errorMessage}`);
|
|
3373
|
+
// Mark file as having an error
|
|
3374
|
+
this.fileProgress.set(file, -1);
|
|
3375
|
+
// Update the uploaded file object
|
|
3376
|
+
const uploadedFileObj = this.uploadedFiles.find(uf => uf.file === file);
|
|
3377
|
+
if (uploadedFileObj) {
|
|
3378
|
+
uploadedFileObj.progress = -1;
|
|
3379
|
+
}
|
|
3380
|
+
// Trigger change detection
|
|
3381
|
+
this.cdr.detectChanges();
|
|
3382
|
+
// Show error message
|
|
3383
|
+
this.messageService.add({
|
|
3384
|
+
severity: 'error',
|
|
3385
|
+
summary: 'Upload Failed',
|
|
3386
|
+
detail: `Failed to upload ${file.name}: ${errorMessage}`
|
|
3387
|
+
});
|
|
3205
3388
|
}
|
|
3206
3389
|
/**
|
|
3207
3390
|
* Handles errors during data loading operations.
|
|
@@ -3244,11 +3427,11 @@ class DocumentUploadComponent {
|
|
|
3244
3427
|
this.dataService.destroy();
|
|
3245
3428
|
}
|
|
3246
3429
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DocumentUploadComponent, deps: [{ token: DocumentUploadService }, { token: DocumentService }, { token: i3.PrimeNGConfig }, { token: FileFormatService }, { token: i3.MessageService }, { token: i0.ChangeDetectorRef }, { token: DocumentUploadBusinessService }, { token: DocumentUploadFormService }, { token: DocumentUploadDataService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3247
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DocumentUploadComponent, isStandalone: false, selector: "lib-document-upload", inputs: { contextId: "contextId" }, outputs: { onFormValidationChange: "onFormValidationChange", onUploadSuccess: "onUploadSuccess" }, viewQueries: [{ propertyName: "fileUploader", first: true, predicate: ["fileUploader"], descendants: true }], ngImport: i0, template: "<div class=\"document-upload-container\">\r\n <!-- Assignment Section -->\r\n <div class=\"assignment-section\">\r\n <h4>Assign to Applicant(s) or Application</h4>\r\n <div class=\"radio-group\">\r\n <div class=\"radio-item\">\r\n <p-radioButton \r\n name=\"assignmentType\" \r\n value=\"Applicant\" \r\n [(ngModel)]=\"selectedAssignmentType\"\r\n (onClick)=\"onAssignmentTypeChange()\"\r\n [inputId]=\"'applicant'\"\r\n ></p-radioButton>\r\n <label [for]=\"'applicant'\" class=\"radio-label\">Applicant(s)</label>\r\n </div>\r\n <div class=\"radio-item\">\r\n <p-radioButton \r\n name=\"assignmentType\" \r\n value=\"Application\" \r\n [(ngModel)]=\"selectedAssignmentType\"\r\n (onClick)=\"onAssignmentTypeChange()\"\r\n [inputId]=\"'application'\"\r\n ></p-radioButton>\r\n <label [for]=\"'application'\" class=\"radio-label\">Application</label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Applicant Selection (only shown when Applicant is selected) -->\r\n <div class=\"applicant-section\" *ngIf=\"selectedAssignmentType === 'Applicant'\">\r\n <h4>Select Applicant(s)</h4>\r\n <div class=\"grid\">\r\n <div \r\n *ngFor=\"let applicant of filteredApplicantList\" \r\n class=\"applicant-item col-12 md:col-6\"\r\n >\r\n <p-radioButton \r\n name=\"selectedApplicant\"\r\n [value]=\"applicant._id\"\r\n [(ngModel)]=\"selectedApplicant\"\r\n [inputId]=\"'applicant-' + applicant._id\"\r\n (onClick)=\"onApplicantSelectionChange()\"\r\n ></p-radioButton>\r\n <label [for]=\"'applicant-' + applicant._id\" class=\"applicant-label\">\r\n {{ applicant.name }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Category Selection -->\r\n <div class=\"category-section\">\r\n <h4>Category</h4>\r\n <p-dropdown\r\n [options]=\"categoryOptions\"\r\n [(ngModel)]=\"selectedCategory\"\r\n placeholder=\"Select Category type\"\r\n optionLabel=\"label\"\r\n optionValue=\"_id\"\r\n (onChange)=\"onCategoryChange()\"\r\n [disabled]=\"!categoryOptions.length\"\r\n class=\"w-full\"\r\n ></p-dropdown>\r\n </div>\r\n\r\n <!-- Document Type Selection -->\r\n <div class=\"document-type-section\">\r\n <h4>Document Type</h4>\r\n <p-dropdown\r\n [options]=\"documentTypeOptions\"\r\n [(ngModel)]=\"selectedDocumentType\"\r\n placeholder=\"Select Document type\"\r\n optionLabel=\"label\"\r\n optionValue=\"_id\"\r\n (onChange)=\"onDocumentTypeChange()\"\r\n [disabled]=\"!documentTypeOptions.length || !selectedCategory\"\r\n class=\"w-full\"\r\n ></p-dropdown>\r\n </div>\r\n\r\n <!-- File Upload Section -->\r\n <div class=\"file-upload-section\">\r\n <h4>Upload Documents</h4>\r\n <div class=\"grid\">\r\n <div class=\"col-12 md:col-12\">\r\n <p-fileUpload \r\n #fileUploader \r\n [multiple]=\"true\" \r\n auto=\"true\" \r\n accept=\"image/png,application/pdf\" \r\n maxFileSize=\"26214400\"\r\n (onSelect)=\"onSelectedFiles($event)\"\r\n >\r\n <ng-template pTemplate=\"header\" let-chooseCallback=\"chooseCallback\" let-clearCallback=\"clearCallback\">\r\n <div class=\"docHeader p-2 flex flex-wrap justify-content-between align-items-center flex-1 gap-2\">\r\n <div class=\"flex gap-2\">\r\n <p-button \r\n (onClick)=\"choose($event, chooseCallback)\" \r\n icon=\"pi pi-images\" \r\n [rounded]=\"true\"\r\n [outlined]=\"true\" \r\n />\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template pTemplate=\"content\" let-removeFileCallback=\"removeFileCallback\"\r\n let-removeUploadedFileCallback=\"removeUploadedFileCallback\">\r\n <div class=\"col-12 md:col-12 p-0\">\r\n <div class=\"col-12 md:col-12 p-0\" *ngIf=\"uploadedFiles.length > 0\">\r\n <div *ngFor=\"let uploadedFile of uploadedFiles; let i = index\"\r\n class=\"m-0 flex flex-column align-items-center gap-1 mt-3\">\r\n <div class=\"col-12 md:col-12 p-0 flex documentInfo\">\r\n <div class=\"documentImage\">\r\n <img src=\"../../../../assets/images/document.png\" [alt]=\"uploadedFile.file.name\" width=\"45\" height=\"50\"\r\n class=\"object-contain\" />\r\n </div>\r\n <div class=\"flex w-full flex-column mt-2 ml-2\">\r\n <div class=\"flex justify-content-between\">\r\n <div style=\"font-weight: bold;font-size: 14px\">\r\n {{ uploadedFile.file.name }}\r\n </div>\r\n <i class=\"pi pi-times cursor-pointer\" (click)=\"handleDocumentRemove(uploadedFile.file,i)\"></i>\r\n </div>\r\n <div class=\"flex justify-content-between mt-1\">\r\n <div style=\"color: #676B89; font-size: 12px; color: green;\" class=\"pi pi-verified\"> \r\n {{ uploadedFile.formattedSize }}\r\n </div>\r\n <div class=\"white-space-nowrap\" style=\"color: #0F8BFD; font-family: 14px;\"> \r\n {{ uploadedFile.progress }} % \r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-12 md:col-12 p-0\">\r\n <p-progressBar \r\n [value]=\"uploadedFile.progress\" \r\n [showValue]=\"false\" \r\n styleClass=\"h-1/2rem md:ml-auto relative\"\r\n [ngClass]=\"{ 'exceeded-progress-bar': uploadedFile.progress > 100 }\"\r\n >\r\n </p-progressBar>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template pTemplate=\"empty\" let-chooseCallback=\"chooseCallback\">\r\n <div *ngIf=\"!uploadedFiles.length\" class=\"flex align-items-center justify-content-center flex-column\"\r\n (click)=\"triggerFileUpload()\">\r\n <i class=\"pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400\"></i>\r\n <p class=\"mt-4 mb-0\">Drag and drop files here to upload.</p>\r\n </div>\r\n </ng-template>\r\n <ng-template pTemplate=\"file\"> </ng-template>\r\n </p-fileUpload>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".flex{display:flex}.items-center{align-items:center}.justify-center{justify-content:center}.flex-col{flex-direction:column}.text-muted-color{color:#6c757d}.p-fileupload-buttonbar{padding:0}.p-fileupload-content{background-color:#0f8bfd1a}.p-fileupload .p-fileupload-content{padding:1rem}.docHeader .p-button-icon{padding:.5rem}.document-upload-container{padding:1rem;max-height:90vh}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1.5rem}.assignment-section h4,.applicant-section h4,.category-section h4,.document-type-section h4,.file-upload-section h4{margin:0 0 .75rem;font-size:1rem;font-weight:600;color:#212529}.radio-group{display:flex;gap:.75rem}.radio-item{display:flex;align-items:center;gap:.5rem;cursor:pointer;transition:all .2s ease}.radio-item:has(.p-radiobutton-box.p-highlight) .radio-label{color:#0f8bfd;font-weight:600}.radio-label{font-size:.9rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease}::ng-deep .p-dropdown{width:100%}::ng-deep .p-dropdown .p-dropdown-label{font-size:.9rem;color:#495057}::ng-deep .p-dropdown .p-dropdown-trigger{color:#6c757d}::ng-deep .p-dropdown:not(.p-disabled):hover{border-color:#0f8bfd}::ng-deep .p-dropdown:not(.p-disabled).p-focus{border-color:#0f8bfd;box-shadow:0 0 0 2px #0f8bfd33}::ng-deep .p-radiobutton .p-radiobutton-box{border-color:#ced4da;border-radius:4px;width:18px;height:18px}::ng-deep .p-radiobutton .p-radiobutton-box:hover{border-color:#0f8bfd}::ng-deep .p-radiobutton .p-radiobutton-box.p-highlight{border-color:#0f8bfd;background-color:transparent}::ng-deep .p-radiobutton .p-radiobutton-icon{background-color:#0f8bfd;width:8px;height:8px;border-radius:2px}.applicant-section .grid{margin:0;padding:0}.applicant-section .applicant-item{display:flex;align-items:center;gap:.75rem;border-radius:.5rem;background-color:#fff;transition:all .2s ease;cursor:pointer;margin-bottom:.75rem}.applicant-section .applicant-item:has(.p-radiobutton-box.p-highlight) .applicant-label{color:#0f8bfd;font-weight:600}.applicant-section .applicant-label{font-size:.95rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;flex:1;font-weight:500;margin:0;transition:color .2s ease}@media (max-width: 768px){.applicant-section .applicant-item{margin-bottom:.5rem;padding:.75rem;min-height:50px}.applicant-section .applicant-label{font-size:.9rem}.document-upload-container{padding:.75rem}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1rem}}.category-section .p-dropdown,.document-type-section .p-dropdown{width:100%!important;min-width:100%!important}.category-section .p-dropdown-panel,.document-type-section .p-dropdown-panel{width:100%!important}:host ::ng-deep .p-dropdown{width:100%!important}:host ::ng-deep .p-dropdown-panel{width:100%!important}.applicant-list{display:none}\n"], dependencies: [{ kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i10.FileUpload, selector: "p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "component", type: i11.ProgressBar, selector: "p-progressBar", inputs: ["value", "showValue", "styleClass", "style", "unit", "mode", "color"] }, { kind: "component", type: i12.RadioButton, selector: "p-radioButton", inputs: ["value", "formControlName", "name", "disabled", "label", "variant", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "style", "styleClass", "labelStyleClass", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i14.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "autoShowPanelOnPrintableCharacterKeyDown", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
3430
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DocumentUploadComponent, isStandalone: false, selector: "lib-document-upload", inputs: { contextId: "contextId" }, outputs: { onFormValidationChange: "onFormValidationChange", onUploadSuccess: "onUploadSuccess" }, viewQueries: [{ propertyName: "fileUploader", first: true, predicate: ["fileUploader"], descendants: true }], ngImport: i0, template: "<div class=\"document-upload-container\">\n <!-- Assignment Section -->\n <div class=\"assignment-section\">\n <h4>Assign to Applicant(s) or Application</h4>\n <div class=\"radio-group\">\n <div class=\"radio-item\">\n <p-radioButton \n name=\"assignmentType\" \n value=\"Applicant\" \n [(ngModel)]=\"selectedAssignmentType\"\n (onClick)=\"onAssignmentTypeChange()\"\n [inputId]=\"'applicant'\"\n ></p-radioButton>\n <label [for]=\"'applicant'\" class=\"radio-label\">Applicant(s)</label>\n </div>\n <div class=\"radio-item\">\n <p-radioButton \n name=\"assignmentType\" \n value=\"Application\" \n [(ngModel)]=\"selectedAssignmentType\"\n (onClick)=\"onAssignmentTypeChange()\"\n [inputId]=\"'application'\"\n ></p-radioButton>\n <label [for]=\"'application'\" class=\"radio-label\">Application</label>\n </div>\n </div>\n </div>\n\n <!-- Applicant Selection (only shown when Applicant is selected) -->\n <div class=\"applicant-section\" *ngIf=\"selectedAssignmentType === 'Applicant'\">\n <h4>Select Applicant(s)</h4>\n <div class=\"grid\">\n <div \n *ngFor=\"let applicant of filteredApplicantList\" \n class=\"applicant-item col-12 md:col-6\"\n >\n <p-radioButton \n name=\"selectedApplicant\"\n [value]=\"applicant._id\"\n [(ngModel)]=\"selectedApplicant\"\n [inputId]=\"'applicant-' + applicant._id\"\n (onClick)=\"onApplicantSelectionChange()\"\n ></p-radioButton>\n <label [for]=\"'applicant-' + applicant._id\" class=\"applicant-label\">\n {{ applicant.name }}\n </label>\n </div>\n </div>\n </div>\n\n <!-- Category Selection -->\n <div class=\"category-section\">\n <h4>Category</h4>\n <p-dropdown\n [options]=\"categoryOptions\"\n [(ngModel)]=\"selectedCategory\"\n placeholder=\"Select Category type\"\n optionLabel=\"label\"\n optionValue=\"_id\"\n (onChange)=\"onCategoryChange()\"\n [disabled]=\"!categoryOptions.length\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n\n <!-- Document Type Selection -->\n <div class=\"document-type-section\">\n <h4>Document Type</h4>\n <p-dropdown\n [options]=\"documentTypeOptions\"\n [(ngModel)]=\"selectedDocumentType\"\n placeholder=\"Select Document type\"\n optionLabel=\"label\"\n optionValue=\"_id\"\n (onChange)=\"onDocumentTypeChange()\"\n [disabled]=\"!documentTypeOptions.length || !selectedCategory\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n\n <!-- File Upload Section -->\n <div class=\"file-upload-section\">\n <h4>Upload Documents</h4>\n \n <!-- Debug Section -->\n <div class=\"debug-section mb-3\" style=\"background: #f0f0f0; padding: 10px; border-radius: 4px;\">\n <button type=\"button\" class=\"p-button p-button-sm p-button-outlined\" (click)=\"logUploadStatus()\">\n Debug: Log Upload Status\n </button>\n <button type=\"button\" class=\"p-button p-button-sm p-button-outlined ml-2\" (click)=\"checkUploadServiceStatus()\">\n Check Service Status\n </button>\n <span class=\"ml-3 text-sm\">Files: {{ uploadedFiles.length }} | Progress Map: {{ fileProgress.size }}</span>\n <div class=\"mt-2 text-xs\">\n <div>All Files Uploaded: {{ areAllFilesUploaded() }}</div>\n <div>Save Button Disabled: {{ getSaveButtonDisabled() }}</div>\n </div>\n </div>\n \n <div class=\"grid\">\n <div class=\"col-12 md:col-12\">\n <p-fileUpload \n #fileUploader \n [multiple]=\"true\" \n [auto]=\"false\" \n accept=\"image/png,application/pdf\" \n maxFileSize=\"26214400\"\n (onSelect)=\"onSelectedFiles($event)\"\n >\n <ng-template pTemplate=\"header\" let-chooseCallback=\"chooseCallback\" let-clearCallback=\"clearCallback\">\n <div class=\"docHeader p-2 flex flex-wrap justify-content-between align-items-center flex-1 gap-2\">\n <div class=\"flex gap-2\">\n <p-button \n (onClick)=\"choose($event, chooseCallback)\" \n icon=\"pi pi-images\" \n [rounded]=\"true\"\n [outlined]=\"true\" \n />\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"content\" let-removeFileCallback=\"removeFileCallback\"\n let-removeUploadedFileCallback=\"removeUploadedFileCallback\">\n <div class=\"col-12 md:col-12 p-0\">\n <div class=\"col-12 md:col-12 p-0\" *ngIf=\"uploadedFiles.length > 0\">\n <div *ngFor=\"let uploadedFile of uploadedFiles; let i = index\"\n class=\"m-0 flex flex-column align-items-center gap-1 mt-3\">\n <div class=\"col-12 md:col-12 p-0 flex documentInfo\">\n <div class=\"documentImage\">\n <img src=\"../../../../assets/images/document.png\" [alt]=\"uploadedFile.file.name\" width=\"45\" height=\"50\"\n class=\"object-contain\" />\n </div>\n <div class=\"flex w-full flex-column mt-2 ml-2\">\n <div class=\"flex justify-content-between\">\n <div style=\"font-weight: bold;font-size: 14px\">\n {{ uploadedFile.file.name }}\n </div>\n <i class=\"pi pi-times cursor-pointer\" (click)=\"handleDocumentRemove(uploadedFile.file,i)\"></i>\n </div>\n <div class=\"flex justify-content-between mt-1\">\n <div style=\"color: #676B89; font-size: 12px; color: green;\" class=\"pi pi-verified\"> \n {{ uploadedFile.formattedSize }}\n </div>\n <div class=\"white-space-nowrap\" style=\"color: #0F8BFD; font-family: 14px;\"> \n {{ uploadedFile.progress }} % \n </div>\n </div>\n </div>\n </div>\n <div class=\"col-12 md:col-12 p-0\">\n <p-progressBar \n [value]=\"uploadedFile.progress\" \n [showValue]=\"false\" \n styleClass=\"h-1/2rem md:ml-auto relative\"\n [ngClass]=\"{ 'exceeded-progress-bar': uploadedFile.progress > 100 }\"\n >\n </p-progressBar>\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"empty\" let-chooseCallback=\"chooseCallback\">\n <div *ngIf=\"!uploadedFiles.length\" class=\"flex align-items-center justify-content-center flex-column\"\n (click)=\"triggerFileUpload()\">\n <i class=\"pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400\"></i>\n <p class=\"mt-4 mb-0\">Drag and drop files here to upload.</p>\n </div>\n </ng-template>\n <ng-template pTemplate=\"file\"> </ng-template>\n </p-fileUpload>\n </div>\n </div>\n </div>\n</div>", styles: [".flex{display:flex}.items-center{align-items:center}.justify-center{justify-content:center}.flex-col{flex-direction:column}.text-muted-color{color:#6c757d}.p-fileupload-buttonbar{padding:0}.p-fileupload-content{background-color:#0f8bfd1a}.p-fileupload .p-fileupload-content{padding:1rem}.docHeader .p-button-icon{padding:.5rem}.document-upload-container{padding:1rem;max-height:90vh}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1.5rem}.assignment-section h4,.applicant-section h4,.category-section h4,.document-type-section h4,.file-upload-section h4{margin:0 0 .75rem;font-size:1rem;font-weight:600;color:#212529}.radio-group{display:flex;gap:.75rem}.radio-item{display:flex;align-items:center;gap:.5rem;cursor:pointer;transition:all .2s ease}.radio-item:has(.p-radiobutton-box.p-highlight) .radio-label{color:#0f8bfd;font-weight:600}.radio-label{font-size:.9rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease}::ng-deep .p-dropdown{width:100%}::ng-deep .p-dropdown .p-dropdown-label{font-size:.9rem;color:#495057}::ng-deep .p-dropdown .p-dropdown-trigger{color:#6c757d}::ng-deep .p-dropdown:not(.p-disabled):hover{border-color:#0f8bfd}::ng-deep .p-dropdown:not(.p-disabled).p-focus{border-color:#0f8bfd;box-shadow:0 0 0 2px #0f8bfd33}::ng-deep .p-radiobutton .p-radiobutton-box{border-color:#ced4da;border-radius:4px;width:18px;height:18px}::ng-deep .p-radiobutton .p-radiobutton-box:hover{border-color:#0f8bfd}::ng-deep .p-radiobutton .p-radiobutton-box.p-highlight{border-color:#0f8bfd;background-color:transparent}::ng-deep .p-radiobutton .p-radiobutton-icon{background-color:#0f8bfd;width:8px;height:8px;border-radius:2px}.applicant-section .grid{margin:0;padding:0}.applicant-section .applicant-item{display:flex;align-items:center;gap:.75rem;border-radius:.5rem;background-color:#fff;transition:all .2s ease;cursor:pointer;margin-bottom:.75rem}.applicant-section .applicant-item:has(.p-radiobutton-box.p-highlight) .applicant-label{color:#0f8bfd;font-weight:600}.applicant-section .applicant-label{font-size:.95rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;flex:1;font-weight:500;margin:0;transition:color .2s ease}@media (max-width: 768px){.applicant-section .applicant-item{margin-bottom:.5rem;padding:.75rem;min-height:50px}.applicant-section .applicant-label{font-size:.9rem}.document-upload-container{padding:.75rem}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1rem}}.category-section .p-dropdown,.document-type-section .p-dropdown{width:100%!important;min-width:100%!important}.category-section .p-dropdown-panel,.document-type-section .p-dropdown-panel{width:100%!important}:host ::ng-deep .p-dropdown{width:100%!important}:host ::ng-deep .p-dropdown-panel{width:100%!important}.applicant-list{display:none}\n"], dependencies: [{ kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i4.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: i10.FileUpload, selector: "p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "component", type: i11.ProgressBar, selector: "p-progressBar", inputs: ["value", "showValue", "styleClass", "style", "unit", "mode", "color"] }, { kind: "component", type: i12.RadioButton, selector: "p-radioButton", inputs: ["value", "formControlName", "name", "disabled", "label", "variant", "tabindex", "inputId", "ariaLabelledBy", "ariaLabel", "style", "styleClass", "labelStyleClass", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i14.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "variant", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "autoShowPanelOnPrintableCharacterKeyDown", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
3248
3431
|
}
|
|
3249
3432
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DocumentUploadComponent, decorators: [{
|
|
3250
3433
|
type: Component,
|
|
3251
|
-
args: [{ selector: 'lib-document-upload', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"document-upload-container\">\r\n <!-- Assignment Section -->\r\n <div class=\"assignment-section\">\r\n <h4>Assign to Applicant(s) or Application</h4>\r\n <div class=\"radio-group\">\r\n <div class=\"radio-item\">\r\n <p-radioButton \r\n name=\"assignmentType\" \r\n value=\"Applicant\" \r\n [(ngModel)]=\"selectedAssignmentType\"\r\n (onClick)=\"onAssignmentTypeChange()\"\r\n [inputId]=\"'applicant'\"\r\n ></p-radioButton>\r\n <label [for]=\"'applicant'\" class=\"radio-label\">Applicant(s)</label>\r\n </div>\r\n <div class=\"radio-item\">\r\n <p-radioButton \r\n name=\"assignmentType\" \r\n value=\"Application\" \r\n [(ngModel)]=\"selectedAssignmentType\"\r\n (onClick)=\"onAssignmentTypeChange()\"\r\n [inputId]=\"'application'\"\r\n ></p-radioButton>\r\n <label [for]=\"'application'\" class=\"radio-label\">Application</label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Applicant Selection (only shown when Applicant is selected) -->\r\n <div class=\"applicant-section\" *ngIf=\"selectedAssignmentType === 'Applicant'\">\r\n <h4>Select Applicant(s)</h4>\r\n <div class=\"grid\">\r\n <div \r\n *ngFor=\"let applicant of filteredApplicantList\" \r\n class=\"applicant-item col-12 md:col-6\"\r\n >\r\n <p-radioButton \r\n name=\"selectedApplicant\"\r\n [value]=\"applicant._id\"\r\n [(ngModel)]=\"selectedApplicant\"\r\n [inputId]=\"'applicant-' + applicant._id\"\r\n (onClick)=\"onApplicantSelectionChange()\"\r\n ></p-radioButton>\r\n <label [for]=\"'applicant-' + applicant._id\" class=\"applicant-label\">\r\n {{ applicant.name }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Category Selection -->\r\n <div class=\"category-section\">\r\n <h4>Category</h4>\r\n <p-dropdown\r\n [options]=\"categoryOptions\"\r\n [(ngModel)]=\"selectedCategory\"\r\n placeholder=\"Select Category type\"\r\n optionLabel=\"label\"\r\n optionValue=\"_id\"\r\n (onChange)=\"onCategoryChange()\"\r\n [disabled]=\"!categoryOptions.length\"\r\n class=\"w-full\"\r\n ></p-dropdown>\r\n </div>\r\n\r\n <!-- Document Type Selection -->\r\n <div class=\"document-type-section\">\r\n <h4>Document Type</h4>\r\n <p-dropdown\r\n [options]=\"documentTypeOptions\"\r\n [(ngModel)]=\"selectedDocumentType\"\r\n placeholder=\"Select Document type\"\r\n optionLabel=\"label\"\r\n optionValue=\"_id\"\r\n (onChange)=\"onDocumentTypeChange()\"\r\n [disabled]=\"!documentTypeOptions.length || !selectedCategory\"\r\n class=\"w-full\"\r\n ></p-dropdown>\r\n </div>\r\n\r\n <!-- File Upload Section -->\r\n <div class=\"file-upload-section\">\r\n <h4>Upload Documents</h4>\r\n <div class=\"grid\">\r\n <div class=\"col-12 md:col-12\">\r\n <p-fileUpload \r\n #fileUploader \r\n [multiple]=\"true\" \r\n auto=\"true\" \r\n accept=\"image/png,application/pdf\" \r\n maxFileSize=\"26214400\"\r\n (onSelect)=\"onSelectedFiles($event)\"\r\n >\r\n <ng-template pTemplate=\"header\" let-chooseCallback=\"chooseCallback\" let-clearCallback=\"clearCallback\">\r\n <div class=\"docHeader p-2 flex flex-wrap justify-content-between align-items-center flex-1 gap-2\">\r\n <div class=\"flex gap-2\">\r\n <p-button \r\n (onClick)=\"choose($event, chooseCallback)\" \r\n icon=\"pi pi-images\" \r\n [rounded]=\"true\"\r\n [outlined]=\"true\" \r\n />\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template pTemplate=\"content\" let-removeFileCallback=\"removeFileCallback\"\r\n let-removeUploadedFileCallback=\"removeUploadedFileCallback\">\r\n <div class=\"col-12 md:col-12 p-0\">\r\n <div class=\"col-12 md:col-12 p-0\" *ngIf=\"uploadedFiles.length > 0\">\r\n <div *ngFor=\"let uploadedFile of uploadedFiles; let i = index\"\r\n class=\"m-0 flex flex-column align-items-center gap-1 mt-3\">\r\n <div class=\"col-12 md:col-12 p-0 flex documentInfo\">\r\n <div class=\"documentImage\">\r\n <img src=\"../../../../assets/images/document.png\" [alt]=\"uploadedFile.file.name\" width=\"45\" height=\"50\"\r\n class=\"object-contain\" />\r\n </div>\r\n <div class=\"flex w-full flex-column mt-2 ml-2\">\r\n <div class=\"flex justify-content-between\">\r\n <div style=\"font-weight: bold;font-size: 14px\">\r\n {{ uploadedFile.file.name }}\r\n </div>\r\n <i class=\"pi pi-times cursor-pointer\" (click)=\"handleDocumentRemove(uploadedFile.file,i)\"></i>\r\n </div>\r\n <div class=\"flex justify-content-between mt-1\">\r\n <div style=\"color: #676B89; font-size: 12px; color: green;\" class=\"pi pi-verified\"> \r\n {{ uploadedFile.formattedSize }}\r\n </div>\r\n <div class=\"white-space-nowrap\" style=\"color: #0F8BFD; font-family: 14px;\"> \r\n {{ uploadedFile.progress }} % \r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"col-12 md:col-12 p-0\">\r\n <p-progressBar \r\n [value]=\"uploadedFile.progress\" \r\n [showValue]=\"false\" \r\n styleClass=\"h-1/2rem md:ml-auto relative\"\r\n [ngClass]=\"{ 'exceeded-progress-bar': uploadedFile.progress > 100 }\"\r\n >\r\n </p-progressBar>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template pTemplate=\"empty\" let-chooseCallback=\"chooseCallback\">\r\n <div *ngIf=\"!uploadedFiles.length\" class=\"flex align-items-center justify-content-center flex-column\"\r\n (click)=\"triggerFileUpload()\">\r\n <i class=\"pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400\"></i>\r\n <p class=\"mt-4 mb-0\">Drag and drop files here to upload.</p>\r\n </div>\r\n </ng-template>\r\n <ng-template pTemplate=\"file\"> </ng-template>\r\n </p-fileUpload>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".flex{display:flex}.items-center{align-items:center}.justify-center{justify-content:center}.flex-col{flex-direction:column}.text-muted-color{color:#6c757d}.p-fileupload-buttonbar{padding:0}.p-fileupload-content{background-color:#0f8bfd1a}.p-fileupload .p-fileupload-content{padding:1rem}.docHeader .p-button-icon{padding:.5rem}.document-upload-container{padding:1rem;max-height:90vh}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1.5rem}.assignment-section h4,.applicant-section h4,.category-section h4,.document-type-section h4,.file-upload-section h4{margin:0 0 .75rem;font-size:1rem;font-weight:600;color:#212529}.radio-group{display:flex;gap:.75rem}.radio-item{display:flex;align-items:center;gap:.5rem;cursor:pointer;transition:all .2s ease}.radio-item:has(.p-radiobutton-box.p-highlight) .radio-label{color:#0f8bfd;font-weight:600}.radio-label{font-size:.9rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease}::ng-deep .p-dropdown{width:100%}::ng-deep .p-dropdown .p-dropdown-label{font-size:.9rem;color:#495057}::ng-deep .p-dropdown .p-dropdown-trigger{color:#6c757d}::ng-deep .p-dropdown:not(.p-disabled):hover{border-color:#0f8bfd}::ng-deep .p-dropdown:not(.p-disabled).p-focus{border-color:#0f8bfd;box-shadow:0 0 0 2px #0f8bfd33}::ng-deep .p-radiobutton .p-radiobutton-box{border-color:#ced4da;border-radius:4px;width:18px;height:18px}::ng-deep .p-radiobutton .p-radiobutton-box:hover{border-color:#0f8bfd}::ng-deep .p-radiobutton .p-radiobutton-box.p-highlight{border-color:#0f8bfd;background-color:transparent}::ng-deep .p-radiobutton .p-radiobutton-icon{background-color:#0f8bfd;width:8px;height:8px;border-radius:2px}.applicant-section .grid{margin:0;padding:0}.applicant-section .applicant-item{display:flex;align-items:center;gap:.75rem;border-radius:.5rem;background-color:#fff;transition:all .2s ease;cursor:pointer;margin-bottom:.75rem}.applicant-section .applicant-item:has(.p-radiobutton-box.p-highlight) .applicant-label{color:#0f8bfd;font-weight:600}.applicant-section .applicant-label{font-size:.95rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;flex:1;font-weight:500;margin:0;transition:color .2s ease}@media (max-width: 768px){.applicant-section .applicant-item{margin-bottom:.5rem;padding:.75rem;min-height:50px}.applicant-section .applicant-label{font-size:.9rem}.document-upload-container{padding:.75rem}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1rem}}.category-section .p-dropdown,.document-type-section .p-dropdown{width:100%!important;min-width:100%!important}.category-section .p-dropdown-panel,.document-type-section .p-dropdown-panel{width:100%!important}:host ::ng-deep .p-dropdown{width:100%!important}:host ::ng-deep .p-dropdown-panel{width:100%!important}.applicant-list{display:none}\n"] }]
|
|
3434
|
+
args: [{ selector: 'lib-document-upload', standalone: false, encapsulation: ViewEncapsulation.None, template: "<div class=\"document-upload-container\">\n <!-- Assignment Section -->\n <div class=\"assignment-section\">\n <h4>Assign to Applicant(s) or Application</h4>\n <div class=\"radio-group\">\n <div class=\"radio-item\">\n <p-radioButton \n name=\"assignmentType\" \n value=\"Applicant\" \n [(ngModel)]=\"selectedAssignmentType\"\n (onClick)=\"onAssignmentTypeChange()\"\n [inputId]=\"'applicant'\"\n ></p-radioButton>\n <label [for]=\"'applicant'\" class=\"radio-label\">Applicant(s)</label>\n </div>\n <div class=\"radio-item\">\n <p-radioButton \n name=\"assignmentType\" \n value=\"Application\" \n [(ngModel)]=\"selectedAssignmentType\"\n (onClick)=\"onAssignmentTypeChange()\"\n [inputId]=\"'application'\"\n ></p-radioButton>\n <label [for]=\"'application'\" class=\"radio-label\">Application</label>\n </div>\n </div>\n </div>\n\n <!-- Applicant Selection (only shown when Applicant is selected) -->\n <div class=\"applicant-section\" *ngIf=\"selectedAssignmentType === 'Applicant'\">\n <h4>Select Applicant(s)</h4>\n <div class=\"grid\">\n <div \n *ngFor=\"let applicant of filteredApplicantList\" \n class=\"applicant-item col-12 md:col-6\"\n >\n <p-radioButton \n name=\"selectedApplicant\"\n [value]=\"applicant._id\"\n [(ngModel)]=\"selectedApplicant\"\n [inputId]=\"'applicant-' + applicant._id\"\n (onClick)=\"onApplicantSelectionChange()\"\n ></p-radioButton>\n <label [for]=\"'applicant-' + applicant._id\" class=\"applicant-label\">\n {{ applicant.name }}\n </label>\n </div>\n </div>\n </div>\n\n <!-- Category Selection -->\n <div class=\"category-section\">\n <h4>Category</h4>\n <p-dropdown\n [options]=\"categoryOptions\"\n [(ngModel)]=\"selectedCategory\"\n placeholder=\"Select Category type\"\n optionLabel=\"label\"\n optionValue=\"_id\"\n (onChange)=\"onCategoryChange()\"\n [disabled]=\"!categoryOptions.length\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n\n <!-- Document Type Selection -->\n <div class=\"document-type-section\">\n <h4>Document Type</h4>\n <p-dropdown\n [options]=\"documentTypeOptions\"\n [(ngModel)]=\"selectedDocumentType\"\n placeholder=\"Select Document type\"\n optionLabel=\"label\"\n optionValue=\"_id\"\n (onChange)=\"onDocumentTypeChange()\"\n [disabled]=\"!documentTypeOptions.length || !selectedCategory\"\n class=\"w-full\"\n ></p-dropdown>\n </div>\n\n <!-- File Upload Section -->\n <div class=\"file-upload-section\">\n <h4>Upload Documents</h4>\n \n <!-- Debug Section -->\n <div class=\"debug-section mb-3\" style=\"background: #f0f0f0; padding: 10px; border-radius: 4px;\">\n <button type=\"button\" class=\"p-button p-button-sm p-button-outlined\" (click)=\"logUploadStatus()\">\n Debug: Log Upload Status\n </button>\n <button type=\"button\" class=\"p-button p-button-sm p-button-outlined ml-2\" (click)=\"checkUploadServiceStatus()\">\n Check Service Status\n </button>\n <span class=\"ml-3 text-sm\">Files: {{ uploadedFiles.length }} | Progress Map: {{ fileProgress.size }}</span>\n <div class=\"mt-2 text-xs\">\n <div>All Files Uploaded: {{ areAllFilesUploaded() }}</div>\n <div>Save Button Disabled: {{ getSaveButtonDisabled() }}</div>\n </div>\n </div>\n \n <div class=\"grid\">\n <div class=\"col-12 md:col-12\">\n <p-fileUpload \n #fileUploader \n [multiple]=\"true\" \n [auto]=\"false\" \n accept=\"image/png,application/pdf\" \n maxFileSize=\"26214400\"\n (onSelect)=\"onSelectedFiles($event)\"\n >\n <ng-template pTemplate=\"header\" let-chooseCallback=\"chooseCallback\" let-clearCallback=\"clearCallback\">\n <div class=\"docHeader p-2 flex flex-wrap justify-content-between align-items-center flex-1 gap-2\">\n <div class=\"flex gap-2\">\n <p-button \n (onClick)=\"choose($event, chooseCallback)\" \n icon=\"pi pi-images\" \n [rounded]=\"true\"\n [outlined]=\"true\" \n />\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"content\" let-removeFileCallback=\"removeFileCallback\"\n let-removeUploadedFileCallback=\"removeUploadedFileCallback\">\n <div class=\"col-12 md:col-12 p-0\">\n <div class=\"col-12 md:col-12 p-0\" *ngIf=\"uploadedFiles.length > 0\">\n <div *ngFor=\"let uploadedFile of uploadedFiles; let i = index\"\n class=\"m-0 flex flex-column align-items-center gap-1 mt-3\">\n <div class=\"col-12 md:col-12 p-0 flex documentInfo\">\n <div class=\"documentImage\">\n <img src=\"../../../../assets/images/document.png\" [alt]=\"uploadedFile.file.name\" width=\"45\" height=\"50\"\n class=\"object-contain\" />\n </div>\n <div class=\"flex w-full flex-column mt-2 ml-2\">\n <div class=\"flex justify-content-between\">\n <div style=\"font-weight: bold;font-size: 14px\">\n {{ uploadedFile.file.name }}\n </div>\n <i class=\"pi pi-times cursor-pointer\" (click)=\"handleDocumentRemove(uploadedFile.file,i)\"></i>\n </div>\n <div class=\"flex justify-content-between mt-1\">\n <div style=\"color: #676B89; font-size: 12px; color: green;\" class=\"pi pi-verified\"> \n {{ uploadedFile.formattedSize }}\n </div>\n <div class=\"white-space-nowrap\" style=\"color: #0F8BFD; font-family: 14px;\"> \n {{ uploadedFile.progress }} % \n </div>\n </div>\n </div>\n </div>\n <div class=\"col-12 md:col-12 p-0\">\n <p-progressBar \n [value]=\"uploadedFile.progress\" \n [showValue]=\"false\" \n styleClass=\"h-1/2rem md:ml-auto relative\"\n [ngClass]=\"{ 'exceeded-progress-bar': uploadedFile.progress > 100 }\"\n >\n </p-progressBar>\n </div>\n </div>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"empty\" let-chooseCallback=\"chooseCallback\">\n <div *ngIf=\"!uploadedFiles.length\" class=\"flex align-items-center justify-content-center flex-column\"\n (click)=\"triggerFileUpload()\">\n <i class=\"pi pi-cloud-upload border-2 border-circle p-5 text-8xl text-400 border-400\"></i>\n <p class=\"mt-4 mb-0\">Drag and drop files here to upload.</p>\n </div>\n </ng-template>\n <ng-template pTemplate=\"file\"> </ng-template>\n </p-fileUpload>\n </div>\n </div>\n </div>\n</div>", styles: [".flex{display:flex}.items-center{align-items:center}.justify-center{justify-content:center}.flex-col{flex-direction:column}.text-muted-color{color:#6c757d}.p-fileupload-buttonbar{padding:0}.p-fileupload-content{background-color:#0f8bfd1a}.p-fileupload .p-fileupload-content{padding:1rem}.docHeader .p-button-icon{padding:.5rem}.document-upload-container{padding:1rem;max-height:90vh}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1.5rem}.assignment-section h4,.applicant-section h4,.category-section h4,.document-type-section h4,.file-upload-section h4{margin:0 0 .75rem;font-size:1rem;font-weight:600;color:#212529}.radio-group{display:flex;gap:.75rem}.radio-item{display:flex;align-items:center;gap:.5rem;cursor:pointer;transition:all .2s ease}.radio-item:has(.p-radiobutton-box.p-highlight) .radio-label{color:#0f8bfd;font-weight:600}.radio-label{font-size:.9rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease}::ng-deep .p-dropdown{width:100%}::ng-deep .p-dropdown .p-dropdown-label{font-size:.9rem;color:#495057}::ng-deep .p-dropdown .p-dropdown-trigger{color:#6c757d}::ng-deep .p-dropdown:not(.p-disabled):hover{border-color:#0f8bfd}::ng-deep .p-dropdown:not(.p-disabled).p-focus{border-color:#0f8bfd;box-shadow:0 0 0 2px #0f8bfd33}::ng-deep .p-radiobutton .p-radiobutton-box{border-color:#ced4da;border-radius:4px;width:18px;height:18px}::ng-deep .p-radiobutton .p-radiobutton-box:hover{border-color:#0f8bfd}::ng-deep .p-radiobutton .p-radiobutton-box.p-highlight{border-color:#0f8bfd;background-color:transparent}::ng-deep .p-radiobutton .p-radiobutton-icon{background-color:#0f8bfd;width:8px;height:8px;border-radius:2px}.applicant-section .grid{margin:0;padding:0}.applicant-section .applicant-item{display:flex;align-items:center;gap:.75rem;border-radius:.5rem;background-color:#fff;transition:all .2s ease;cursor:pointer;margin-bottom:.75rem}.applicant-section .applicant-item:has(.p-radiobutton-box.p-highlight) .applicant-label{color:#0f8bfd;font-weight:600}.applicant-section .applicant-label{font-size:.95rem;color:#495057;cursor:pointer;-webkit-user-select:none;user-select:none;flex:1;font-weight:500;margin:0;transition:color .2s ease}@media (max-width: 768px){.applicant-section .applicant-item{margin-bottom:.5rem;padding:.75rem;min-height:50px}.applicant-section .applicant-label{font-size:.9rem}.document-upload-container{padding:.75rem}.assignment-section,.applicant-section,.category-section,.document-type-section,.file-upload-section{margin-bottom:1rem}}.category-section .p-dropdown,.document-type-section .p-dropdown{width:100%!important;min-width:100%!important}.category-section .p-dropdown-panel,.document-type-section .p-dropdown-panel{width:100%!important}:host ::ng-deep .p-dropdown{width:100%!important}:host ::ng-deep .p-dropdown-panel{width:100%!important}.applicant-list{display:none}\n"] }]
|
|
3252
3435
|
}], ctorParameters: () => [{ type: DocumentUploadService }, { type: DocumentService }, { type: i3.PrimeNGConfig }, { type: FileFormatService }, { type: i3.MessageService }, { type: i0.ChangeDetectorRef }, { type: DocumentUploadBusinessService }, { type: DocumentUploadFormService }, { type: DocumentUploadDataService }], propDecorators: { contextId: [{
|
|
3253
3436
|
type: Input
|
|
3254
3437
|
}], fileUploader: [{
|
|
@@ -3420,7 +3603,19 @@ class UserListService {
|
|
|
3420
3603
|
this.documentQuery = documentQuery;
|
|
3421
3604
|
}
|
|
3422
3605
|
getInitials(name) {
|
|
3423
|
-
|
|
3606
|
+
if (!name || name.trim() === SHARED.EMPTY) {
|
|
3607
|
+
return SHARED.EMPTY;
|
|
3608
|
+
}
|
|
3609
|
+
const words = name.trim().split(SHARED.EMPTY_SPACE).filter(word => word.length > SHARED.INITIAL_COUNT);
|
|
3610
|
+
if (words.length === 1) {
|
|
3611
|
+
return words[0].substring(0, 2).toUpperCase();
|
|
3612
|
+
}
|
|
3613
|
+
else if (words.length >= 2) {
|
|
3614
|
+
const firstWord = words[0];
|
|
3615
|
+
const lastWord = words[words.length - 1];
|
|
3616
|
+
return (firstWord.charAt(0) + lastWord.charAt(0)).toUpperCase();
|
|
3617
|
+
}
|
|
3618
|
+
return SHARED.EMPTY;
|
|
3424
3619
|
}
|
|
3425
3620
|
getColorByIndex(index) {
|
|
3426
3621
|
const colors = SHARED.COLORS;
|
|
@@ -3525,10 +3720,10 @@ class UserListComponent {
|
|
|
3525
3720
|
this.cdr = cdr;
|
|
3526
3721
|
}
|
|
3527
3722
|
ngOnChanges(changes) {
|
|
3528
|
-
if (changes[
|
|
3723
|
+
if (changes[SHARED.USER_LIST] && !changes[SHARED.USER_LIST].firstChange) {
|
|
3529
3724
|
this.initializeUserData();
|
|
3530
3725
|
}
|
|
3531
|
-
if (changes[
|
|
3726
|
+
if (changes[SHARED.CATEGORIES] && !changes[SHARED.CATEGORIES].firstChange) {
|
|
3532
3727
|
this.updateFilteredUserData();
|
|
3533
3728
|
}
|
|
3534
3729
|
}
|
|
@@ -3626,7 +3821,7 @@ class UserListComponent {
|
|
|
3626
3821
|
this.categoriesSubscription.unsubscribe();
|
|
3627
3822
|
}
|
|
3628
3823
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UserListComponent, deps: [{ token: DocumentHelperService }, { token: DocumentStore }, { token: DocumentQuery }, { token: UserListService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
3629
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UserListComponent, isStandalone: false, selector: "lib-user-list", inputs: { userList: "userList", categories: "categories" }, outputs: { userSelected: "userSelected" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"user-list-container\" [@slideInFromTop]>\r\n <div class=\"user-cards\">\r\n <div \r\n *ngFor=\"let user of filteredUserData\" \r\n class=\"user-card\"\r\n [class.selected]=\"selectedUser === user.name\"\r\n [style.border-color]=\"selectedUser === user.name ? '#f97316' : 'transparent'\"\r\n (click)=\"onUserSelect(user.name, user._id)\"\r\n >\r\n @if(user.name === \"Application Docs\"){\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\"><i class=\"pi pi-user\"></i></span>\r\n </div>\r\n }@else {\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\">{{ user.initials }}</span>\r\n </div>\r\n }\r\n <div class=\"user-info\">\r\n <div class=\"username\">{{ user.name }}</div>\r\n <div class=\"document-counts\">\r\n
|
|
3824
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: UserListComponent, isStandalone: false, selector: "lib-user-list", inputs: { userList: "userList", categories: "categories" }, outputs: { userSelected: "userSelected" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"user-list-container\" [@slideInFromTop]>\r\n <div class=\"user-cards\">\r\n <div \r\n *ngFor=\"let user of filteredUserData\" \r\n class=\"user-card\"\r\n [class.selected]=\"selectedUser === user.name\"\r\n [style.border-color]=\"selectedUser === user.name ? '#f97316' : 'transparent'\"\r\n (click)=\"onUserSelect(user.name, user._id)\"\r\n >\r\n @if(user.name === \"Application Docs\"){\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\"><i class=\"pi pi-user\"></i></span>\r\n </div>\r\n }@else {\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\">{{ user.initials }}</span>\r\n </div>\r\n }\r\n <div class=\"user-info\">\r\n <div class=\"username\">{{ user.name }}</div>\r\n <div class=\"document-counts\">\r\n <span style=\"color : #16A34A;\"> {{ user.approved }} approved </span><span>/ {{ user.pending }} pending</span>\r\n </div>\r\n </div>\r\n <div class=\"selection-indicator\" *ngIf=\"selectedUser === user.name\" [@fadeIn]>\r\n <i class=\"ri-check-line\"></i>\r\n </div>\r\n </div>\r\n \r\n <!-- Show message when filtered list is empty -->\r\n <div *ngIf=\"filteredUserData.length === 0 && shouldShowContainer\" class=\"no-users-message\" [@slideInFromTop]>\r\n <p>No users available for this category.</p>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".user-list-container{padding:1rem}.user-cards{display:flex;flex-wrap:wrap;gap:1rem;transition:all .3s ease-in-out}.user-card{display:flex;align-items:center;gap:.75rem;padding:1rem;border:2px solid transparent;border-radius:8px;cursor:pointer;transition:all .2s ease;background:#fff;box-shadow:0 2px 4px #0000001a;min-width:284px;max-width:284px;height:80px;position:relative;flex-shrink:0}.user-card:hover{box-shadow:0 4px 8px #00000026}.user-card.selected{background-color:#f8fafc;box-shadow:0 4px 8px #00000026;border-width:2px}.user-avatar{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;color:#fff;font-size:14px;flex-shrink:0}.avatar-orange{background-color:#f97316}.avatar-blue{background-color:#3b82f6}.avatar-green{background-color:#10b981}.avatar-grey{background-color:#6b7280}.avatar-purple{background-color:#8b5cf6}.user-info{flex:1;min-width:0;overflow:hidden}.username{font-weight:600;color:#1f2937;margin-bottom:.25rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.document-counts{font-size:.875rem;color:#6b7280;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.selection-indicator{position:absolute;top:8px;right:8px;width:20px;height:20px;background-color:#10b981;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-size:12px;flex-shrink:0}.no-users-message{display:flex;justify-content:center;align-items:center;padding:2rem;background:#f8fafc;border-radius:8px;border:2px dashed #d1d5db;margin:1rem 0}.no-users-message p{color:#6b7280;font-size:.875rem;font-weight:500;margin:0;text-align:center}\n"], dependencies: [{ kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], animations: [
|
|
3630
3825
|
trigger('slideInFromTop', [
|
|
3631
3826
|
state('void', style({
|
|
3632
3827
|
opacity: 0,
|
|
@@ -3684,7 +3879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
|
|
|
3684
3879
|
animate('200ms ease-in-out')
|
|
3685
3880
|
])
|
|
3686
3881
|
])
|
|
3687
|
-
], template: "<div class=\"user-list-container\" [@slideInFromTop]>\r\n <div class=\"user-cards\">\r\n <div \r\n *ngFor=\"let user of filteredUserData\" \r\n class=\"user-card\"\r\n [class.selected]=\"selectedUser === user.name\"\r\n [style.border-color]=\"selectedUser === user.name ? '#f97316' : 'transparent'\"\r\n (click)=\"onUserSelect(user.name, user._id)\"\r\n >\r\n @if(user.name === \"Application Docs\"){\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\"><i class=\"pi pi-user\"></i></span>\r\n </div>\r\n }@else {\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\">{{ user.initials }}</span>\r\n </div>\r\n }\r\n <div class=\"user-info\">\r\n <div class=\"username\">{{ user.name }}</div>\r\n <div class=\"document-counts\">\r\n
|
|
3882
|
+
], template: "<div class=\"user-list-container\" [@slideInFromTop]>\r\n <div class=\"user-cards\">\r\n <div \r\n *ngFor=\"let user of filteredUserData\" \r\n class=\"user-card\"\r\n [class.selected]=\"selectedUser === user.name\"\r\n [style.border-color]=\"selectedUser === user.name ? '#f97316' : 'transparent'\"\r\n (click)=\"onUserSelect(user.name, user._id)\"\r\n >\r\n @if(user.name === \"Application Docs\"){\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\"><i class=\"pi pi-user\"></i></span>\r\n </div>\r\n }@else {\r\n <div class=\"user-avatar\" [ngClass]=\"'avatar-' + user.color\">\r\n <span class=\"initials\">{{ user.initials }}</span>\r\n </div>\r\n }\r\n <div class=\"user-info\">\r\n <div class=\"username\">{{ user.name }}</div>\r\n <div class=\"document-counts\">\r\n <span style=\"color : #16A34A;\"> {{ user.approved }} approved </span><span>/ {{ user.pending }} pending</span>\r\n </div>\r\n </div>\r\n <div class=\"selection-indicator\" *ngIf=\"selectedUser === user.name\" [@fadeIn]>\r\n <i class=\"ri-check-line\"></i>\r\n </div>\r\n </div>\r\n \r\n <!-- Show message when filtered list is empty -->\r\n <div *ngIf=\"filteredUserData.length === 0 && shouldShowContainer\" class=\"no-users-message\" [@slideInFromTop]>\r\n <p>No users available for this category.</p>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".user-list-container{padding:1rem}.user-cards{display:flex;flex-wrap:wrap;gap:1rem;transition:all .3s ease-in-out}.user-card{display:flex;align-items:center;gap:.75rem;padding:1rem;border:2px solid transparent;border-radius:8px;cursor:pointer;transition:all .2s ease;background:#fff;box-shadow:0 2px 4px #0000001a;min-width:284px;max-width:284px;height:80px;position:relative;flex-shrink:0}.user-card:hover{box-shadow:0 4px 8px #00000026}.user-card.selected{background-color:#f8fafc;box-shadow:0 4px 8px #00000026;border-width:2px}.user-avatar{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:700;color:#fff;font-size:14px;flex-shrink:0}.avatar-orange{background-color:#f97316}.avatar-blue{background-color:#3b82f6}.avatar-green{background-color:#10b981}.avatar-grey{background-color:#6b7280}.avatar-purple{background-color:#8b5cf6}.user-info{flex:1;min-width:0;overflow:hidden}.username{font-weight:600;color:#1f2937;margin-bottom:.25rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.document-counts{font-size:.875rem;color:#6b7280;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.2}.selection-indicator{position:absolute;top:8px;right:8px;width:20px;height:20px;background-color:#10b981;border-radius:50%;display:flex;align-items:center;justify-content:center;color:#fff;font-size:12px;flex-shrink:0}.no-users-message{display:flex;justify-content:center;align-items:center;padding:2rem;background:#f8fafc;border-radius:8px;border:2px dashed #d1d5db;margin:1rem 0}.no-users-message p{color:#6b7280;font-size:.875rem;font-weight:500;margin:0;text-align:center}\n"] }]
|
|
3688
3883
|
}], ctorParameters: () => [{ type: DocumentHelperService }, { type: DocumentStore }, { type: DocumentQuery }, { type: UserListService }, { type: i0.ChangeDetectorRef }], propDecorators: { userList: [{
|
|
3689
3884
|
type: Input
|
|
3690
3885
|
}], categories: [{
|
|
@@ -3835,12 +4030,19 @@ class DocumentSearchComponent {
|
|
|
3835
4030
|
this.searchTerm = SHARED.EMPTY;
|
|
3836
4031
|
this.documentHelperService.setSearchKey(null);
|
|
3837
4032
|
}
|
|
4033
|
+
/**
|
|
4034
|
+
* Clears all filters including search, menu item, user, and status selections
|
|
4035
|
+
*/
|
|
4036
|
+
onClearAllFilters() {
|
|
4037
|
+
this.searchTerm = SHARED.EMPTY;
|
|
4038
|
+
this.documentHelperService.clearSelectionState();
|
|
4039
|
+
}
|
|
3838
4040
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DocumentSearchComponent, deps: [{ token: DocumentHelperService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3839
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DocumentSearchComponent, isStandalone: false, selector: "document-search", inputs: { contextId: "contextId" }, outputs: { onActionClick: "onActionClick" }, ngImport: i0, template: "<div class=\"search-container\">\r\n <div class=\"search-input-wrapper\">\r\n <i class=\"pi pi-search search-icon\"></i>\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"searchTerm\"\r\n (ngModelChange)=\"onSearchInputChange($event)\"\r\n class=\"search-input\"\r\n placeholder=\"Search by document name, category, type, status or applicant name...\"\r\n [attr.aria-label]=\"'Search documents'\"\r\n />\r\n <button \r\n *ngIf=\"searchTerm\"\r\n type=\"button\"\r\n class=\"clear-button\"\r\n (click)=\"onClearSearch()\"\r\n [attr.aria-label]=\"'Clear search'\"\r\n >\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n </div>\r\n
|
|
4041
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: DocumentSearchComponent, isStandalone: false, selector: "document-search", inputs: { contextId: "contextId" }, outputs: { onActionClick: "onActionClick" }, ngImport: i0, template: "<div class=\"search-container\">\r\n <div class=\"search-input-wrapper\">\r\n <i class=\"pi pi-search search-icon\"></i>\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"searchTerm\"\r\n (ngModelChange)=\"onSearchInputChange($event)\"\r\n class=\"search-input\"\r\n placeholder=\"Search by document name, category, type, status or applicant name...\"\r\n [attr.aria-label]=\"'Search documents'\"\r\n />\r\n <button \r\n *ngIf=\"searchTerm\"\r\n type=\"button\"\r\n class=\"clear-button\"\r\n (click)=\"onClearSearch()\"\r\n [attr.aria-label]=\"'Clear search'\"\r\n >\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n </div>\r\n\r\n <button \r\n type=\"button\"\r\n class=\"clear-all-filters-link\"\r\n (click)=\"onClearAllFilters()\"\r\n [attr.aria-label]=\"'Clear all'\"\r\n >\r\n Clear All\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n\r\n <div class=\"filters-section\">\r\n <button \r\n type=\"button\"\r\n class=\"action-button\"\r\n (click)=\"onActionClick.emit()\"\r\n [attr.aria-label]=\"'Open actions menu'\"\r\n >\r\n Actions\r\n </button>\r\n </div>\r\n</div> ", styles: [".search-container{display:flex;align-items:center;gap:1rem;width:100%;justify-content:flex-start;padding:10px}.search-input-wrapper{position:relative;flex:1;display:flex;align-items:center;max-width:50%;min-width:300px}.clear-all-filters-link{background:none;border:none;color:#0f8bfd;cursor:pointer;padding:8px 12px;border-radius:4px;font-size:16px;font-weight:500;text-decoration:none!important;transition:background-color .2s ease,color .2s ease;white-space:nowrap;flex-shrink:0;display:flex;justify-content:center;align-items:center;gap:4px}.filters-section{display:flex;align-items:center;gap:1rem;flex-shrink:0;margin-left:auto}.search-icon{position:absolute;left:12px;color:#6c757d;z-index:1}.search-input{width:100%;padding:12px 40px;border:1px solid #dee2e6;border-radius:8px;font-size:14px;outline:none;transition:border-color .2s ease,box-shadow .2s ease}.search-input:focus{border-color:#0f8bfd;box-shadow:0 0 0 3px #0f8bfd1a}.search-input::placeholder{color:#6c757d}.clear-button{position:absolute;right:12px;background:none;border:none;color:#6c757d;cursor:pointer;padding:4px;border-radius:4px;transition:background-color .2s ease,color .2s ease}.clear-button:hover{background-color:#f8f9fa;color:#495057}.action-button{background-color:#0f8bfd;color:#fff;border:none;padding:12px 24px;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:background-color .2s ease,transform .1s ease;white-space:nowrap}.action-button:hover{background-color:#0d7ae6;transform:translateY(-1px)}.action-button:active{transform:translateY(0)}.action-button:focus{outline:none;box-shadow:0 0 0 3px #0f8bfd4d}@media (max-width: 768px){.search-container{flex-direction:column;gap:.75rem}.search-input-wrapper{max-width:100%}.filters-section{width:100%;justify-content:center;gap:.5rem}.action-button{width:auto;justify-content:center}}\n"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.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: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
3840
4042
|
}
|
|
3841
4043
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: DocumentSearchComponent, decorators: [{
|
|
3842
4044
|
type: Component,
|
|
3843
|
-
args: [{ selector: 'document-search', standalone: false, template: "<div class=\"search-container\">\r\n <div class=\"search-input-wrapper\">\r\n <i class=\"pi pi-search search-icon\"></i>\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"searchTerm\"\r\n (ngModelChange)=\"onSearchInputChange($event)\"\r\n class=\"search-input\"\r\n placeholder=\"Search by document name, category, type, status or applicant name...\"\r\n [attr.aria-label]=\"'Search documents'\"\r\n />\r\n <button \r\n *ngIf=\"searchTerm\"\r\n type=\"button\"\r\n class=\"clear-button\"\r\n (click)=\"onClearSearch()\"\r\n [attr.aria-label]=\"'Clear search'\"\r\n >\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n </div>\r\n
|
|
4045
|
+
args: [{ selector: 'document-search', standalone: false, template: "<div class=\"search-container\">\r\n <div class=\"search-input-wrapper\">\r\n <i class=\"pi pi-search search-icon\"></i>\r\n <input \r\n type=\"text\" \r\n [(ngModel)]=\"searchTerm\"\r\n (ngModelChange)=\"onSearchInputChange($event)\"\r\n class=\"search-input\"\r\n placeholder=\"Search by document name, category, type, status or applicant name...\"\r\n [attr.aria-label]=\"'Search documents'\"\r\n />\r\n <button \r\n *ngIf=\"searchTerm\"\r\n type=\"button\"\r\n class=\"clear-button\"\r\n (click)=\"onClearSearch()\"\r\n [attr.aria-label]=\"'Clear search'\"\r\n >\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n </div>\r\n\r\n <button \r\n type=\"button\"\r\n class=\"clear-all-filters-link\"\r\n (click)=\"onClearAllFilters()\"\r\n [attr.aria-label]=\"'Clear all'\"\r\n >\r\n Clear All\r\n <i class=\"pi pi-times\"></i>\r\n </button>\r\n\r\n <div class=\"filters-section\">\r\n <button \r\n type=\"button\"\r\n class=\"action-button\"\r\n (click)=\"onActionClick.emit()\"\r\n [attr.aria-label]=\"'Open actions menu'\"\r\n >\r\n Actions\r\n </button>\r\n </div>\r\n</div> ", styles: [".search-container{display:flex;align-items:center;gap:1rem;width:100%;justify-content:flex-start;padding:10px}.search-input-wrapper{position:relative;flex:1;display:flex;align-items:center;max-width:50%;min-width:300px}.clear-all-filters-link{background:none;border:none;color:#0f8bfd;cursor:pointer;padding:8px 12px;border-radius:4px;font-size:16px;font-weight:500;text-decoration:none!important;transition:background-color .2s ease,color .2s ease;white-space:nowrap;flex-shrink:0;display:flex;justify-content:center;align-items:center;gap:4px}.filters-section{display:flex;align-items:center;gap:1rem;flex-shrink:0;margin-left:auto}.search-icon{position:absolute;left:12px;color:#6c757d;z-index:1}.search-input{width:100%;padding:12px 40px;border:1px solid #dee2e6;border-radius:8px;font-size:14px;outline:none;transition:border-color .2s ease,box-shadow .2s ease}.search-input:focus{border-color:#0f8bfd;box-shadow:0 0 0 3px #0f8bfd1a}.search-input::placeholder{color:#6c757d}.clear-button{position:absolute;right:12px;background:none;border:none;color:#6c757d;cursor:pointer;padding:4px;border-radius:4px;transition:background-color .2s ease,color .2s ease}.clear-button:hover{background-color:#f8f9fa;color:#495057}.action-button{background-color:#0f8bfd;color:#fff;border:none;padding:12px 24px;border-radius:8px;font-size:14px;font-weight:500;cursor:pointer;transition:background-color .2s ease,transform .1s ease;white-space:nowrap}.action-button:hover{background-color:#0d7ae6;transform:translateY(-1px)}.action-button:active{transform:translateY(0)}.action-button:focus{outline:none;box-shadow:0 0 0 3px #0f8bfd4d}@media (max-width: 768px){.search-container{flex-direction:column;gap:.75rem}.search-input-wrapper{max-width:100%}.filters-section{width:100%;justify-content:center;gap:.5rem}.action-button{width:auto;justify-content:center}}\n"] }]
|
|
3844
4046
|
}], ctorParameters: () => [{ type: DocumentHelperService }], propDecorators: { contextId: [{
|
|
3845
4047
|
type: Input
|
|
3846
4048
|
}], onActionClick: [{
|