Warning, /firebird/firebird-ng/src/app/utils/config-property.ts is written in an unsupported language. File is not indexed.
0001 import {BehaviorSubject, Observable} from 'rxjs';
0002
0003
0004 /**
0005 * Storage general interface for storing ConfigProperty-ies.
0006 * ConfigProperty uses the storage to save and load values
0007 */
0008 interface ConfigPropertyStorage {
0009 getItem(key: string): string | null;
0010 setItem(key: string, value: string): void;
0011 }
0012
0013 /**
0014 * Use local storage to save load ConfigProperty
0015 */
0016 class ConfigPropertyLocalStorage implements ConfigPropertyStorage {
0017 getItem(key: string): string | null {
0018 return localStorage.getItem(key);
0019 }
0020
0021 setItem(key: string, value: string): void {
0022 localStorage.setItem(key, value);
0023 }
0024 }
0025
0026 /**
0027 * Manages an individual configuration property. Provides reactive updates to subscribers,
0028 * persistence to localStorage, and optional value validation.
0029 *
0030 * @template T The type of the configuration value.
0031 */
0032 export class ConfigProperty<T> {
0033 public subject: BehaviorSubject<T>;
0034
0035 /** Observable for subscribers to react to changes in the property value. */
0036 public changes$: Observable<T>;
0037
0038 /**
0039 * Creates an instance of ConfigProperty.
0040 *
0041 * @param {string} key The localStorage key under which the property value is stored.
0042 * @param {T} defaultValue The default value of the property if not previously stored.
0043 * @param storage
0044 * @param {() => void} saveCallback The callback to execute after setting a new value.
0045 * @param {(value: T) => boolean} [validator] Optional validator function to validate the property value.
0046 */
0047 constructor(
0048 private key: string,
0049 private defaultValue: T,
0050 private saveCallback?: () => void,
0051 private validator?: (value: T) => boolean,
0052 private storage: ConfigPropertyStorage = new ConfigPropertyLocalStorage(),
0053 ) {
0054 const value = this.loadValue();
0055 this.subject = new BehaviorSubject<T>(value);
0056 this.changes$ = this.subject.asObservable();
0057 }
0058
0059
0060 /**
0061 * Loads the property value from localStorage or returns the default value if not found or invalid.
0062 *
0063 * @returns {T} The loaded or default value of the property.
0064 */
0065 private loadValue(): T {
0066 let storedValue: string|null = null;
0067 let parsedValue: any = undefined;
0068 try {
0069 storedValue = this.storage.getItem(this.key);
0070
0071 if (storedValue !== null) {
0072 parsedValue = (typeof this.defaultValue) !== 'string' ? JSON.parse(storedValue) : storedValue;
0073 } else {
0074 parsedValue = this.defaultValue;
0075 }
0076 return this.validator && !this.validator(parsedValue) ? this.defaultValue : parsedValue;
0077 } catch (error) {
0078 console.error(`Error at ConfigProperty.loadValue, key='${this.key}'`);
0079 console.log(' storedValue', storedValue);
0080 console.log(' parsedValue', parsedValue);
0081 console.log(' Default value will be used: ', this.defaultValue);
0082 console.log(error);
0083
0084 return this.defaultValue;
0085 }
0086 }
0087
0088 /**
0089 * Sets the property value after validation. If the value is valid, it updates the property and calls the save callback.
0090 *
0091 * @param {T} value The new value to set for the property.
0092 */
0093 set value(value: T) {
0094 if (this.validator && !this.validator(value)) {
0095 console.error('Validation failed for:', value);
0096 return;
0097 }
0098 this.storage.setItem(this.key, typeof value !== 'string' ? JSON.stringify(value) : value);
0099
0100 if(this.saveCallback) {
0101 this.saveCallback();
0102 }
0103
0104 this.subject.next(value);
0105 }
0106
0107 /**
0108 * Gets the current value of the property.
0109 *
0110 * @returns {T} The current value of the property.
0111 */
0112 get value(): T {
0113 return this.subject.value;
0114 }
0115 }