Adds settings screen and refactors get/set app defaults
This commit is contained in:
parent
0d4ed8f6d9
commit
69d490d76f
|
@ -34,7 +34,6 @@ env:
|
|||
- BASE_HREF=/
|
||||
- DEPLOY_URL=/
|
||||
- HOME_ROUTE=home
|
||||
- IRB_URL=http://localhost:5001/
|
||||
- PORT0=4200
|
||||
- PRODUCTION=false
|
||||
script:
|
||||
|
@ -42,7 +41,7 @@ script:
|
|||
|
||||
deploy:
|
||||
provider: script
|
||||
script: bash ./deploy.sh sartography/cr-connect-frontend
|
||||
script: bash ./deploy.sh sartography/uva-covid19-testing-kiosk
|
||||
on:
|
||||
all_branches: true
|
||||
condition: $TRAVIS_BRANCH =~ ^(dev|testing|demo|training|staging|master|rrt\/.*)$
|
||||
|
|
|
@ -3790,6 +3790,15 @@
|
|||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -10404,7 +10413,6 @@
|
|||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
|
@ -10951,8 +10959,7 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safe-regex": {
|
||||
"version": "1.1.0",
|
||||
|
@ -11165,10 +11172,9 @@
|
|||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
|
||||
"integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
|
@ -12351,6 +12357,15 @@
|
|||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
|
@ -13499,6 +13514,17 @@
|
|||
"terser": "^4.1.2",
|
||||
"webpack-sources": "^1.4.0",
|
||||
"worker-farm": "^1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"serialize-javascript": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
|
||||
"integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"ngx-qrcode-svg": "^2.0.0",
|
||||
"rfdc": "^1.1.4",
|
||||
"rxjs": "~6.6.3",
|
||||
"serialize-javascript": "^5.0.1",
|
||||
"tslib": "^2.0.0",
|
||||
"zone.js": "~0.10.3"
|
||||
},
|
||||
|
|
|
@ -5,10 +5,12 @@ import {FlexLayoutModule} from '@angular/flex-layout';
|
|||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {MatButtonModule} from '@angular/material/button';
|
||||
import {MatCardModule} from '@angular/material/card';
|
||||
import {MatOptionModule} from '@angular/material/core';
|
||||
import {MAT_FORM_FIELD_DEFAULT_OPTIONS, MatFormFieldModule} from '@angular/material/form-field';
|
||||
import {MatIconModule} from '@angular/material/icon';
|
||||
import {MatInputModule} from '@angular/material/input';
|
||||
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
|
||||
import {MatSelectModule} from '@angular/material/select';
|
||||
import {MatToolbarModule} from '@angular/material/toolbar';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {FormlyModule} from '@ngx-formly/core';
|
||||
|
@ -70,7 +72,10 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
|
|||
MatIconModule,
|
||||
MatFormFieldModule,
|
||||
QRCodeSVGModule,
|
||||
AppRoutingModule, // <-- This line MUST be last (https://angular.io/guide/router#module-import-order-matters)
|
||||
AppRoutingModule,
|
||||
MatOptionModule,
|
||||
MatSelectModule,
|
||||
// <-- This line MUST be last (https://angular.io/guide/router#module-import-order-matters)
|
||||
],
|
||||
providers: [
|
||||
{provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: {appearance: 'outline'}},
|
||||
|
|
|
@ -1,31 +1,60 @@
|
|||
import {AppDefaults} from '../interfaces/appDefaults.interface';
|
||||
import {LabelLayout, LabelLayoutType} from '../interfaces/labelLayout';
|
||||
|
||||
// Default form field and data values
|
||||
export const defaults: AppDefaults = {
|
||||
countsCollection: 'counts', // Name of collection for Line Counts in Firebase.
|
||||
samplesCollection: 'samples', // Name of collection for Line Counts in Firebase.
|
||||
dateEncodedFormat: 'yyyyMMddHHmm', // Format for dates when encoded in IDs for database records.
|
||||
dateDisplayFormat: 'MM/dd/yyyy, hh:mm aa', // Format for dates when displayed to user.
|
||||
numCopies: 3, // Default number of copies of labels to print. Can be overridden by user setting.
|
||||
labelLayout: 'round_32mm_1up' as LabelLayoutType, // Which label layout to use for printing. Can be overridden by user setting.
|
||||
locationId: '0000', // Default location ID. Can be overridden by user setting.
|
||||
lineCountRegex: /^[\d]{4}-[\d]{12}$/, // ID format for Line Count records.
|
||||
qrCodeRegex: /^[\d]{9}-[a-zA-Z]+-[\d]{12}-[\d]{4}$/, // ID format for QR Code records.
|
||||
barCodeNumLength: 9, // Number of digits in Bar Code.
|
||||
barCodeRegex: /^[\d]{14}$|^[\d]{9}$/, // Pattern for Bar Code data. Scanned barcodes will be either 9 or 14 digits long.
|
||||
// Manually-entered ID numbers will be exactly 9 digits long.
|
||||
initialsLength: 5,
|
||||
initialsRegex: /^[a-zA-Z]{2,5}$/,
|
||||
};
|
||||
import createClone from 'rfdc';
|
||||
import serializeJs from 'serialize-javascript';
|
||||
import {AppDefaults, AppDefaultsOptions} from '../interfaces/appDefaults.interface';
|
||||
import {LabelLayout} from '../interfaces/labelLayout.interface';
|
||||
|
||||
export const labelLayouts = {
|
||||
round_32mm_1up: new LabelLayout({
|
||||
name: '32mm Round Label - 1up',
|
||||
type: 'round_32mm_1up',
|
||||
numCols: 1,
|
||||
columnGap: 0,
|
||||
}),
|
||||
round_32mm_2up: new LabelLayout({
|
||||
name: '32mm Round Label - 2up',
|
||||
type: 'round_32mm_2up',
|
||||
numCols: 2,
|
||||
columnGap: 1.3,
|
||||
}),
|
||||
};
|
||||
|
||||
// Default form field and data values
|
||||
export const defaults: AppDefaults = new AppDefaults({
|
||||
barCodeNumLength: 9, // Number of digits in Bar Code.
|
||||
barCodeRegExp: /^[\d]{14}$|^[\d]{9}$/, // Pattern for Bar Code data. Scanned barcodes will be either 9 or 14 digits long. Manually-entered ID numbers will be exactly 9 digits long.
|
||||
countsCollection: 'counts', // Name of collection for Line Counts in Firebase.
|
||||
dateDisplayFormat: 'MM/dd/yyyy, hh:mm aa', // Format for dates when displayed to user.
|
||||
dateEncodedFormat: 'yyyyMMddHHmm', // Format for dates when encoded in IDs for database records.
|
||||
initialsLength: 5,
|
||||
initialsRegExp: /^[a-zA-Z]{2,5}$/,
|
||||
labelLayout: labelLayouts.round_32mm_1up, // Which label layout to use for printing. Can be overridden by user setting.
|
||||
lineCountRegExp: /^[\d]{4}-[\d]{12}$/, // ID format for Line Count records.
|
||||
locationId: '0000', // Default location ID. Can be overridden by user setting.
|
||||
locationIdRegExp: /^[\d]{4}$/, // ID format for Line Count records.
|
||||
numCopies: 1, // Default number of copies of labels to print. Can be overridden by user setting.
|
||||
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.
|
||||
});
|
||||
|
||||
export const getSettings = (): AppDefaults => {
|
||||
const storedSettings = localStorage.getItem('settings');
|
||||
|
||||
if (storedSettings) {
|
||||
// tslint:disable-next-line:no-eval
|
||||
return new AppDefaults(eval(`(${storedSettings})`));
|
||||
} else {
|
||||
localStorage.setItem('settings', serializeJs(defaults));
|
||||
return defaults;
|
||||
}
|
||||
};
|
||||
|
||||
export const saveSettings = (newSettings: AppDefaultsOptions): AppDefaults => {
|
||||
const settings: AppDefaults = createClone()(getSettings());
|
||||
|
||||
Object.keys(newSettings).forEach(k => {
|
||||
settings[k] = newSettings[k];
|
||||
});
|
||||
|
||||
localStorage.setItem('settings', serializeJs(settings));
|
||||
return getSettings();
|
||||
};
|
||||
|
|
|
@ -1,17 +1,51 @@
|
|||
import {LabelLayoutType} from './labelLayout';
|
||||
import {LabelLayout} from './labelLayout.interface';
|
||||
|
||||
export interface AppDefaults {
|
||||
countsCollection: string;
|
||||
samplesCollection: string;
|
||||
dateEncodedFormat: string;
|
||||
dateDisplayFormat: string;
|
||||
numCopies: number;
|
||||
labelLayout: LabelLayoutType;
|
||||
locationId: string;
|
||||
lineCountRegex: RegExp;
|
||||
qrCodeRegex: RegExp;
|
||||
barCodeRegex: RegExp;
|
||||
barCodeNumLength: number;
|
||||
initialsRegex: RegExp;
|
||||
initialsLength: number;
|
||||
export interface AppDefaultsOptions {
|
||||
barCodeNumLength?: number;
|
||||
barCodeRegExp?: RegExp | string;
|
||||
countsCollection?: string;
|
||||
dateDisplayFormat?: string;
|
||||
dateEncodedFormat?: string;
|
||||
initialsLength?: number;
|
||||
initialsRegExp?: RegExp | string;
|
||||
labelLayout?: LabelLayout;
|
||||
lineCountRegExp?: RegExp | string;
|
||||
locationId?: string;
|
||||
locationIdRegExp?: RegExp | string;
|
||||
numCopies?: number;
|
||||
qrCodeRegExp?: RegExp | string;
|
||||
samplesCollection?: string;
|
||||
}
|
||||
|
||||
export class AppDefaults {
|
||||
barCodeNumLength: number;
|
||||
barCodeRegExp: RegExp;
|
||||
countsCollection: string;
|
||||
dateDisplayFormat: string;
|
||||
dateEncodedFormat: string;
|
||||
initialsLength: number;
|
||||
initialsRegExp: RegExp;
|
||||
labelLayout: LabelLayout;
|
||||
lineCountRegExp: RegExp;
|
||||
locationId: string;
|
||||
locationIdRegExp: RegExp;
|
||||
numCopies: number;
|
||||
qrCodeRegExp: RegExp;
|
||||
samplesCollection: string;
|
||||
|
||||
constructor(options: AppDefaultsOptions) {
|
||||
console.log('options', options);
|
||||
const keys = Object.keys(options);
|
||||
keys.forEach(k => {
|
||||
if (k.includes('RegExp')) {
|
||||
if (typeof options[k] === 'string') {
|
||||
this[k] = new RegExp(options[k]);
|
||||
} else {
|
||||
this[k] = options[k];
|
||||
}
|
||||
} else {
|
||||
this[k] = options[k];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export declare type LabelLayoutType = 'round_32mm_1up' | 'round_32mm_2up';
|
||||
|
||||
export interface LayoutOptions {
|
||||
type?: string;
|
||||
name?: string;
|
||||
units?: string;
|
||||
pointsPerUnit?: number;
|
||||
labelSize?: number;
|
||||
|
@ -17,6 +17,8 @@ export interface LayoutOptions {
|
|||
}
|
||||
|
||||
export class LabelLayout {
|
||||
type = 'round_32mm_1up';
|
||||
name = '32mm Round Label - 1up';
|
||||
units = 'mm';
|
||||
pointsPerUnit = 0.3528;
|
||||
labelSize = 28.6;
|
||||
|
@ -32,18 +34,10 @@ export class LabelLayout {
|
|||
numCopies = 1;
|
||||
|
||||
constructor(private options: LayoutOptions) {
|
||||
this.units = options.units || this.units;
|
||||
this.pointsPerUnit = options.pointsPerUnit || this.pointsPerUnit;
|
||||
this.marginSize = options.marginSize || this.marginSize;
|
||||
this.labelSize = options.labelSize || this.labelSize;
|
||||
this.numCols = options.numCols || this.numCols;
|
||||
this.columnGap = options.columnGap || this.columnGap;
|
||||
this.sideTextWidth = options.sideTextWidth || this.sideTextWidth;
|
||||
this.sideTextTop = options.sideTextTop || this.sideTextTop;
|
||||
this.sideTextMargin = options.sideTextMargin || this.sideTextMargin;
|
||||
this.topTextMargin = options.topTextMargin || this.topTextMargin;
|
||||
this.bottomTextMargin = options.bottomTextMargin || this.bottomTextMargin;
|
||||
this.fontSizePt = options.fontSizePt || this.fontSizePt;
|
||||
const keys = Object.keys(options);
|
||||
keys.forEach(k => {
|
||||
this[k] = options[k];
|
||||
});
|
||||
}
|
||||
|
||||
get dimensions() {
|
|
@ -43,7 +43,7 @@ export class PrintComponent implements OnInit {
|
|||
}
|
||||
|
||||
get columns() {
|
||||
return Array(defaults.labelLayout === 'round_32mm_2up' ? 2 : 1).fill('');
|
||||
return Array(defaults.labelLayout.type === 'round_32mm_2up' ? 2 : 1).fill('');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
|
|
@ -18,16 +18,6 @@
|
|||
type="text"
|
||||
[formControl]="barCodeFormControl"
|
||||
>
|
||||
<button
|
||||
mat-button
|
||||
*ngIf="barCodeValue"
|
||||
matSuffix
|
||||
mat-icon-button
|
||||
aria-label="Clear"
|
||||
(click)="barCodeFormControl.patchValue('')"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<mat-error *ngIf="barCodeFormControl.hasError('required')">This field is required.</mat-error>
|
||||
<mat-error *ngIf="barCodeFormControl.hasError('pattern')">Please enter exactly 9 or 14 digits.</mat-error>
|
||||
</mat-form-field>
|
||||
|
@ -39,31 +29,30 @@
|
|||
type="text"
|
||||
[formControl]="initialsFormControl"
|
||||
>
|
||||
<button
|
||||
mat-button
|
||||
*ngIf="initialsValue"
|
||||
matSuffix
|
||||
mat-icon-button
|
||||
aria-label="Clear"
|
||||
(click)="initialsFormControl.patchValue('')"
|
||||
>
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
<mat-error *ngIf="initialsFormControl.hasError('required')">This field is required.</mat-error>
|
||||
<mat-error *ngIf="initialsFormControl.hasError('pattern')">Please enter only letters.</mat-error>
|
||||
<mat-error *ngIf="initialsFormControl.hasError('pattern')">Please enter only 2-5 letters.</mat-error>
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button
|
||||
#nextButton="matButton"
|
||||
mat-flat-button
|
||||
class="btn-xl"
|
||||
color="accent"
|
||||
fxFlex="50%"
|
||||
[disabled]="!hasInfo"
|
||||
routerLink="/print"
|
||||
[queryParams]="queryParams"
|
||||
>Next</button>
|
||||
<button mat-flat-button class="btn-xl" fxFlex="50%" routerLink="/">Cancel</button>
|
||||
>Next <mat-icon>navigate_next</mat-icon></button>
|
||||
<button
|
||||
mat-flat-button
|
||||
class="btn-xl"
|
||||
(click)="resetForm()"
|
||||
><mat-icon>restore_page</mat-icon> Reset</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
class="btn-xl"
|
||||
routerLink="/"
|
||||
><mat-icon>cancel</mat-icon> Cancel</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import {AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {FormControl, Validators} from '@angular/forms';
|
||||
import {MatButton} from '@angular/material/button';
|
||||
import {MatInput} from '@angular/material/input';
|
||||
import {Params} from '@angular/router';
|
||||
import {defaults} from '../config/defaults';
|
||||
import {defaults, getSettings} from '../config/defaults';
|
||||
import {AppDefaults} from '../interfaces/appDefaults.interface';
|
||||
|
||||
|
||||
@Component({
|
||||
|
@ -11,18 +13,18 @@ import {defaults} from '../config/defaults';
|
|||
styleUrls: ['./sample.component.scss']
|
||||
})
|
||||
export class SampleComponent implements AfterViewInit {
|
||||
barCodeErrorMessage = '';
|
||||
initialsErrorMessage = '';
|
||||
settings: AppDefaults = getSettings();
|
||||
barCodeFormControl = new FormControl('', [
|
||||
Validators.required,
|
||||
Validators.pattern(defaults.barCodeRegex),
|
||||
Validators.pattern(this.settings.barCodeRegExp),
|
||||
]);
|
||||
initialsFormControl = new FormControl('', [
|
||||
Validators.required,
|
||||
Validators.pattern(defaults.initialsRegex),
|
||||
Validators.pattern(this.settings.initialsRegExp),
|
||||
]);
|
||||
@ViewChild('barCodeInput') barCodeInput: MatInput;
|
||||
@ViewChild('initialsInput') initialsInput: MatInput;
|
||||
@ViewChild('nextButton') nextButton: MatButton;
|
||||
|
||||
get queryParams(): Params {
|
||||
return {
|
||||
|
@ -32,9 +34,7 @@ export class SampleComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
constructor(private changeDetector: ChangeDetectorRef) {
|
||||
this.barCodeFormControl.registerOnChange(() => {
|
||||
this.checkBarCodeValue();
|
||||
});
|
||||
this.barCodeFormControl.registerOnChange(() => this.checkBarCodeValue());
|
||||
this.initialsFormControl.registerOnChange(() => this.checkInitialsValue());
|
||||
}
|
||||
|
||||
|
@ -47,11 +47,11 @@ export class SampleComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
get hasBarCode(): boolean {
|
||||
return defaults.barCodeRegex.test(this.barCodeValue);
|
||||
return this.settings.barCodeRegExp.test(this.barCodeValue);
|
||||
}
|
||||
|
||||
get hasInitials(): boolean {
|
||||
return defaults.initialsRegex.test(this.initialsValue);
|
||||
return this.settings.initialsRegExp.test(this.initialsValue);
|
||||
}
|
||||
|
||||
get hasInfo(): boolean {
|
||||
|
@ -66,19 +66,21 @@ export class SampleComponent implements AfterViewInit {
|
|||
checkBarCodeValue() {
|
||||
console.log('--- checkBarCodeValue ---');
|
||||
if (this.hasBarCode) {
|
||||
this.barCodeErrorMessage = '';
|
||||
this.initialsInput.focus();
|
||||
this.changeDetector.detectChanges();
|
||||
} else {
|
||||
this.barCodeErrorMessage = 'Wrong barcode.';
|
||||
}
|
||||
}
|
||||
|
||||
checkInitialsValue() {
|
||||
if (this.hasInitials) {
|
||||
this.initialsErrorMessage = '';
|
||||
} else {
|
||||
this.initialsErrorMessage = 'Wrong barcode.';
|
||||
console.log('--- checkInitialsValue ---');
|
||||
if (this.hasInitials && this.hasBarCode) {
|
||||
this.nextButton.focus();
|
||||
this.changeDetector.detectChanges();
|
||||
}
|
||||
}
|
||||
|
||||
resetForm() {
|
||||
this.barCodeFormControl.patchValue('');
|
||||
this.initialsFormControl.patchValue('');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,64 @@
|
|||
<p>settings works!</p>
|
||||
<div
|
||||
class="full-height bg-primary"
|
||||
fxLayout="row"
|
||||
fxLayoutAlign="center center"
|
||||
fxLayoutGap="40px"
|
||||
>
|
||||
<mat-card fxFlex="50%">
|
||||
<mat-card-header>
|
||||
<h1>Scan Barcode</h1>
|
||||
</mat-card-header>
|
||||
|
||||
<mat-card-content fxLayout="row wrap" fxLayoutAlign="center center">
|
||||
<mat-form-field class="barcode-input" fxFlex="95%">
|
||||
<mat-label>Location ID #</mat-label>
|
||||
<input
|
||||
#locationIdInput="matInput"
|
||||
matInput
|
||||
type="text"
|
||||
[formControl]="locationIdFormControl"
|
||||
>
|
||||
<mat-error *ngIf="locationIdFormControl.hasError('required')">This field is required.</mat-error>
|
||||
<mat-error *ngIf="locationIdFormControl.hasError('pattern')">Please enter exactly 4 digits.</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="initials-input" fxFlex="95%">
|
||||
<mat-label>Label layout</mat-label>
|
||||
<mat-select
|
||||
#labelLayoutSelect="matSelect"
|
||||
[formControl]="labelLayoutFormControl"
|
||||
[value]="settings.labelLayout.type"
|
||||
>
|
||||
<mat-option *ngFor="let layout of labelLayouts" [value]="layout.type">{{layout.name}}</mat-option>
|
||||
</mat-select>
|
||||
<mat-error *ngIf="labelLayoutFormControl.hasError('required')">This field is required.</mat-error>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="initials-input" fxFlex="95%">
|
||||
<mat-label>Number of copies of label</mat-label>
|
||||
<input
|
||||
#numCopiesInput="matInput"
|
||||
matInput
|
||||
type="number"
|
||||
[formControl]="numCopiesFormControl"
|
||||
[value]="settings.numCopies.toString()"
|
||||
>
|
||||
<mat-error *ngIf="numCopiesFormControl.hasError('required')">This field is required.</mat-error>
|
||||
<mat-error *ngIf="numCopiesFormControl.hasError('pattern')">Please enter only 2-5 letters.</mat-error>
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button
|
||||
mat-flat-button
|
||||
class="btn-xl"
|
||||
color="accent"
|
||||
[disabled]="!hasInfo"
|
||||
(click)="save()"
|
||||
>Save <mat-icon>save</mat-icon></button>
|
||||
<button
|
||||
mat-flat-button
|
||||
class="btn-xl"
|
||||
routerLink="/"
|
||||
><mat-icon>cancel</mat-icon> Cancel</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {FormControl, Validators} from '@angular/forms';
|
||||
import {MatInput} from '@angular/material/input';
|
||||
import {MatSelect} from '@angular/material/select';
|
||||
import {getSettings, labelLayouts, saveSettings} from '../config/defaults';
|
||||
import {AppDefaults} from '../interfaces/appDefaults.interface';
|
||||
import {LabelLayout} from '../interfaces/labelLayout.interface';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
|
@ -6,10 +13,33 @@ import { Component, OnInit } from '@angular/core';
|
|||
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),
|
||||
]);
|
||||
|
||||
constructor() { }
|
||||
labelLayouts: LabelLayout[] = Object.values(labelLayouts);
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
get hasInfo(): boolean {
|
||||
return this.numCopiesFormControl.valid && this.locationIdFormControl.valid;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
save() {
|
||||
saveSettings({
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,3 +61,4 @@ import 'zone.js/dist/zone'; // Included with Angular CLI.
|
|||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
(window as any).global = window;
|
||||
|
|
Loading…
Reference in New Issue