Replaces home screen with sample screen. Goes back to sample screen when print button clicked. Forces initials to uppercase. Tweaks label formatting. Displays locationId in navbar.
This commit is contained in:
parent
ae9c484cf0
commit
f1d93684a9
|
@ -10,9 +10,10 @@ describe('COVID19 Testing Kiosk App', () => {
|
|||
http = new HttpClient('http://localhost:5001');
|
||||
});
|
||||
|
||||
it('should automatically sign-in and redirect to home screen', () => {
|
||||
it('should automatically sign-in and redirect to sample input screen', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getRoute()).toEqual('/');
|
||||
|
||||
});
|
||||
|
||||
it('should navigate to settings screen', () => {
|
||||
|
@ -23,15 +24,7 @@ describe('COVID19 Testing Kiosk App', () => {
|
|||
page.clickAndExpectRoute('#nav_home', '/');
|
||||
});
|
||||
|
||||
it('should navigate to occupancy count input screen', () => {
|
||||
page.clickAndExpectRoute('#nav_count', '/count');
|
||||
});
|
||||
|
||||
it('should navigate back to home screen', () => {
|
||||
it('should navigate back to sample input screen', () => {
|
||||
page.clickAndExpectRoute('#nav_home', '/');
|
||||
});
|
||||
|
||||
it('should navigate to sample input screen', () => {
|
||||
page.clickAndExpectRoute('#nav_sample', '/sample');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ export const routes: Routes = [
|
|||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: HomeComponent
|
||||
component: SampleComponent
|
||||
},
|
||||
{
|
||||
path: 'sample',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="mat-typography">
|
||||
<app-navbar [testingLocation]="testingLocation"></app-navbar>
|
||||
<app-navbar></app-navbar>
|
||||
<router-outlet *ngIf="!loading; else loadingMessage"></router-outlet>
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
import {Component, Inject} from '@angular/core';
|
||||
import {MatIconRegistry} from '@angular/material/icon';
|
||||
import {DomSanitizer, Title} from '@angular/platform-browser';
|
||||
import {Router} from '@angular/router';
|
||||
import {Title} from '@angular/platform-browser';
|
||||
import {AppEnvironment} from './models/appEnvironment.interface';
|
||||
import {TestingLocation} from './models/testingLocation.interface';
|
||||
import {GoogleAnalyticsService} from './services/google-analytics.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
|
||||
export class AppComponent {
|
||||
loading: boolean;
|
||||
testingLocation: TestingLocation = {
|
||||
id: '0000',
|
||||
name: 'Click here to set location',
|
||||
};
|
||||
|
||||
constructor(
|
||||
@Inject('APP_ENVIRONMENT') private environment: AppEnvironment,
|
||||
|
@ -25,6 +18,7 @@ export class AppComponent {
|
|||
this.titleService.setTitle(this.environment.title);
|
||||
}
|
||||
|
||||
|
||||
reload() {
|
||||
this.loading = true;
|
||||
setTimeout(() => this.loading = false, 300);
|
||||
|
|
|
@ -20,7 +20,7 @@ describe('BarcodeDataMatrixComponent', () => {
|
|||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BarcodeDataMatrixComponent);
|
||||
component = fixture.componentInstance;
|
||||
settings.labelLayout = labelLayouts.rectangular_lg;
|
||||
// settings.labelLayout = labelLayouts.rectangular_lg;
|
||||
component.settings = settings;
|
||||
component.format = settings.labelLayout.barcodeType;
|
||||
component.value = '987654321-202101231122-ABCDE-0123';
|
||||
|
|
|
@ -26,31 +26,31 @@ export const labelLayouts = {
|
|||
topTextMargin: 0,
|
||||
bottomTextMargin: 0,
|
||||
}),
|
||||
rectangular_lg: new LabelLayout({
|
||||
name: '2in x 1.25in Rectangular Label',
|
||||
barcodeType: 'qrcode',
|
||||
type: 'rectangular_lg',
|
||||
numCols: 1,
|
||||
columnGap: 0,
|
||||
labelWidth: 28.6,
|
||||
labelHeight: 28.6,
|
||||
sideTextMargin: 10,
|
||||
topTextMargin: 1,
|
||||
bottomTextMargin: 1,
|
||||
}),
|
||||
rectangular_sm: new LabelLayout({
|
||||
name: '96mm x 15mm Rectangular Label',
|
||||
barcodeType: 'datamatrix',
|
||||
type: 'rectangular_sm',
|
||||
numCols: 1,
|
||||
columnGap: 0,
|
||||
labelWidth: 32,
|
||||
labelHeight: 16,
|
||||
marginSize: 6,
|
||||
sideTextMargin: 2,
|
||||
topTextMargin: 3,
|
||||
bottomTextMargin: 3,
|
||||
}),
|
||||
// rectangular_lg: new LabelLayout({
|
||||
// name: '2in x 1.25in Rectangular Label',
|
||||
// barcodeType: 'qrcode',
|
||||
// type: 'rectangular_lg',
|
||||
// numCols: 1,
|
||||
// columnGap: 0,
|
||||
// labelWidth: 28.6,
|
||||
// labelHeight: 28.6,
|
||||
// sideTextMargin: 10,
|
||||
// topTextMargin: 1,
|
||||
// bottomTextMargin: 1,
|
||||
// }),
|
||||
// rectangular_sm: new LabelLayout({
|
||||
// name: '96mm x 15mm Rectangular Label',
|
||||
// barcodeType: 'datamatrix',
|
||||
// type: 'rectangular_sm',
|
||||
// numCols: 1,
|
||||
// columnGap: 0,
|
||||
// labelWidth: 32,
|
||||
// labelHeight: 16,
|
||||
// marginSize: 6,
|
||||
// sideTextMargin: 2,
|
||||
// topTextMargin: 3,
|
||||
// bottomTextMargin: 3,
|
||||
// }),
|
||||
};
|
||||
|
||||
export const defaultOptions: AppDefaultsOptions = {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div
|
||||
class="date"
|
||||
[ngStyle]="{marginTop: settings.labelLayout.dimensions.topTextMargin}"
|
||||
>{{dateCreated | date:'yyMMdd'}}{{initials}}</div>
|
||||
>{{dateCreated | date:'yyMMdd'}}{{initials.toUpperCase()}}</div>
|
||||
<div
|
||||
class="time"
|
||||
[ngStyle]="{marginLeft: settings.labelLayout.dimensions.sideTextMargin}"
|
||||
|
|
|
@ -14,18 +14,22 @@
|
|||
width: 24.6mm;
|
||||
height: 24.6mm;
|
||||
border: 2mm solid transparent;
|
||||
border-radius: 2mm;
|
||||
background-color: transparent;
|
||||
border-radius: 100%;
|
||||
background-color: white;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
.date {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.barcode {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ export class LabelLayoutComponent implements OnInit {
|
|||
get qrCodeValue(): string {
|
||||
return createQrCodeValue(
|
||||
this.barCode,
|
||||
this.initials,
|
||||
this.initials.toUpperCase(),
|
||||
this.dateCreated,
|
||||
this.settings.locationId
|
||||
);
|
||||
|
|
|
@ -28,12 +28,12 @@ export class LabelLayout {
|
|||
labelWidth = 28.6;
|
||||
marginSize = 1.7;
|
||||
numCols = 1;
|
||||
columnGap = 4;
|
||||
columnGap = 0;
|
||||
sideTextWidth = 4;
|
||||
sideTextTop = 11;
|
||||
sideTextMargin = 1.5;
|
||||
topTextMargin = 3;
|
||||
bottomTextMargin = 2.5;
|
||||
sideTextMargin = 0;
|
||||
topTextMargin = 0;
|
||||
bottomTextMargin = 0;
|
||||
fontSizePt = 6;
|
||||
numCopies = 1;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {AppDefaults} from '../models/appDefaults.interface';
|
||||
import {SettingsService} from '../services/settings.service';
|
||||
import {TestingLocation} from '../models/testingLocation.interface';
|
||||
|
||||
@Component({
|
||||
selector: 'app-navbar',
|
||||
|
@ -8,16 +8,20 @@ import {TestingLocation} from '../models/testingLocation.interface';
|
|||
styleUrls: ['./navbar.component.scss']
|
||||
})
|
||||
export class NavbarComponent implements OnInit {
|
||||
@Input() testingLocation: TestingLocation;
|
||||
settings: AppDefaults;
|
||||
locationId: string;
|
||||
|
||||
constructor(private settingsService: SettingsService) {
|
||||
this.settingsService.settings.subscribe(settings => {
|
||||
this.settings = settings;
|
||||
this.locationId = !this.hasDefaultId ? this.settings.locationId : '0000';
|
||||
});
|
||||
}
|
||||
|
||||
get hasDefaultId(): boolean {
|
||||
return (!this.settings || this.settings.locationId === '0000');
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
get locationId(): string {
|
||||
const settings = this.settingsService.getSettings();
|
||||
return settings.locationId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<app-label-layout
|
||||
*ngFor="let col of columns"
|
||||
[barCode]="barCode"
|
||||
[initials]="initials"
|
||||
[initials]="initials.toUpperCase()"
|
||||
[dateCreated]="dateCreated"
|
||||
></app-label-layout>
|
||||
</div>
|
||||
|
|
|
@ -16,6 +16,7 @@ describe('PrintLayoutComponent', () => {
|
|||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PrintLayoutComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.initials = 'abcde';
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
>
|
||||
<app-print-layout
|
||||
[barCode]="barCode"
|
||||
[initials]="initials"
|
||||
[initials]="initials.toUpperCase()"
|
||||
[dateCreated]="dateCreated"
|
||||
></app-print-layout>
|
||||
</mat-card-content>
|
||||
|
@ -26,7 +26,7 @@
|
|||
#saveAndPrintButton="matButton"
|
||||
mat-flat-button
|
||||
class="btn-lg"
|
||||
[color]="isSaved ? '' : 'accent'"
|
||||
color="accent"
|
||||
(click)="saveAndPrint()"
|
||||
autofocus
|
||||
fxFlex="33%"
|
||||
|
@ -37,8 +37,7 @@
|
|||
class="btn-lg"
|
||||
routerLink="/"
|
||||
fxFlex="33%"
|
||||
[color]="isSaved ? 'accent' : ''"
|
||||
><mat-icon>done</mat-icon> Done</button>
|
||||
><mat-icon>cancel</mat-icon> Cancel</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
@ -46,7 +45,7 @@
|
|||
<div id="media-print">
|
||||
<app-print-layout
|
||||
[barCode]="barCode"
|
||||
[initials]="initials"
|
||||
[initials]="initials.toUpperCase()"
|
||||
[dateCreated]="dateCreated"
|
||||
></app-print-layout>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {MatButton} from '@angular/material/button';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {createQrCodeValue} from '../_util/qrCode';
|
||||
import {AppDefaults} from '../models/appDefaults.interface';
|
||||
import {LabelLayout} from '../models/labelLayout.interface';
|
||||
|
@ -26,6 +26,7 @@ export class PrintComponent implements AfterViewInit {
|
|||
constructor(
|
||||
private api: ApiService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private changeDetector: ChangeDetectorRef,
|
||||
private settingsService: SettingsService,
|
||||
private cacheService: CacheService,
|
||||
|
@ -33,13 +34,14 @@ export class PrintComponent implements AfterViewInit {
|
|||
this.dateCreated = new Date();
|
||||
this.route.queryParamMap.subscribe(queryParamMap => {
|
||||
this.barCode = queryParamMap.get('barCode');
|
||||
this.initials = queryParamMap.get('initials');
|
||||
this.initials = queryParamMap.get('initials').toUpperCase();
|
||||
});
|
||||
this.settings = this.settingsService.getSettings();
|
||||
this.isSaved = false;
|
||||
|
||||
this.save(s => {
|
||||
this.isSaved = true;
|
||||
this.changeDetector.detectChanges();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -73,7 +75,7 @@ export class PrintComponent implements AfterViewInit {
|
|||
save(callback: (s: Sample) => void) {
|
||||
const id = createQrCodeValue(
|
||||
this.barCode,
|
||||
this.initials,
|
||||
this.initials.toUpperCase(),
|
||||
this.dateCreated,
|
||||
this.settings.locationId
|
||||
);
|
||||
|
@ -102,8 +104,7 @@ export class PrintComponent implements AfterViewInit {
|
|||
saveAndPrint() {
|
||||
this.save(s => {
|
||||
window.print();
|
||||
this.doneButton.focus();
|
||||
this.changeDetector.detectChanges();
|
||||
this.router.navigate(['/']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,20 +45,14 @@
|
|||
color="accent"
|
||||
[disabled]="hasErrors"
|
||||
(click)="goPrint()"
|
||||
fxFlex="33%"
|
||||
fxFlex="50%"
|
||||
>Next <mat-icon>navigate_next</mat-icon></button>
|
||||
<button
|
||||
mat-flat-button
|
||||
class="btn-lg"
|
||||
(click)="resetForm()"
|
||||
fxFlex="33%"
|
||||
fxFlex="50%"
|
||||
><mat-icon>restore</mat-icon> Reset</button>
|
||||
<button
|
||||
mat-flat-button
|
||||
class="btn-lg"
|
||||
routerLink="/"
|
||||
fxFlex="33%"
|
||||
><mat-icon>cancel</mat-icon> Cancel</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ export class SampleComponent implements AfterViewInit {
|
|||
get queryParams(): Params {
|
||||
return {
|
||||
barCode: this.barCodeValue.slice(0, 9),
|
||||
initials: this.initialsValue,
|
||||
initials: this.initialsValue.toUpperCase(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ export class SampleComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
get initialsValue(): string {
|
||||
return this.initialsFormControl.value;
|
||||
return this.initialsFormControl.value.toUpperCase();
|
||||
}
|
||||
|
||||
get hasBarCode(): boolean {
|
||||
|
@ -58,7 +58,7 @@ export class SampleComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
get hasInitials(): boolean {
|
||||
return this.settings.initialsRegExp.test(this.initialsValue);
|
||||
return this.settings.initialsRegExp.test(this.initialsValue.toUpperCase());
|
||||
}
|
||||
|
||||
get hasErrors(): boolean {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import createClone from 'rfdc';
|
||||
import {BehaviorSubject} from 'rxjs';
|
||||
import serializeJs from 'serialize-javascript';
|
||||
import {defaultOptions} from '../config/defaults';
|
||||
import {AppDefaults, AppDefaultsOptions} from '../models/appDefaults.interface';
|
||||
|
@ -11,10 +12,15 @@ export class SettingsService {
|
|||
// Default form field and data values
|
||||
defaults: AppDefaults = new AppDefaults(defaultOptions);
|
||||
|
||||
// Observable to subscribe to settings updates
|
||||
settings = new BehaviorSubject<AppDefaults>(this.defaults);
|
||||
|
||||
// Deserializes settings from local storage and returns AppDefaults instance
|
||||
getStoredSettings(): AppDefaults {
|
||||
// tslint:disable-next-line:no-eval
|
||||
return new AppDefaults(eval(`(${localStorage.getItem('settings')})`));
|
||||
const storedSettings = new AppDefaults(eval(`(${localStorage.getItem('settings')})`));
|
||||
this.settings.next(storedSettings);
|
||||
return storedSettings;
|
||||
}
|
||||
|
||||
// Returns true if settings are found in local storage
|
||||
|
@ -40,6 +46,7 @@ export class SettingsService {
|
|||
});
|
||||
|
||||
localStorage.setItem('settings', serializeJs(settings));
|
||||
this.settings.next(settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,14 @@
|
|||
</mat-card-header>
|
||||
|
||||
<mat-card-content fxLayout="row wrap" fxLayoutAlign="center center">
|
||||
<mat-form-field class="location-input" fxFlex="95%">
|
||||
<mat-form-field class="location-input" fxFlex="95%" >
|
||||
<mat-label>Location ID #</mat-label>
|
||||
<input
|
||||
#locationIdInput="matInput"
|
||||
matInput
|
||||
type="text"
|
||||
[formControl]="locationIdFormControl"
|
||||
(keyup.enter)="save()"
|
||||
>
|
||||
<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>
|
||||
|
@ -38,6 +39,7 @@
|
|||
matInput
|
||||
type="number"
|
||||
[formControl]="numCopiesFormControl"
|
||||
(keyup.enter)="save()"
|
||||
>
|
||||
<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>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {FormControl, Validators} from '@angular/forms';
|
||||
import {MatInput} from '@angular/material/input';
|
||||
import {Router} from '@angular/router';
|
||||
import {labelLayouts} from '../config/defaults';
|
||||
import {AppDefaults} from '../models/appDefaults.interface';
|
||||
|
@ -11,13 +12,15 @@ import {SettingsService} from '../services/settings.service';
|
|||
templateUrl: './settings.component.html',
|
||||
styleUrls: ['./settings.component.scss']
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
export class SettingsComponent implements AfterViewInit {
|
||||
settings: AppDefaults;
|
||||
numCopiesFormControl: FormControl;
|
||||
labelLayoutFormControl: FormControl;
|
||||
locationIdFormControl: FormControl;
|
||||
labelLayouts: LabelLayout[];
|
||||
|
||||
@ViewChild('locationIdInput') locationIdInput: MatInput;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private settingsService: SettingsService
|
||||
|
@ -43,15 +46,18 @@ export class SettingsComponent implements OnInit {
|
|||
return this.numCopiesFormControl.valid && this.locationIdFormControl.valid;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
ngAfterViewInit(): void {
|
||||
this.locationIdInput.focus();
|
||||
}
|
||||
|
||||
save() {
|
||||
this.settingsService.saveSettings({
|
||||
labelLayout: labelLayouts[this.labelLayoutFormControl.value],
|
||||
numCopies: this.numCopiesFormControl.value,
|
||||
locationId: this.locationIdFormControl.value,
|
||||
});
|
||||
this.router.navigate(['/']);
|
||||
if (this.hasInfo) {
|
||||
this.settingsService.saveSettings({
|
||||
labelLayout: labelLayouts[this.labelLayoutFormControl.value],
|
||||
numCopies: this.numCopiesFormControl.value,
|
||||
locationId: this.locationIdFormControl.value,
|
||||
});
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue