mirror of
https://github.com/sartography/uva-covid19-testing-frontend.git
synced 2025-03-04 00:51:13 +00:00
Adds rectangular label layouts with support for DataMatrix Rectangular Extension 2D barcodes.
This commit is contained in:
parent
5d75e93c07
commit
fa86d296f6
@ -29,6 +29,11 @@
|
|||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"src/styles.scss"
|
"src/styles.scss"
|
||||||
|
],
|
||||||
|
"allowedCommonJsDependencies": [
|
||||||
|
"bwip-js",
|
||||||
|
"qrcode",
|
||||||
|
"serialize-javascript"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -2959,6 +2959,11 @@
|
|||||||
"integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
|
"integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bwip-js": {
|
||||||
|
"version": "2.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/bwip-js/-/bwip-js-2.0.11.tgz",
|
||||||
|
"integrity": "sha512-8hAwUM+5FrGguKRaFi2QxKF9SxQM4fAfTy5TVAkeBODH6Eq3Q8MMEoBN+ymIBxiGKL+wNHB1Z1pv5f9oWGLUKQ=="
|
||||||
|
},
|
||||||
"bytes": {
|
"bytes": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
"@angular/router": "~11.0.0-next.2",
|
"@angular/router": "~11.0.0-next.2",
|
||||||
"@ngx-formly/core": "^5.8.0",
|
"@ngx-formly/core": "^5.8.0",
|
||||||
"@ngx-formly/material": "^5.8.0",
|
"@ngx-formly/material": "^5.8.0",
|
||||||
|
"bwip-js": "^2.0.11",
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
"ngx-qrcode-svg": "^2.0.0",
|
"ngx-qrcode-svg": "^2.0.0",
|
||||||
"rfdc": "^1.1.4",
|
"rfdc": "^1.1.4",
|
||||||
|
@ -31,6 +31,7 @@ import {ApiService} from './services/api.service';
|
|||||||
import {CacheService} from './services/cache.service';
|
import {CacheService} from './services/cache.service';
|
||||||
import {SettingsService} from './services/settings.service';
|
import {SettingsService} from './services/settings.service';
|
||||||
import {SettingsComponent} from './settings/settings.component';
|
import {SettingsComponent} from './settings/settings.component';
|
||||||
|
import { BarcodeDataMatrixComponent } from './barcode-data-matrix/barcode-data-matrix.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used internal to get a string instance of the `<base href="" />` value from `index.html`.
|
* This function is used internal to get a string instance of the `<base href="" />` value from `index.html`.
|
||||||
@ -60,6 +61,7 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
|
|||||||
PrintLayoutComponent,
|
PrintLayoutComponent,
|
||||||
SampleComponent,
|
SampleComponent,
|
||||||
SettingsComponent,
|
SettingsComponent,
|
||||||
|
BarcodeDataMatrixComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
<canvas id="barcodeCanvas"></canvas>
|
||||||
|
<div id="err"></div>
|
@ -0,0 +1,4 @@
|
|||||||
|
#barcodeCanvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { BarcodeDataMatrixComponent } from './barcode-data-matrix.component';
|
||||||
|
|
||||||
|
describe('BarcodeDataMatrixComponent', () => {
|
||||||
|
let component: BarcodeDataMatrixComponent;
|
||||||
|
let fixture: ComponentFixture<BarcodeDataMatrixComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ BarcodeDataMatrixComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(BarcodeDataMatrixComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
35
src/app/barcode-data-matrix/barcode-data-matrix.component.ts
Normal file
35
src/app/barcode-data-matrix/barcode-data-matrix.component.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
|
import bwipjs from 'bwip-js';
|
||||||
|
import {AppDefaults} from '../models/appDefaults.interface';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-barcode-data-matrix',
|
||||||
|
templateUrl: './barcode-data-matrix.component.html',
|
||||||
|
styleUrls: ['./barcode-data-matrix.component.scss']
|
||||||
|
})
|
||||||
|
export class BarcodeDataMatrixComponent implements OnInit {
|
||||||
|
@Input() format: string;
|
||||||
|
@Input() value: string;
|
||||||
|
@Input() settings: AppDefaults;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.renderBarcode();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderBarcode(): void {
|
||||||
|
bwipjs.toCanvas('barcodeCanvas', {
|
||||||
|
bcid: this.format,
|
||||||
|
text: this.value,
|
||||||
|
scale: 2,
|
||||||
|
width: this.settings.labelLayout.labelWidth,
|
||||||
|
height: this.settings.labelLayout.labelHeight,
|
||||||
|
includetext: false,
|
||||||
|
textalign: 'center',
|
||||||
|
version: '8x96',
|
||||||
|
padding: this.settings.labelLayout.marginSize,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -4,16 +4,37 @@ import {LabelLayout} from '../models/labelLayout.interface';
|
|||||||
export const labelLayouts = {
|
export const labelLayouts = {
|
||||||
round_32mm_1up: new LabelLayout({
|
round_32mm_1up: new LabelLayout({
|
||||||
name: '32mm Round Label - 1up',
|
name: '32mm Round Label - 1up',
|
||||||
|
barcodeType: 'qrcode',
|
||||||
type: 'round_32mm_1up',
|
type: 'round_32mm_1up',
|
||||||
numCols: 1,
|
numCols: 1,
|
||||||
columnGap: 0,
|
columnGap: 0,
|
||||||
}),
|
}),
|
||||||
round_32mm_2up: new LabelLayout({
|
round_32mm_2up: new LabelLayout({
|
||||||
name: '32mm Round Label - 2up',
|
name: '32mm Round Label - 2up',
|
||||||
|
barcodeType: 'qrcode',
|
||||||
type: 'round_32mm_2up',
|
type: 'round_32mm_2up',
|
||||||
numCols: 2,
|
numCols: 2,
|
||||||
columnGap: 3.4,
|
columnGap: 3.4,
|
||||||
}),
|
}),
|
||||||
|
rectangular_lg: new LabelLayout({
|
||||||
|
name: '2in x 1.25in Rectangular Label',
|
||||||
|
barcodeType: 'qrcode',
|
||||||
|
type: 'rectangular_lg',
|
||||||
|
numCols: 1,
|
||||||
|
columnGap: 0,
|
||||||
|
labelWidth: 38,
|
||||||
|
labelHeight: 38,
|
||||||
|
}),
|
||||||
|
rectangular_sm: new LabelLayout({
|
||||||
|
name: '96mm x 15mm Rectangular Label',
|
||||||
|
barcodeType: 'datamatrixrectangularextension',
|
||||||
|
type: 'rectangular_sm',
|
||||||
|
numCols: 1,
|
||||||
|
columnGap: 0,
|
||||||
|
labelWidth: 96,
|
||||||
|
labelHeight: 8,
|
||||||
|
marginSize: 4,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const defaultOptions: AppDefaultsOptions = {
|
export const defaultOptions: AppDefaultsOptions = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div class="label-layout">
|
<div class="label-layout" [ngStyle]="pageStyle">
|
||||||
<div class="date">{{dateCreated | date:'yyMMdd'}}{{initials}}</div>
|
<div class="date">{{dateCreated | date:'yyMMdd'}}{{initials}}</div>
|
||||||
<div class="time">
|
<div class="time">
|
||||||
T<br />
|
T<br />
|
||||||
@ -6,9 +6,18 @@
|
|||||||
{{dateCreated | date:'mm'}}
|
{{dateCreated | date:'mm'}}
|
||||||
</div>
|
</div>
|
||||||
<qrcode-svg
|
<qrcode-svg
|
||||||
|
*ngIf="settings.labelLayout.barcodeType === 'qrcode'"
|
||||||
[value]="qrCodeValue"
|
[value]="qrCodeValue"
|
||||||
errorCorrectionLevel="H"
|
errorCorrectionLevel="H"
|
||||||
|
[ngStyle]="labelStyle"
|
||||||
></qrcode-svg>
|
></qrcode-svg>
|
||||||
|
<app-barcode-data-matrix
|
||||||
|
*ngIf="settings.labelLayout.barcodeType !== 'qrcode'"
|
||||||
|
[value]="qrCodeValue"
|
||||||
|
[format]="settings.labelLayout.barcodeType"
|
||||||
|
[ngStyle]="labelStyle"
|
||||||
|
[settings]="settings"
|
||||||
|
></app-barcode-data-matrix>
|
||||||
<div class="location">
|
<div class="location">
|
||||||
L<br />
|
L<br />
|
||||||
{{settings.locationId.slice(0, 2)}}<br />
|
{{settings.locationId.slice(0, 2)}}<br />
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 24.6mm;
|
width: 24.6mm;
|
||||||
height: 24.6mm;
|
height: 24.6mm;
|
||||||
border: 2mm solid white;
|
border: 2mm solid transparent;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background-color: white;
|
background-color: transparent;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qrcode-svg {
|
qrcode-svg, app-barcode-data-matrix {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {Component, Input, OnInit} from '@angular/core';
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
import {createQrCodeValue} from '../_util/qrCode';
|
import {createQrCodeValue} from '../_util/qrCode';
|
||||||
import {AppDefaults} from '../models/appDefaults.interface';
|
import {AppDefaults} from '../models/appDefaults.interface';
|
||||||
|
import {CssStyle} from '../models/cssStyle.interface';
|
||||||
import {SettingsService} from '../services/settings.service';
|
import {SettingsService} from '../services/settings.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -13,9 +14,27 @@ export class LabelLayoutComponent implements OnInit {
|
|||||||
@Input() barCode: string;
|
@Input() barCode: string;
|
||||||
@Input() initials: string;
|
@Input() initials: string;
|
||||||
settings: AppDefaults;
|
settings: AppDefaults;
|
||||||
|
pageStyle: CssStyle;
|
||||||
|
labelStyle: CssStyle;
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService) {
|
constructor(private settingsService: SettingsService) {
|
||||||
this.settings = this.settingsService.getSettings();
|
this.settings = this.settingsService.getSettings();
|
||||||
|
const d = this.settings.labelLayout.dimensions;
|
||||||
|
|
||||||
|
this.pageStyle = {
|
||||||
|
width: d.pageWidth,
|
||||||
|
height: d.pageHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
this.labelStyle = {
|
||||||
|
width: d.labelWidth,
|
||||||
|
height: d.labelHeight,
|
||||||
|
marginTop: `-${this.settings.labelLayout.labelHeight / 2}mm`,
|
||||||
|
marginLeft: `-${this.settings.labelLayout.labelWidth / 2}mm`,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get qrCodeValue(): string {
|
get qrCodeValue(): string {
|
||||||
|
1
src/app/models/cssStyle.interface.ts
Normal file
1
src/app/models/cssStyle.interface.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export interface CssStyle { [klass: string]: any; }
|
@ -1,9 +1,11 @@
|
|||||||
export interface LayoutOptions {
|
export interface LayoutOptions {
|
||||||
|
barcodeType?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
units?: string;
|
units?: string;
|
||||||
pointsPerUnit?: number;
|
pointsPerUnit?: number;
|
||||||
labelSize?: number;
|
labelWidth?: number;
|
||||||
|
labelHeight?: number;
|
||||||
marginSize?: number;
|
marginSize?: number;
|
||||||
numCols?: number;
|
numCols?: number;
|
||||||
columnGap?: number;
|
columnGap?: number;
|
||||||
@ -17,11 +19,13 @@ export interface LayoutOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class LabelLayout {
|
export class LabelLayout {
|
||||||
|
barcodeType = 'qrcode';
|
||||||
type = 'round_32mm_1up';
|
type = 'round_32mm_1up';
|
||||||
name = '32mm Round Label - 1up';
|
name = '32mm Round Label - 1up';
|
||||||
units = 'mm';
|
units = 'mm';
|
||||||
pointsPerUnit = 0.3528;
|
pointsPerUnit = 0.3528;
|
||||||
labelSize = 28.6;
|
labelHeight = 28.6;
|
||||||
|
labelWidth = 28.6;
|
||||||
marginSize = 1.7;
|
marginSize = 1.7;
|
||||||
numCols = 1;
|
numCols = 1;
|
||||||
columnGap = 4;
|
columnGap = 4;
|
||||||
@ -45,8 +49,10 @@ export class LabelLayout {
|
|||||||
bottomTextMargin: this._toUnits(this.bottomTextMargin),
|
bottomTextMargin: this._toUnits(this.bottomTextMargin),
|
||||||
columnGap: this._toUnits(this.columnGap),
|
columnGap: this._toUnits(this.columnGap),
|
||||||
fontSize: this._toUnits(this.fontSize),
|
fontSize: this._toUnits(this.fontSize),
|
||||||
labelSize: this._toUnits(this.labelSize),
|
labelWidth: this._toUnits(this.labelWidth),
|
||||||
labelSizeWithMargins: this._toUnits(this.labelSizeWithMargins),
|
labelWidthWithMargins: this._toUnits(this.labelWidthWithMargins),
|
||||||
|
labelHeight: this._toUnits(this.labelHeight),
|
||||||
|
labelHeightWithMargins: this._toUnits(this.labelHeightWithMargins),
|
||||||
marginWidth: this._toUnits(this.marginSize),
|
marginWidth: this._toUnits(this.marginSize),
|
||||||
pageHeight: this._toUnits(this.pageHeight),
|
pageHeight: this._toUnits(this.pageHeight),
|
||||||
pageWidth: this._toUnits(this.pageWidth),
|
pageWidth: this._toUnits(this.pageWidth),
|
||||||
@ -57,16 +63,20 @@ export class LabelLayout {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get labelSizeWithMargins(): number {
|
get labelWidthWithMargins(): number {
|
||||||
return (this.labelSize + (this.marginSize * 2));
|
return (this.labelWidth + (this.marginSize * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
get labelHeightWithMargins(): number {
|
||||||
|
return (this.labelHeight + (this.marginSize * 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
get pageWidth(): number {
|
get pageWidth(): number {
|
||||||
return (this.labelSizeWithMargins * this.numCols);
|
return (this.labelWidthWithMargins * this.numCols);
|
||||||
}
|
}
|
||||||
|
|
||||||
get pageHeight(): number {
|
get pageHeight(): number {
|
||||||
return (this.labelSizeWithMargins * this.numCopies);
|
return (this.labelHeightWithMargins * this.numCopies);
|
||||||
}
|
}
|
||||||
|
|
||||||
get fontSize(): number {
|
get fontSize(): number {
|
||||||
|
BIN
src/assets/bwip-fonts/Inconsolata.otf
Normal file
BIN
src/assets/bwip-fonts/Inconsolata.otf
Normal file
Binary file not shown.
BIN
src/assets/bwip-fonts/OCRA7.ttf
Normal file
BIN
src/assets/bwip-fonts/OCRA7.ttf
Normal file
Binary file not shown.
BIN
src/assets/bwip-fonts/OCRB7.ttf
Normal file
BIN
src/assets/bwip-fonts/OCRB7.ttf
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user