119602: Rework settings validation

This commit is contained in:
Andreas Awouters
2025-02-21 12:53:44 +01:00
parent cd825ac0da
commit dcd32c48c3
4 changed files with 23 additions and 16 deletions

View File

@@ -40,5 +40,5 @@ export class AccessibilitySettingsServiceStub {
isValid = jasmine.createSpy('isValid').and.returnValue(true); isValid = jasmine.createSpy('isValid').and.returnValue(true);
allValid = jasmine.createSpy('allValid').and.returnValue(true); formValuesValid = jasmine.createSpy('allValid').and.returnValue(true);
} }

View File

@@ -24,11 +24,16 @@ export const ACCESSIBILITY_COOKIE = 'dsAccessibilityCookie';
export const ACCESSIBILITY_SETTINGS_METADATA_KEY = 'dspace.accessibility.settings'; export const ACCESSIBILITY_SETTINGS_METADATA_KEY = 'dspace.accessibility.settings';
/** /**
* Type containing all possible accessibility settings. * Array containing all possible accessibility settings.
* When adding new settings, make sure to add the new setting to the accessibility-settings component form. * When adding new settings, make sure to add the new setting to the accessibility-settings component form.
* The converter methods to convert from stored format to form format (and vice-versa) need to be updated as well. * The converter methods to convert from stored format to form format (and vice-versa) need to be updated as well.
*/ */
export type AccessibilitySetting = 'notificationTimeOut' | 'liveRegionTimeOut'; export const accessibilitySettingKeys = ['notificationTimeOut', 'liveRegionTimeOut'] as const;
/**
* Type representing the possible accessibility settings
*/
export type AccessibilitySetting = typeof accessibilitySettingKeys[number];
/** /**
* Type representing an object that contains accessibility settings values for all accessibility settings. * Type representing an object that contains accessibility settings values for all accessibility settings.
@@ -294,24 +299,26 @@ export class AccessibilitySettingsService {
} }
/** /**
* Returns true if the provided value is a valid value for the provided AccessibilitySetting. * Returns true if the provided AccessibilitySetting is valid in regard to the provided formValues.
*/ */
isValid(setting: AccessibilitySetting | string, value: string): boolean { isValid(setting: AccessibilitySetting, formValues: AccessibilitySettingsFormValues): boolean {
switch (setting) { switch (setting) {
case 'notificationTimeOut': case 'notificationTimeOut':
return hasNoValue(value) || parseFloat(value) > 0; return formValues.notificationTimeOutEnabled ?
hasNoValue(formValues.notificationTimeOut) || parseFloat(formValues.notificationTimeOut) > 0 :
true;
case 'liveRegionTimeOut': case 'liveRegionTimeOut':
return hasNoValue(value) || parseFloat(value) > 0; return hasNoValue(formValues.liveRegionTimeOut) || parseFloat(formValues.liveRegionTimeOut) > 0;
default: default:
throw new Error(`Unhandled accessibility setting during validity check: ${setting}`); throw new Error(`Unhandled accessibility setting during validity check: ${setting}`);
} }
} }
/** /**
* Returns true if all settings in the provided AccessibilitySettings object are valid * Returns true if all settings in the provided AccessibilitySettingsFormValues object are valid
*/ */
allValid(settings: AccessibilitySettings) { formValuesValid(formValues: AccessibilitySettingsFormValues) {
return Object.entries(settings).every(([setting, value], _) => this.isValid(setting, value)); return accessibilitySettingKeys.every(setting => this.isValid(setting, formValues));
} }
} }

View File

@@ -30,12 +30,12 @@
<div class="col-sm-4"> <div class="col-sm-4">
<input [type]="'number'" [id]="'notificationTimeOutInput'" class="form-control" <input [type]="'number'" [id]="'notificationTimeOutInput'" class="form-control"
[ngClass]="{'is-invalid': !settingsService.isValid('notificationTimeOut', formValues.notificationTimeOut)}" [ngClass]="{'is-invalid': !settingsService.isValid('notificationTimeOut', formValues)}"
[min]="1" [min]="1"
[readOnly]="!formValues.notificationTimeOutEnabled" [readOnly]="!formValues.notificationTimeOutEnabled"
[(ngModel)]="formValues.notificationTimeOut" [ngModelOptions]="{ standalone: true }" [(ngModel)]="formValues.notificationTimeOut" [ngModelOptions]="{ standalone: true }"
[attr.aria-describedby]="'notificationTimeOutHint'"> [attr.aria-describedby]="'notificationTimeOutHint'">
<div class="invalid-feedback" [ngClass]="{ 'd-block': !settingsService.isValid('notificationTimeOut', formValues.notificationTimeOut) }"> <div class="invalid-feedback" [ngClass]="{ 'd-block': !settingsService.isValid('notificationTimeOut', formValues) }">
{{ 'info.accessibility-settings.notificationTimeOut.invalid' | translate }} {{ 'info.accessibility-settings.notificationTimeOut.invalid' | translate }}
</div> </div>
</div> </div>
@@ -57,11 +57,11 @@
<div class="col-sm-4"> <div class="col-sm-4">
<input [type]="'number'" [id]="'liveRegionTimeOutInput'" class="form-control" <input [type]="'number'" [id]="'liveRegionTimeOutInput'" class="form-control"
[ngClass]="{'is-invalid': !settingsService.isValid('liveRegionTimeOut', formValues.liveRegionTimeOut)}" [ngClass]="{'is-invalid': !settingsService.isValid('liveRegionTimeOut', formValues)}"
[min]="1" [min]="1"
[(ngModel)]="formValues.liveRegionTimeOut" [ngModelOptions]="{ standalone: true }" [(ngModel)]="formValues.liveRegionTimeOut" [ngModelOptions]="{ standalone: true }"
[attr.aria-describedby]="'liveRegionTimeOutHint'"> [attr.aria-describedby]="'liveRegionTimeOutHint'">
<div class="invalid-feedback" [ngClass]="{ 'd-block': !settingsService.isValid('liveRegionTimeOut', formValues.liveRegionTimeOut) }"> <div class="invalid-feedback" [ngClass]="{ 'd-block': !settingsService.isValid('liveRegionTimeOut', formValues) }">
{{ 'info.accessibility-settings.liveRegionTimeOut.invalid' | translate }} {{ 'info.accessibility-settings.liveRegionTimeOut.invalid' | translate }}
</div> </div>
</div> </div>

View File

@@ -61,9 +61,9 @@ export class AccessibilitySettingsComponent implements OnInit, OnDestroy {
*/ */
saveSettings() { saveSettings() {
const formValues = this.formValues; const formValues = this.formValues;
const convertedValues = this.settingsService.convertFormValuesToStoredValues(formValues);
if (this.settingsService.allValid(convertedValues)) { if (this.settingsService.formValuesValid(formValues)) {
const convertedValues = this.settingsService.convertFormValuesToStoredValues(formValues);
this.settingsService.setSettings(convertedValues).pipe(take(1)).subscribe(location => { this.settingsService.setSettings(convertedValues).pipe(take(1)).subscribe(location => {
if (location !== 'failed') { if (location !== 'failed') {
this.notificationsService.success(null, this.translateService.instant('info.accessibility-settings.save-notification.' + location)); this.notificationsService.success(null, this.translateService.instant('info.accessibility-settings.save-notification.' + location));