Refactors defaults into Settings Service.

This commit is contained in:
Aaron Louie 2020-09-23 17:23:12 -04:00
parent b1264b3c00
commit 6c6d8b9f3f
11 changed files with 126 additions and 98 deletions

View File

@ -1,6 +1,4 @@
import createClone from 'rfdc';
import serializeJs from 'serialize-javascript';
import {AppDefaults, AppDefaultsOptions} from '../interfaces/appDefaults.interface';
import {AppDefaultsOptions} from '../interfaces/appDefaults.interface';
import {LabelLayout} from '../interfaces/labelLayout.interface';
export const labelLayouts = {
@ -35,39 +33,3 @@ export const defaultOptions: AppDefaultsOptions = {
qrCodeRegExp: /^[\d]{9}-[a-zA-Z]+-[\d]{12}-[\d]{4}$/, // ID format for QR Code records.
samplesCollection: 'samples', // Name of collection for Line Counts in Firebase.
};
// Default form field and data values
export const defaults: AppDefaults = new AppDefaults(defaultOptions);
// Deserializes settings from local storage and returns AppDefaults instance
export const getStoredSettings = (): AppDefaults => {
// tslint:disable-next-line:no-eval
return new AppDefaults(eval(`(${localStorage.getItem('settings')})`));
};
// Returns true if settings are found in local storage
export const hasStoredSettings = (): boolean => {
return !!localStorage.getItem('settings');
};
// Returns settings from local storage, or defaults if none have been saved yet.
export const getSettings = (): AppDefaults => {
if (hasStoredSettings()) {
return getStoredSettings();
} else {
return saveSettings(defaults);
}
};
// Serializes given settings and stores them in local storage
export const saveSettings = (newSettings: AppDefaultsOptions): AppDefaults => {
const settings: AppDefaults = createClone({circles: true})(defaults);
Object.keys(newSettings).forEach(k => {
console.log(`${k}:`, newSettings[k]);
settings[k] = newSettings[k];
});
localStorage.setItem('settings', serializeJs(settings));
return settings;
};

View File

@ -1,6 +1,7 @@
import {formatDate} from '@angular/common';
import {Component, Input, OnInit} from '@angular/core';
import {getSettings} from '../config/defaults';
import {AppDefaults} from '../interfaces/appDefaults.interface';
import {SettingsService} from '../services/settings.service';
@Component({
selector: 'app-label-layout',
@ -11,9 +12,10 @@ export class LabelLayoutComponent implements OnInit {
@Input() dateCreated: Date;
@Input() barCode: string;
@Input() initials: string;
settings = getSettings();
settings: AppDefaults;
constructor() {
constructor(private settingsService: SettingsService) {
this.settings = this.settingsService.getSettings();
}
get qrCodeValue(): string {

View File

@ -1,7 +1,7 @@
<mat-toolbar color="primary">
<mat-toolbar-row>
<button mat-button routerLink="/" class="logo">BeSAFE</button>
<button mat-button routerLink="/settings">{{testingLocation.name}} ({{locationId}})</button>
<button mat-button routerLink="/settings">{{testingLocation ? testingLocation.name : 'No location found'}} ({{locationId}})</button>
<span fxFlex></span>
<button mat-icon-button routerLink="/"><mat-icon>home</mat-icon></button>
<button mat-icon-button routerLink="/settings"><mat-icon>settings</mat-icon></button>

View File

@ -1,5 +1,5 @@
import {Component, Input, OnInit} from '@angular/core';
import {getSettings} from '../config/defaults';
import {SettingsService} from '../services/settings.service';
import {TestingLocation} from '../interfaces/testingLocation.interface';
@Component({
@ -11,8 +11,8 @@ export class NavbarComponent implements OnInit {
@Input() testingLocation: TestingLocation;
locationId: string;
constructor() {
const settings = getSettings();
constructor(private settingsService: SettingsService) {
const settings = this.settingsService.getSettings();
this.locationId = settings.locationId;
}

View File

@ -1,5 +1,6 @@
import {Component, Input, OnInit} from '@angular/core';
import {getSettings} from '../config/defaults';
import {AppDefaults} from '../interfaces/appDefaults.interface';
import {SettingsService} from '../services/settings.service';
@Component({
selector: 'app-print-layout',
@ -10,10 +11,13 @@ export class PrintLayoutComponent implements OnInit {
@Input() dateCreated: Date;
@Input() barCode: string;
@Input() initials: string;
settings = getSettings();
dimensions = this.settings.labelLayout.dimensions;
settings: AppDefaults;
dimensions: {[key: string]: string};
constructor() { }
constructor(private settingsService: SettingsService) {
this.settings = this.settingsService.getSettings();
this.dimensions = this.settings.labelLayout.dimensions;
}
ngOnInit(): void {
}

View File

@ -1,10 +1,10 @@
import {AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
import {AfterViewInit, ChangeDetectorRef, Component, ViewChild} from '@angular/core';
import {FormControl, Validators} from '@angular/forms';
import {MatButton} from '@angular/material/button';
import {MatInput} from '@angular/material/input';
import {Params, Router} from '@angular/router';
import {defaults, getSettings} from '../config/defaults';
import {AppDefaults} from '../interfaces/appDefaults.interface';
import {SettingsService} from '../services/settings.service';
@Component({
@ -13,19 +13,31 @@ import {AppDefaults} from '../interfaces/appDefaults.interface';
styleUrls: ['./sample.component.scss']
})
export class SampleComponent implements AfterViewInit {
settings: AppDefaults = getSettings();
barCodeFormControl = new FormControl('', [
Validators.required,
Validators.pattern(this.settings.barCodeRegExp),
]);
initialsFormControl = new FormControl('', [
Validators.required,
Validators.pattern(this.settings.initialsRegExp),
]);
settings: AppDefaults;
barCodeFormControl: FormControl;
initialsFormControl: FormControl;
@ViewChild('barCodeInput') barCodeInput: MatInput;
@ViewChild('initialsInput') initialsInput: MatInput;
@ViewChild('nextButton') nextButton: MatButton;
constructor(
private router: Router,
private changeDetector: ChangeDetectorRef,
private settingsService: SettingsService,
) {
this.settings = this.settingsService.getSettings();
this.barCodeFormControl = new FormControl('', [
Validators.required,
Validators.pattern(this.settings.barCodeRegExp),
]);
this.initialsFormControl = new FormControl('', [
Validators.required,
Validators.pattern(this.settings.initialsRegExp),
]);
this.barCodeFormControl.registerOnChange(() => this.checkBarCodeValue());
this.initialsFormControl.registerOnChange(() => this.checkInitialsValue());
}
get queryParams(): Params {
return {
barCode: this.barCodeValue.slice(0, 9),
@ -33,14 +45,6 @@ export class SampleComponent implements AfterViewInit {
};
}
constructor(
private router: Router,
private changeDetector: ChangeDetectorRef
) {
this.barCodeFormControl.registerOnChange(() => this.checkBarCodeValue());
this.initialsFormControl.registerOnChange(() => this.checkInitialsValue());
}
get barCodeValue(): string {
return this.barCodeFormControl.value;
}
@ -67,7 +71,6 @@ export class SampleComponent implements AfterViewInit {
}
checkBarCodeValue() {
console.log('--- checkBarCodeValue ---');
if (this.hasBarCode) {
this.initialsInput.focus();
this.changeDetector.detectChanges();
@ -75,7 +78,6 @@ export class SampleComponent implements AfterViewInit {
}
checkInitialsValue() {
console.log('--- checkInitialsValue ---');
if (this.hasInitials && this.hasBarCode) {
this.nextButton.focus();
this.changeDetector.detectChanges();

View File

@ -22,7 +22,7 @@ export class GoogleAnalyticsService {
}
public authEvent(req: HttpRequest<any>) {
this.event('login', 'authentication', req.url)
this.event('login', 'authentication', req.url);
}
public errorEvent(error: ApiError) {
@ -32,7 +32,7 @@ export class GoogleAnalyticsService {
public setUser(uid) {
if (gtag) {
gtag('set', {user_id: uid}); // Set the user ID using signed-in user_id.
this.event('user-id available', 'authentication', uid)
this.event('user-id available', 'authentication', uid);
}
}

View File

@ -0,0 +1,50 @@
import {Injectable} from '@angular/core';
import createClone from 'rfdc';
import serializeJs from 'serialize-javascript';
import {defaultOptions} from '../config/defaults';
import {AppDefaults, AppDefaultsOptions} from '../interfaces/appDefaults.interface';
@Injectable({
providedIn: 'root'
})
export class SettingsService {
// Default form field and data values
defaults: AppDefaults = new AppDefaults(defaultOptions);
// Deserializes settings from local storage and returns AppDefaults instance
getStoredSettings(): AppDefaults {
// tslint:disable-next-line:no-eval
return new AppDefaults(eval(`(${localStorage.getItem('settings')})`));
}
// Returns true if settings are found in local storage
hasStoredSettings(): boolean {
return !!localStorage.getItem('settings');
}
// Returns settings from local storage, or defaults if none have been saved yet.
getSettings(): AppDefaults {
if (this.hasStoredSettings()) {
return this.getStoredSettings();
} else {
return this.saveSettings(this.defaults);
}
}
// Serializes given settings and stores them in local storage
saveSettings(newSettings: AppDefaultsOptions): AppDefaults {
const settings: AppDefaults = createClone({circles: true})(this.defaults);
Object.keys(newSettings).forEach(k => {
console.log(`${k}:`, newSettings[k]);
settings[k] = newSettings[k];
});
localStorage.setItem('settings', serializeJs(settings));
return settings;
}
}

View File

@ -1,12 +1,10 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {Component, OnInit} from '@angular/core';
import {FormControl, Validators} from '@angular/forms';
import {MatInput} from '@angular/material/input';
import {MatSelect} from '@angular/material/select';
import {Router} from '@angular/router';
import {getSettings, labelLayouts, saveSettings} from '../config/defaults';
import {labelLayouts} from '../config/defaults';
import {AppDefaults} from '../interfaces/appDefaults.interface';
import {LabelLayout} from '../interfaces/labelLayout.interface';
import {SettingsService} from '../services/settings.service';
@Component({
selector: 'app-settings',
@ -14,21 +12,31 @@ import {LabelLayout} from '../interfaces/labelLayout.interface';
styleUrls: ['./settings.component.scss']
})
export class SettingsComponent implements OnInit {
settings: AppDefaults = getSettings();
numCopiesFormControl = new FormControl(this.settings.numCopies, [
Validators.required,
]);
labelLayoutFormControl = new FormControl(this.settings.labelLayout.type, [
Validators.required,
]);
locationIdFormControl = new FormControl(this.settings.locationId, [
Validators.required,
Validators.pattern(this.settings.locationIdRegExp),
]);
settings: AppDefaults;
numCopiesFormControl: FormControl;
labelLayoutFormControl: FormControl;
locationIdFormControl: FormControl;
labelLayouts: LabelLayout[];
labelLayouts: LabelLayout[] = Object.values(labelLayouts);
constructor(
private router: Router,
private settingsService: SettingsService
) {
this.settings = this.settingsService.getSettings();
this.numCopiesFormControl = new FormControl(this.settings.numCopies, [
Validators.required,
]);
constructor(private router: Router) {
this.labelLayoutFormControl = new FormControl(this.settings.labelLayout.type, [
Validators.required,
]);
this.locationIdFormControl = new FormControl(this.settings.locationId, [
Validators.required,
Validators.pattern(this.settings.locationIdRegExp),
]);
this.labelLayouts = Object.values(labelLayouts);
}
get hasInfo(): boolean {
@ -39,7 +47,7 @@ export class SettingsComponent implements OnInit {
}
save() {
saveSettings({
this.settingsService.saveSettings({
labelLayout: labelLayouts[this.labelLayoutFormControl.value],
numCopies: this.numCopiesFormControl.value,
locationId: this.locationIdFormControl.value,

View File

@ -6,5 +6,5 @@ export class MockEnvironment implements AppEnvironment {
production = false;
api = 'apiRoot';
title = 'Mock Title';
googleAnalyticsKey = '';
googleAnalyticsKey = 'SOME_KEY';
}

View File

@ -2,11 +2,11 @@ import {AppEnvironment} from '../app/interfaces/appEnvironment.interface';
declare var ENV;
export const _has = (env, key, temp): boolean => env && ![null, undefined, temp, ''].includes(env[key]);
export const hasEnv = (env, key, temp): boolean => env && ![null, undefined, temp, ''].includes(env[key]);
export const environment: AppEnvironment = {
production: _has(ENV, 'production', '$PRODUCTION') ? (ENV.production === 'true') : false,
api: _has(ENV, 'api', '$API_URL') ? ENV.api : 'http://localhost:5000/v1.0',
title: _has(ENV, 'title', '$TITLE') ? ENV.title : 'COVID19 Testing Kiosk',
googleAnalyticsKey: _has(ENV, 'googleAnalyticsKey', '$GOOGLE_ANALYTICS_KEY') ? ENV.googleAnalyticsKey : 'UA-168203235-5',
production: hasEnv(ENV, 'production', '$PRODUCTION') ? (ENV.production === 'true') : false,
api: hasEnv(ENV, 'api', '$API_URL') ? ENV.api : 'http://localhost:5000/v1.0',
title: hasEnv(ENV, 'title', '$TITLE') ? ENV.title : 'COVID19 Testing Kiosk',
googleAnalyticsKey: hasEnv(ENV, 'googleAnalyticsKey', '$GOOGLE_ANALYTICS_KEY') ? ENV.googleAnalyticsKey : 'UA-168203235-5',
};