@bnsights/bbsf-controls 1.0.178 → 1.0.179

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.
@@ -2122,6 +2122,7 @@ class FileUploadComponent {
2122
2122
  this.ERROR_DISPLAY_DURATION = 5000;
2123
2123
  this.MAX_MEMORY_USAGE = 100 * 1024 * 1024; // 100MB limit
2124
2124
  this.currentMemoryUsage = 0;
2125
+ this.hasClearedRequiredError = false; // Track if required error was already cleared
2125
2126
  this.isSubmitted = false;
2126
2127
  this.OnChange = new EventEmitter();
2127
2128
  this.isUploadComplete = new EventEmitter();
@@ -2143,6 +2144,11 @@ class FileUploadComponent {
2143
2144
  this.removeRequiredValidation = () => {
2144
2145
  this.controlUtility.removeRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
2145
2146
  };
2147
+ this.removeRequiredValidatorOnly = () => {
2148
+ this.validationRules = this.validationRules.filter(validator => validator !== Validators.required);
2149
+ this.fileUploadFormControl.setValidators(this.validationRules);
2150
+ this.fileUploadFormControl.updateValueAndValidity();
2151
+ };
2146
2152
  this.addRequiredValidation = () => {
2147
2153
  this.controlUtility.addRequiredValidation(this.fileUploadFormControl, this.validationRules, this.options);
2148
2154
  };
@@ -2557,9 +2563,28 @@ class FileUploadComponent {
2557
2563
  }
2558
2564
  showFileCountError(errorKey, message) {
2559
2565
  const currentErrors = this.fileUploadFormControl.errors || {};
2560
- currentErrors[errorKey] = message;
2561
- this.fileUploadFormControl.setErrors(currentErrors);
2566
+ // Preserve existing errors and add the new one
2567
+ const newErrors = { ...currentErrors };
2568
+ newErrors[errorKey] = message;
2569
+ this.fileUploadFormControl.setErrors(newErrors);
2562
2570
  this.fileUploadFormControl.markAsTouched();
2571
+ // Force the form control to be invalid
2572
+ this.fileUploadFormControl.markAsDirty();
2573
+ // Ensure the error persists
2574
+ this.forceValidationErrorDisplay(errorKey, message);
2575
+ }
2576
+ forceValidationErrorDisplay(errorKey, message) {
2577
+ // Force the validation error to persist by re-applying it after a short delay
2578
+ setTimeout(() => {
2579
+ const currentErrors = this.fileUploadFormControl.errors || {};
2580
+ if (!currentErrors[errorKey]) {
2581
+ const newErrors = { ...currentErrors };
2582
+ newErrors[errorKey] = message;
2583
+ this.fileUploadFormControl.setErrors(newErrors);
2584
+ this.fileUploadFormControl.markAsTouched();
2585
+ this.fileUploadFormControl.markAsDirty();
2586
+ }
2587
+ }, 100);
2563
2588
  }
2564
2589
  clearFileCountError(errorKey) {
2565
2590
  const currentErrors = this.fileUploadFormControl.errors;
@@ -2588,9 +2613,15 @@ class FileUploadComponent {
2588
2613
  const totalSizeMsg = this.utilityService.getResourceValue('TotalFileSizeExceeded')
2589
2614
  .replace('{maxSize}', this.options.maxSizeForAllFilesInMB.toString());
2590
2615
  const currentErrors = this.fileUploadFormControl.errors || {};
2591
- currentErrors['MaxSizeForAllFilesInMB'] = totalSizeMsg;
2592
- this.fileUploadFormControl.setErrors(currentErrors);
2616
+ // Preserve existing errors and add the new one
2617
+ const newErrors = { ...currentErrors };
2618
+ newErrors['MaxSizeForAllFilesInMB'] = totalSizeMsg;
2619
+ this.fileUploadFormControl.setErrors(newErrors);
2593
2620
  this.fileUploadFormControl.markAsTouched();
2621
+ // Force the form control to be invalid
2622
+ this.fileUploadFormControl.markAsDirty();
2623
+ // Ensure the error persists
2624
+ this.forceValidationErrorDisplay('MaxSizeForAllFilesInMB', totalSizeMsg);
2594
2625
  }
2595
2626
  validateFileSize(file) {
2596
2627
  const maxFileSize = this.options.fileMaxSizeInMB * this.BYTES_TO_MB;
@@ -2661,15 +2692,22 @@ class FileUploadComponent {
2661
2692
  return;
2662
2693
  const errorMessage = errors.join('<br/>');
2663
2694
  this.setValidationError('InvalidFiles', errorMessage);
2695
+ // Increase the error display duration to prevent errors from disappearing too quickly
2664
2696
  setTimeout(() => {
2665
2697
  this.clearInvalidFilesError();
2666
- }, this.ERROR_DISPLAY_DURATION);
2698
+ }, this.ERROR_DISPLAY_DURATION * 2); // Double the duration
2667
2699
  }
2668
2700
  setValidationError(errorKey, errorMessage) {
2669
2701
  const currentErrors = this.fileUploadFormControl.errors || {};
2670
- currentErrors[errorKey] = errorMessage;
2671
- this.fileUploadFormControl.setErrors(currentErrors);
2702
+ // Preserve existing errors and add the new one
2703
+ const newErrors = { ...currentErrors };
2704
+ newErrors[errorKey] = errorMessage;
2705
+ this.fileUploadFormControl.setErrors(newErrors);
2672
2706
  this.fileUploadFormControl.markAsTouched();
2707
+ // Force the form control to be invalid
2708
+ this.fileUploadFormControl.markAsDirty();
2709
+ // Ensure the error persists
2710
+ this.forceValidationErrorDisplay(errorKey, errorMessage);
2673
2711
  }
2674
2712
  clearInvalidFilesError() {
2675
2713
  const currentErrors = this.fileUploadFormControl.errors;
@@ -2684,9 +2722,16 @@ class FileUploadComponent {
2684
2722
  }
2685
2723
  }
2686
2724
  setFormControlError(errorKey, errorValue) {
2687
- this.fileUploadFormControl.setErrors({ [errorKey]: errorValue });
2725
+ const currentErrors = this.fileUploadFormControl.errors || {};
2726
+ // Preserve existing errors and add the new one
2727
+ const newErrors = { ...currentErrors };
2728
+ newErrors[errorKey] = errorValue;
2729
+ this.fileUploadFormControl.setErrors(newErrors);
2688
2730
  this.fileUploadFormControl.markAsTouched();
2731
+ this.fileUploadFormControl.markAsDirty();
2689
2732
  this.uploader.queue = [];
2733
+ // Ensure the error persists
2734
+ this.forceValidationErrorDisplay(errorKey, errorValue);
2690
2735
  }
2691
2736
  handleAsyncFileUpload(element, filesArray) {
2692
2737
  const uploadSubscription = this.fileUploadService.uploadFile(element._file).subscribe({
@@ -2829,11 +2874,30 @@ class FileUploadComponent {
2829
2874
  this.options.value = value;
2830
2875
  }
2831
2876
  preserveErrorsAndUpdateValue(value) {
2832
- const currentErrors = this.fileUploadFormControl.errors;
2877
+ // If we have a valid file value and haven't cleared the required error yet, remove it
2878
+ if (this.hasValidFileValue(value) && !this.hasClearedRequiredError) {
2879
+ // Use the custom method that only removes the validator without changing the isRequired option
2880
+ // This keeps the asterisk visible while removing the validation logic
2881
+ this.removeRequiredValidatorOnly();
2882
+ // Mark that we've cleared the required error
2883
+ this.hasClearedRequiredError = true;
2884
+ }
2885
+ // Set the form control value
2833
2886
  this.fileUploadFormControl.setValue(value, { emitEvent: false });
2887
+ // Update the form group control value
2834
2888
  this.group.get(this.options.name)?.setValue(value, { emitEvent: false });
2835
- if (currentErrors) {
2836
- this.fileUploadFormControl.setErrors(currentErrors);
2889
+ }
2890
+ hasValidFileValue(value) {
2891
+ if (!value)
2892
+ return false;
2893
+ if (this.options.isMultipleFile) {
2894
+ const multipleValue = value;
2895
+ return (multipleValue.uploadedFiles && multipleValue.uploadedFiles.length > 0) ||
2896
+ (multipleValue.existingFiles && multipleValue.existingFiles.length > 0);
2897
+ }
2898
+ else {
2899
+ const singleValue = value;
2900
+ return singleValue.file && singleValue.file.fileName !== '';
2837
2901
  }
2838
2902
  }
2839
2903
  handlePatchAndEmit() {
@@ -2873,13 +2937,15 @@ class FileUploadComponent {
2873
2937
  this.fileUploadModel = null;
2874
2938
  if (this.options.isRequired) {
2875
2939
  this.fileUploadFormControl.markAsTouched();
2940
+ // Use the existing utility function to add required validation back
2941
+ this.addRequiredValidation();
2876
2942
  }
2877
- const currentErrors = this.fileUploadFormControl.errors;
2943
+ // Reset the flag so required validation can work again
2944
+ this.hasClearedRequiredError = false;
2878
2945
  this.group.get(this.options.name)?.setValue(this.fileUploadModel, { emitEvent: false });
2879
- if (currentErrors) {
2880
- this.fileUploadFormControl.setErrors(currentErrors);
2881
- }
2882
2946
  this.options.value = this.fileUploadModel;
2947
+ // Re-evaluate all validations after file removal
2948
+ this.reEvaluateAllValidations();
2883
2949
  }
2884
2950
  handleMultipleFileRemoval(item) {
2885
2951
  // Clean up blob URL
@@ -2945,17 +3011,97 @@ class FileUploadComponent {
2945
3011
  MinFileCountValidationKey: this.options.minNoOfFiles
2946
3012
  });
2947
3013
  this.fileUploadFormControl.markAsTouched();
3014
+ this.addRequiredValidation();
3015
+ this.hasClearedRequiredError = false;
3016
+ }
3017
+ // Re-evaluate all validations after file removal
3018
+ this.reEvaluateAllValidations();
3019
+ }
3020
+ reEvaluateAllValidations() {
3021
+ // Clear all existing validation errors first
3022
+ this.fileUploadFormControl.setErrors(null);
3023
+ // Re-apply required validation if needed
3024
+ if (this.options.isRequired) {
3025
+ this.addRequiredValidation();
3026
+ }
3027
+ // Re-validate file count constraints
3028
+ this.reValidateFileCountConstraints();
3029
+ // Re-validate total file size
3030
+ this.reValidateTotalFileSize();
3031
+ // Re-validate individual files
3032
+ this.reValidateIndividualFiles();
3033
+ // Clear validation errors that are no longer applicable
3034
+ this.clearObsoleteValidationErrors();
3035
+ // Update form control validity
3036
+ this.fileUploadFormControl.updateValueAndValidity();
3037
+ }
3038
+ clearObsoleteValidationErrors() {
3039
+ const currentFileCount = this.uploader.queue.length;
3040
+ // Clear max file count error if current count is within limit
3041
+ if (this.options.maxNoOfFiles > 0 && currentFileCount <= this.options.maxNoOfFiles) {
3042
+ this.clearFileCountError('MaxFileCountValidationKey');
3043
+ }
3044
+ // Clear min file count error if current count meets minimum requirement
3045
+ if (this.options.minNoOfFiles > 0 && currentFileCount >= this.options.minNoOfFiles) {
3046
+ this.clearFileCountError('MinFileCountValidationKey');
3047
+ }
3048
+ // Clear total size error if current total size is within limit
3049
+ if (this.options.maxSizeForAllFilesInMB > 0) {
3050
+ const totalSize = this.uploader.queue.reduce((sum, element) => sum + element.file.size, 0);
3051
+ const maxSizeBytes = this.options.maxSizeForAllFilesInMB * this.BYTES_TO_MB;
3052
+ if (totalSize <= maxSizeBytes) {
3053
+ this.clearFileCountError('MaxSizeForAllFilesInMB');
3054
+ }
3055
+ }
3056
+ }
3057
+ reValidateFileCountConstraints() {
3058
+ const currentFileCount = this.uploader.queue.length;
3059
+ // Check minimum file count
3060
+ if (this.options.minNoOfFiles > 0 && currentFileCount < this.options.minNoOfFiles) {
3061
+ const minFileMsg = this.utilityService.getResourceValue('MinimumFilesRequired')
3062
+ .replace('{count}', this.options.minNoOfFiles.toString());
3063
+ this.showFileCountError('MinFileCountValidationKey', minFileMsg);
3064
+ }
3065
+ // Check maximum file count
3066
+ if (this.options.maxNoOfFiles > 0 && currentFileCount > this.options.maxNoOfFiles) {
3067
+ const maxFileMsg = this.utilityService.getResourceValue('MaximumFilesExceeded') ||
3068
+ `Maximum {maxCount} files allowed. You have selected {currentCount} files.`;
3069
+ const finalMsg = maxFileMsg
3070
+ .replace('{maxCount}', this.options.maxNoOfFiles.toString())
3071
+ .replace('{currentCount}', currentFileCount.toString());
3072
+ this.showFileCountError('MaxFileCountValidationKey', finalMsg);
3073
+ }
3074
+ }
3075
+ reValidateTotalFileSize() {
3076
+ if (this.options.maxSizeForAllFilesInMB > 0) {
3077
+ const totalSize = this.uploader.queue.reduce((sum, element) => sum + element.file.size, 0);
3078
+ const maxSizeBytes = this.options.maxSizeForAllFilesInMB * this.BYTES_TO_MB;
3079
+ if (totalSize > maxSizeBytes) {
3080
+ this.showTotalSizeError();
3081
+ }
3082
+ }
3083
+ }
3084
+ reValidateIndividualFiles() {
3085
+ // Re-validate each remaining file for size and type
3086
+ for (const element of this.uploader.queue) {
3087
+ const file = element.file;
3088
+ if (!file)
3089
+ continue;
3090
+ // Check file size
3091
+ if (!this.validateIndividualFileSize(file)) {
3092
+ this.setFormControlError('FileMaxSizeInMB', `${this.options.fileMaxSizeInMB}MB`);
3093
+ }
3094
+ // Check file type
3095
+ if (!this.validateIndividualFileType(file)) {
3096
+ this.setFormControlError('ToolTipTypeError', this.toolTipTypeArray);
3097
+ }
2948
3098
  }
2949
3099
  }
2950
3100
  updateMultipleFileModel() {
2951
3101
  this.multipleFileUploadModel.correlationID_GUID = this.options.value?.correlationID_GUID;
2952
- const currentErrors = this.fileUploadFormControl.errors;
2953
3102
  this.fileUploadFormControl.setValue(this.multipleFileUploadModel, { emitEvent: false });
2954
3103
  this.group.get(this.options.name)?.setValue(this.multipleFileUploadModel, { emitEvent: false });
2955
3104
  this.options.value = this.multipleFileUploadModel;
2956
- if (currentErrors) {
2957
- this.fileUploadFormControl.setErrors(currentErrors);
2958
- }
2959
3105
  }
2960
3106
  convertSizeToMB(size) {
2961
3107
  if (size === 0) {