mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 23:13:04 +00:00
Merge branch 'accessibility-settings-7.6' into accessibility-settings-main
# Conflicts: # src/app/accessibility/accessibility-settings.service.spec.ts # src/app/accessibility/accessibility-settings.service.ts # src/app/info/accessibility-settings/accessibility-settings.component.spec.ts # src/app/info/accessibility-settings/accessibility-settings.component.ts # src/app/shared/cookies/klaro-configuration.ts # src/assets/i18n/en.json5
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
Inject,
|
||||
Injectable,
|
||||
} from '@angular/core';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {
|
||||
combineLatest,
|
||||
Observable,
|
||||
of,
|
||||
switchMap,
|
||||
@@ -10,13 +14,19 @@ import {
|
||||
take,
|
||||
} from 'rxjs/operators';
|
||||
|
||||
import {
|
||||
APP_CONFIG,
|
||||
AppConfig,
|
||||
} from '../../config/app-config.interface';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { AuthService } from '../core/auth/auth.service';
|
||||
import { EPersonDataService } from '../core/eperson/eperson-data.service';
|
||||
import { EPerson } from '../core/eperson/models/eperson.model';
|
||||
import { CookieService } from '../core/services/cookie.service';
|
||||
import { getFirstCompletedRemoteData } from '../core/shared/operators';
|
||||
import { OrejimeService } from '../shared/cookies/orejime.service';
|
||||
import {
|
||||
hasNoValue,
|
||||
hasValue,
|
||||
isNotEmpty,
|
||||
} from '../shared/empty.util';
|
||||
@@ -33,11 +43,16 @@ export const ACCESSIBILITY_COOKIE = 'dsAccessibilityCookie';
|
||||
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.
|
||||
* 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.
|
||||
@@ -73,6 +88,8 @@ export class AccessibilitySettingsService {
|
||||
protected cookieService: CookieService,
|
||||
protected authService: AuthService,
|
||||
protected ePersonService: EPersonDataService,
|
||||
protected orejimeService: OrejimeService,
|
||||
@Inject(APP_CONFIG) protected appConfig: AppConfig,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -136,8 +153,9 @@ export class AccessibilitySettingsService {
|
||||
*
|
||||
* Returns 'cookie' when the changes were stored in the cookie.
|
||||
* Returns 'metadata' when the changes were stored in metadata.
|
||||
* Returns 'failed' when both options failed.
|
||||
*/
|
||||
set(setting: AccessibilitySetting, value: string): Observable<'cookie' | 'metadata'> {
|
||||
set(setting: AccessibilitySetting, value: string): Observable<'metadata' | 'cookie' | 'failed'> {
|
||||
return this.updateSettings({ [setting]: value });
|
||||
}
|
||||
|
||||
@@ -148,18 +166,15 @@ export class AccessibilitySettingsService {
|
||||
*
|
||||
* Returns 'cookie' when the changes were stored in the cookie.
|
||||
* Returns 'metadata' when the changes were stored in metadata.
|
||||
* Returns 'failed' when both options failed.
|
||||
*/
|
||||
setSettings(settings: AccessibilitySettings): Observable<'cookie' | 'metadata'> {
|
||||
setSettings(settings: AccessibilitySettings): Observable<'metadata' | 'cookie' | 'failed'> {
|
||||
return this.setSettingsInAuthenticatedUserMetadata(settings).pipe(
|
||||
take(1),
|
||||
map((succeeded) => {
|
||||
if (!succeeded) {
|
||||
this.setSettingsInCookie(settings);
|
||||
return 'cookie';
|
||||
} else {
|
||||
return 'metadata';
|
||||
}
|
||||
}),
|
||||
map(saveLocation => saveLocation === 'metadata'),
|
||||
switchMap((savedInMetadata) =>
|
||||
savedInMetadata ? ofMetadata() : this.setSettingsInCookie(settings),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -169,8 +184,9 @@ export class AccessibilitySettingsService {
|
||||
*
|
||||
* Returns 'cookie' when the changes were stored in the cookie.
|
||||
* Returns 'metadata' when the changes were stored in metadata.
|
||||
* Returns 'failed' when both options failed.
|
||||
*/
|
||||
updateSettings(settings: AccessibilitySettings): Observable<'cookie' | 'metadata'> {
|
||||
updateSettings(settings: AccessibilitySettings): Observable<'metadata' | 'cookie' | 'failed'> {
|
||||
return this.getAll().pipe(
|
||||
take(1),
|
||||
map(currentSettings => Object.assign({}, currentSettings, settings)),
|
||||
@@ -181,9 +197,9 @@ export class AccessibilitySettingsService {
|
||||
/**
|
||||
* Attempts to set the provided settings on the currently authorized user's metadata.
|
||||
* Emits false when no user is authenticated or when the metadata update failed.
|
||||
* Emits true when the metadata update succeeded.
|
||||
* Emits 'metadata' when the metadata update succeeded, and 'failed' otherwise.
|
||||
*/
|
||||
setSettingsInAuthenticatedUserMetadata(settings: AccessibilitySettings): Observable<boolean> {
|
||||
setSettingsInAuthenticatedUserMetadata(settings: AccessibilitySettings): Observable<'metadata' | 'failed'> {
|
||||
return this.authService.getAuthenticatedUserFromStoreIfAuthenticated().pipe(
|
||||
take(1),
|
||||
switchMap(user => {
|
||||
@@ -192,7 +208,7 @@ export class AccessibilitySettingsService {
|
||||
const clonedUser = cloneDeep(user);
|
||||
return this.setSettingsInMetadata(clonedUser, settings);
|
||||
} else {
|
||||
return of(false);
|
||||
return ofFailed();
|
||||
}
|
||||
}),
|
||||
);
|
||||
@@ -205,7 +221,7 @@ export class AccessibilitySettingsService {
|
||||
setSettingsInMetadata(
|
||||
user: EPerson,
|
||||
settings: AccessibilitySettings,
|
||||
): Observable<boolean> {
|
||||
): Observable<'metadata' | 'failed'> {
|
||||
if (isNotEmpty(settings)) {
|
||||
user.setMetadata(ACCESSIBILITY_SETTINGS_METADATA_KEY, null, JSON.stringify(settings));
|
||||
} else {
|
||||
@@ -217,35 +233,49 @@ export class AccessibilitySettingsService {
|
||||
switchMap(operations =>
|
||||
isNotEmpty(operations) ? this.ePersonService.patch(user, operations) : createSuccessfulRemoteDataObject$({})),
|
||||
getFirstCompletedRemoteData(),
|
||||
map(rd => rd.hasSucceeded),
|
||||
switchMap(rd => rd.hasSucceeded ? ofMetadata() : ofFailed()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the provided settings in a cookie
|
||||
* Attempts to set the provided settings in a cookie.
|
||||
* Emits 'failed' when setting in a cookie failed due to the cookie not being accepted, 'cookie' when it succeeded.
|
||||
*/
|
||||
setSettingsInCookie(settings: AccessibilitySettings) {
|
||||
if (isNotEmpty(settings)) {
|
||||
this.cookieService.set(ACCESSIBILITY_COOKIE, settings, { expires: environment.accessibility.cookieExpirationDuration });
|
||||
} else {
|
||||
this.cookieService.remove(ACCESSIBILITY_COOKIE);
|
||||
}
|
||||
setSettingsInCookie(settings: AccessibilitySettings): Observable<'cookie' | 'failed'> {
|
||||
return this.orejimeService.getSavedPreferences().pipe(
|
||||
map(preferences => preferences.accessibility),
|
||||
map((accessibilityCookieAccepted: boolean) => {
|
||||
if (accessibilityCookieAccepted) {
|
||||
if (isNotEmpty(settings)) {
|
||||
this.cookieService.set(ACCESSIBILITY_COOKIE, settings, { expires: this.appConfig.accessibility.cookieExpirationDuration });
|
||||
} else {
|
||||
this.cookieService.remove(ACCESSIBILITY_COOKIE);
|
||||
}
|
||||
|
||||
return 'cookie';
|
||||
} else {
|
||||
return 'failed';
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all settings in the cookie and attempts to clear settings in metadata.
|
||||
* Emits true if settings in metadata were cleared and false otherwise.
|
||||
* Emits an array mentioning which settings succeeded or failed.
|
||||
*/
|
||||
clearSettings(): Observable<boolean> {
|
||||
this.setSettingsInCookie({});
|
||||
return this.setSettingsInAuthenticatedUserMetadata({});
|
||||
clearSettings(): Observable<['cookie' | 'failed', 'metadata' | 'failed']> {
|
||||
return combineLatest([
|
||||
this.setSettingsInCookie({}),
|
||||
this.setSettingsInAuthenticatedUserMetadata({}),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the placeholder to be used for the provided AccessibilitySetting.
|
||||
* Returns an empty string when no placeholder is specified for the provided setting.
|
||||
* Retrieve the default value to be used for the provided AccessibilitySetting.
|
||||
* Returns an empty string when no default value is specified for the provided setting.
|
||||
*/
|
||||
getPlaceholder(setting: AccessibilitySetting): string {
|
||||
getDefaultValue(setting: AccessibilitySetting): string {
|
||||
switch (setting) {
|
||||
case 'notificationTimeOut':
|
||||
return millisecondsToSeconds(environment.notifications.timeOut.toString());
|
||||
@@ -287,6 +317,28 @@ export class AccessibilitySettingsService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the provided AccessibilitySetting is valid in regard to the provided formValues.
|
||||
*/
|
||||
isValid(setting: AccessibilitySetting, formValues: AccessibilitySettingsFormValues): boolean {
|
||||
switch (setting) {
|
||||
case 'notificationTimeOut':
|
||||
return formValues.notificationTimeOutEnabled ?
|
||||
hasNoValue(formValues.notificationTimeOut) || parseFloat(formValues.notificationTimeOut) > 0 :
|
||||
true;
|
||||
case 'liveRegionTimeOut':
|
||||
return hasNoValue(formValues.liveRegionTimeOut) || parseFloat(formValues.liveRegionTimeOut) > 0;
|
||||
default:
|
||||
throw new Error(`Unhandled accessibility setting during validity check: ${setting}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all settings in the provided AccessibilitySettingsFormValues object are valid
|
||||
*/
|
||||
formValuesValid(formValues: AccessibilitySettingsFormValues) {
|
||||
return accessibilitySettingKeys.every(setting => this.isValid(setting, formValues));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,3 +366,11 @@ function millisecondsToSeconds(millisecondsStr: string): string {
|
||||
return (milliseconds / 1000).toString();
|
||||
}
|
||||
}
|
||||
|
||||
function ofMetadata(): Observable<'metadata'> {
|
||||
return of('metadata');
|
||||
}
|
||||
|
||||
function ofFailed(): Observable<'failed'> {
|
||||
return of('failed');
|
||||
}
|
||||
|
Reference in New Issue
Block a user