argos/dmp-frontend/src/app/core/services/user-settings/user-settings.service.ts

333 lines
12 KiB
TypeScript

import { Injectable } from '@angular/core';
import { UserSettingPersist, UserSettingsInformation, UserSettings as UserSettingsObject } from '@app/core/model/user-settings/user-settings.model';
import { BaseService } from '@common/base/base.service';
import { Guid } from '@common/types/guid';
import * as moment from 'moment';
import { Moment } from 'moment';
import { Observable, Subject, of as observableOf } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { AuthService, LoginStatus } from '../auth/auth.service';
import { ConfigurationService } from '../configuration/configuration.service';
import { UserSettingsHttpService } from './user-settings-http.service';
export enum UserSettingsType {
Setting = 0,
Config = 1
}
@Injectable()
export class UserSettingsService extends BaseService {
static CACHE_SETTINGS_LIFETIME = 7200; // (value is in seconds) 2 hours
public userSettingUpdated: Subject<string>;
private userSettingsMap: Map<String, any> = new Map<String, any>();
private userSettingsLastAccessMap: Map<String, Moment> = new Map<String, Moment>();
constructor(
private userSettingsHttpService: UserSettingsHttpService,
private authService: AuthService,
private installationConfigurationService: ConfigurationService
) {
super();
this.userSettingUpdated = new Subject<string>();
this.authService.getAuthenticationStateObservable().pipe(takeUntil(this._destroyed)).subscribe(authenticationState => {
if (authenticationState.loginStatus === LoginStatus.LoggedOut) {
localStorage.clear();
this.userSettingsMap = new Map<String, any>();
this.userSettingsLastAccessMap = new Map<String, Moment>();
}
});
}
public getUserSettingUpdatedObservable(): Observable<string> {
return this.userSettingUpdated.asObservable();
}
get<T>(userSettingsInformation: UserSettingsInformation<T>): Observable<UserSettings<T>> {
if (this.userSettingsLastAccessMap.has(userSettingsInformation.key)) {
const lastAccess = this.userSettingsLastAccessMap.get(userSettingsInformation.key);
const difference = moment.utc().diff(lastAccess, 'seconds');
if (difference > UserSettingsService.CACHE_SETTINGS_LIFETIME) {
this.clearSetting(userSettingsInformation.key);
}
}
this.userSettingsLastAccessMap.set(userSettingsInformation.key, moment.utc());
if (this.userSettingsMap.has(userSettingsInformation.key)) { return observableOf(this.userSettingsMap.get(userSettingsInformation.key)); }
return this.loadUserSettings<T>(userSettingsInformation);
}
set<T>(setting: UserSetting<T>, isDefault: boolean = false, userSettingsInformation: UserSettingsInformation<T> = null) {
const userSetting = this.buildUserSetting(setting, userSettingsInformation.key, isDefault);
let userSettings: UserSettings<T> = this.buildUserSettings(userSetting, userSettingsInformation.key);
if (this.userSettingsMap.has(userSettingsInformation.key)) {
userSettings = this.userSettingsMap.get(userSettingsInformation.key);
if (userSettings == null) { userSettings = this.buildUserSettings(userSetting, userSettingsInformation.key); }
const itemIndex = userSettings.settings.findIndex(item => item.id === userSetting.id);
if (itemIndex < 0) {
userSettings.settings.push(userSetting);
} else {
userSettings.settings[itemIndex] = userSetting;
}
if (isDefault) {
userSettings.defaultSetting = userSetting;
}
} else {
userSetting.isDefault = isDefault;
if (isDefault) { userSettings.defaultSetting = userSetting; }
}
userSettings.settings.forEach((element) => {
if (!(element.id === userSettings.defaultSetting.id)) {
element.isDefault = false;
}
});
this.persistUserSettings(userSettingsInformation.key, userSettings, userSettingsInformation, true);
this.userSettingsLastAccessMap.set(userSettingsInformation.key, moment.utc());
}
remove<T>(id: Guid, userSettingsInformation: UserSettingsInformation<T> = null) {
this.deleteFromWebServer(id, userSettingsInformation);
}
share(userSettings: UserSetting<any>, targetId: Guid, newName: string): Observable<UserSettingsObject> {
const userSettingsToPersist: UserSettingPersist = {
id: null,
key: userSettings.key,
isDefault: false,
name: newName,
type: userSettings.type,
value: JSON.stringify(userSettings.value),
hash: null
};
return this.userSettingsHttpService.share(userSettingsToPersist, targetId);
}
private deleteFromWebServer<T>(id: Guid, userSettingsInformation: UserSettingsInformation<T>) {
this.userSettingsHttpService.delete(id).pipe(takeUntil(this._destroyed)).subscribe(item => {
const result: UserSettings<T> = (item ? this.toTypedUserSettings<T>(item as UserSettingsObject) : null);
this.persistUserSettings(userSettingsInformation.key, result, userSettingsInformation, false);
this.userSettingUpdated.next(userSettingsInformation.key);
});
}
private buildUserSettings<T>(setting: UserSetting<T>, key: string): UserSettings<T> {
const userSettings: UserSettings<T> = {
key: key,
settings: [setting],
defaultSetting: setting
};
return userSettings;
}
private buildUserSetting<T>(setting: UserSetting<T>, key: string, isDefault: boolean): UserSetting<T> {
const userSettings: UserSetting<T> = {
id: setting.id,
key: key,
name: setting.name,
value: setting.value,
type: UserSettingsType.Setting,
isDefault: isDefault,
hash: setting.hash
};
return userSettings;
}
private loadUserSettings<T>(userSettingsInformation: UserSettingsInformation<T>): Observable<UserSettings<T>> {
const localStorageItem = this.loadFromLocalStorage(userSettingsInformation.key);
if (localStorageItem) {
const jsonLocalStorageItem = JSON.parse(localStorageItem);
if (jsonLocalStorageItem) { return observableOf((jsonLocalStorageItem as UserSettings<T>)); }
}
return this.userSettingsHttpService.getSingle(userSettingsInformation.key).pipe(
// catchError(() => {
// const result: UserSettings<T> = this.defaultValue(userSettingsInformation);
// this.persistUserSettings(userSettingsInformation.key, result, userSettingsInformation, false);
// return observableOf(result);
// }),
map(x => {
const result: UserSettings<T> = (x ? this.toTypedUserSettings<T>(x as UserSettingsObject) : null);
this.persistUserSettings(userSettingsInformation.key, result, userSettingsInformation, false);
return result;
}));
}
private persistUserSettings<T>(key: string, userSettings: UserSettings<T>, userSettingsInformation: UserSettingsInformation<T>, pushChangeToServer: boolean = true) {
this.userSettingsMap.set(key, userSettings);
this.storeToLocalStorage(key, userSettings);
if (pushChangeToServer) {
this.persistSettingsChanges(key, userSettings, userSettingsInformation);
}
}
private persistSettingsChanges<T>(key: string, userSettings: UserSettings<T>, userSettingsInformation: UserSettingsInformation<T>, updateLocalAfterPush: boolean = true) {
const changesToPush: UserSettingPersist[] = [];
const userSettingsPersist = this.prepareSettingsToPushToWebServer(userSettings);
userSettingsPersist.forEach(element => {
changesToPush.push(element);
});
this.pushToWebServer(changesToPush, userSettingsInformation, updateLocalAfterPush);
}
private buildPersistModel(element: any): UserSettingPersist {
const userSettingsToPersist: UserSettingPersist = {
id: element.id,
key: element.key,
isDefault: element.isDefault,
name: element.name,
type: element.type,
value: JSON.stringify(element.value),
hash: element.hash
};
return userSettingsToPersist;
}
private prepareSettingsToPushToWebServer(userSettings: UserSettings<any>): UserSettingPersist[] {
const userSettingsArray: UserSettingPersist[] = [];
if (userSettings && userSettings.settings && userSettings.settings.length !== 0) {
userSettings.settings.forEach(element => {
userSettingsArray.push(this.buildPersistModel(element));
});
}
return userSettingsArray;
}
private toTypedUserSettings<T>(userSettings: UserSettingsObject): UserSettings<T> {
const settingsArray: UserSetting<T>[] = [];
if (userSettings && userSettings.settings && userSettings.settings.length !== 0) {
userSettings.settings.forEach(element => {
const settingElement: UserSetting<T> = {
id: element.id,
key: userSettings.key,
name: element.name,
value: JSON.parse(element.value),
userId: element.userId,
updatedAt: element.updatedAt,
createdAt: element.createdAt,
hash: element.hash,
type: element.type,
isDefault: element.isDefault
};
settingsArray.push(settingElement);
});
}
let defaultSetting: UserSetting<T> = null;
if (userSettings.defaultSetting) {
const defaultSettingValue = userSettings.defaultSetting;
defaultSetting = {
id: defaultSettingValue.id,
key: userSettings.key,
name: defaultSettingValue.name,
value: userSettings.defaultSetting ? JSON.parse(defaultSettingValue.value) : defaultSettingValue.value,
userId: defaultSettingValue.userId,
updatedAt: defaultSettingValue.updatedAt,
createdAt: defaultSettingValue.createdAt,
hash: defaultSettingValue.hash,
type: defaultSettingValue.type,
isDefault: defaultSettingValue.isDefault
};
}
const result: UserSettings<T> = {
key: userSettings.key,
settings: settingsArray,
defaultSetting: defaultSetting
};
return result;
}
private pushToWebServer<T>(userSettingsToPersist: UserSettingPersist[], userSettingsInformation: UserSettingsInformation<T>, updateLocalAfterPush: boolean) {
if (!userSettingsToPersist || userSettingsToPersist.length === 0) { return; }
this.userSettingsHttpService.persistAll(userSettingsToPersist).pipe(takeUntil(this._destroyed)).subscribe(items => {
if (updateLocalAfterPush) {
const result: UserSettings<any>[] = items ? items.map(x => this.toTypedUserSettings<any>(x as UserSettingsObject)) : [];
result.forEach(item => {
if (item.defaultSetting != null) {
this.userSettingsMap.set(item.key, item);
this.storeToLocalStorage(item.key, item);
} else {
this.clearSetting(item.key);
}
this.userSettingUpdated.next(item.key);
});
}
});
}
private clearSetting(key: string) {
this.userSettingsMap.delete(key);
this.userSettingsLastAccessMap.delete(key);
this.deleteFromLocalStorage(key);
}
private loadFromLocalStorage(key: string) {
return localStorage.getItem(this.generateLocalStorageKey(key));
}
private storeToLocalStorage(key: string, value: any) {
return localStorage.setItem(this.generateLocalStorageKey(key), JSON.stringify(value));
}
private deleteFromLocalStorage(key: string) {
return localStorage.removeItem(this.generateLocalStorageKey(key));
}
private generateLocalStorageKey(key: string): string {
return `${this.getUserSettingsVersion()}_${this.getUserId()}_${key}`;
}
// private defaultValue<T>(userSettingsInformation: UserSettingsInformation<T>): UserSettings<T> {
// const defaultSetting: UserSetting<T> = {
// id: null,
// name: null,
// userId: this.getUserId(),
// key: userSettingsInformation.key,
// type: UserSettingsType.Config,
// isDefault: true,
// value: new userSettingsInformation.type()
// };
// const userSettings: UserSettings<T> = {
// defaultSetting: defaultSetting,
// key: userSettingsInformation.key,
// settings: [defaultSetting]
// };
// return userSettings;
// }
private getUserId(): Guid {
return this.authService.userId();
}
private getUserSettingsVersion(): string {
return this.installationConfigurationService.userSettingsVersion;
}
}
export interface UserSettings<T> {
key: string;
settings: UserSetting<T>[];
defaultSetting: UserSetting<T>;
}
export interface UserSetting<T> {
id: Guid;
name: string;
key: string;
type: UserSettingsType;
value: T;
createdAt?: Date;
updatedAt?: Date;
hash?: string;
userId?: Guid;
isDefault?: boolean;
}