[HIMA-16] - Added QR code scanner module

This commit is contained in:
Peter Skrlj
2019-02-07 22:03:50 +01:00
parent fa0080a907
commit 23d284f033
11 changed files with 298 additions and 1117 deletions

View File

@@ -20,6 +20,7 @@
"@angular/platform-browser-dynamic": "~7.2.0",
"@angular/router": "~7.2.0",
"@ngxs/store": "^3.3.4",
"@zxing/ngx-scanner": "^1.3.0",
"core-js": "^2.5.4",
"ngx-infinite-scroll": "^7.0.1",
"rxjs": "~6.3.3",

View File

@@ -0,0 +1,7 @@
<div class="container">
<h1>Artikel scannen</h1>
<caption>
Scannen Sie den Artikel um Informationen zu erhalten.
</caption>
<app-barcode-scanner></app-barcode-scanner>
</div>

View File

@@ -0,0 +1,34 @@
.container {
display: flex;
align-items: center;
padding: 36px;
flex-direction: column;
background-color: rgba(255, 255, 255, 1);
border-radius: 5px;
box-shadow: 0px -2px 24px 0px rgba(220, 226, 233, 0.8);
user-select: none;
h1 {
font-family: 'Open Sans';
font-size: 26px;
font-weight: 600;
color: rgba(0, 0, 0, 1);
margin: 0;
margin-bottom: 15px;
}
caption {
width: 360px;
font-family: 'Open Sans';
font-size: 22px;
color: rgba(0, 0, 0, 1);
text-align: center;
margin-bottom: 25px;
}
}
app-barcode-scanner {
width: 550px;
height: 300px;
border: #e1ebf5 2px solid;
}

View File

@@ -0,0 +1,12 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-barcode-search',
templateUrl: 'barcode-search.component.html',
styleUrls: ['barcode-search.component.scss']
})
export class BarcodeSearchComponent implements OnInit {
constructor() {}
ngOnInit() {}
}

View File

@@ -0,0 +1,14 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ZXingScannerModule } from '@zxing/ngx-scanner';
import { BarcodeSearchComponent } from './barcode-search.component';
import { BarcodeScannerComponent } from './components/barcode-scanner/barcode-scanner.component';
@NgModule({
imports: [ZXingScannerModule, CommonModule],
exports: [BarcodeSearchComponent],
declarations: [BarcodeSearchComponent, BarcodeScannerComponent],
providers: []
})
export class BarcodeSearchModule {}

View File

@@ -0,0 +1,51 @@
<div class="w-100" [hidden]="!hasDevices">
<zxing-scanner
#scanner
[scannerEnabled]="enabled"
(scanError)="scanErrorHandler($event)"
(scanFailure)="scanFailureHandler($event)"
(camerasFound)="camerasFoundHandler($event)"
[formats]="allowedFormats"
></zxing-scanner>
</div>
<div class="scanner-controls" *ngIf="!enabled">
<div class="result">
<span
(click)="scanToggle()"
class="action"
*ngIf="hasDevices && hasPermission"
>
<i class="icon-placeholder"></i>
<span>Scan</span>
</span>
<span (click)="search()" *ngIf="code" class="action">
<i class="icon-placeholder"></i>
<span>Suchen</span>
</span>
</div>
<div class="scan-result">
<span>{{ code }}</span>
</div>
</div>
<div class="debug" *ngIf="debugMode">
<table class="table-scanner-state">
<thead>
<tr>
<th>Status</th>
<th>Property</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ stateToEmoji(hasDevices) }}</td>
<td>Devices</td>
</tr>
<tr>
<td>{{ stateToEmoji(hasPermission) }}</td>
<td>Permissions</td>
</tr>
</tbody>
</table>
</div>

View File

@@ -0,0 +1,52 @@
:host {
overflow: hidden;
align-items: center;
flex-direction: column;
display: flex;
position: relative;
}
.scanner-controls {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.action {
display: flex;
flex-direction: column;
align-items: center;
margin: 0 20px;
}
.result {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.scan-result {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-weight: 600;
margin-bottom: 50px;
font-size: 26px;
}
.icon-placeholder {
$buttonSize: 30px;
border-radius: 60px;
border: #e1ebf5 2px solid;
background-color: white;
width: $buttonSize;
height: $buttonSize;
display: block;
padding: $buttonSize;
}

View File

@@ -0,0 +1,91 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { BarcodeFormat, Result } from '@zxing/library';
import { ZXingScannerComponent } from '@zxing/ngx-scanner';
@Component({
selector: 'app-barcode-scanner',
templateUrl: 'barcode-scanner.component.html',
styleUrls: ['barcode-scanner.component.scss']
})
export class BarcodeScannerComponent implements OnInit {
allowedFormats = [
BarcodeFormat.QR_CODE,
BarcodeFormat.EAN_13,
BarcodeFormat.CODE_128,
BarcodeFormat.UPC_A
];
public enabled = false;
public debugMode = true;
public code = '';
@ViewChild('scanner')
scanner: ZXingScannerComponent;
hasDevices;
availableDevices: MediaDeviceInfo[];
currentDevice: MediaDeviceInfo;
hasPermission;
constructor() {}
ngOnInit() {
this.scanner.camerasNotFound.subscribe(() => (this.hasDevices = false));
this.scanner.scanComplete.subscribe(result => this.scanSuccess(result));
this.scanner.permissionResponse.subscribe((perm: boolean) => {
this.hasPermission = perm;
});
}
scanSuccess(result: Result) {
console.log(event);
this.code = result.getText();
this.enabled = false;
}
camerasFoundHandler(devices: MediaDeviceInfo[]) {
this.hasDevices = true;
this.availableDevices = devices;
this.currentDevice = devices[0];
for (const device of devices) {
if (/back|rear|environment/gi.test(device.label)) {
this.scanner.changeDevice(device);
this.currentDevice = device;
break;
}
}
}
scanToggle() {
this.enabled = !this.enabled;
if (this.enabled) {
this.scanner.scan(this.currentDevice.deviceId);
}
}
search() {}
scanErrorHandler($event) {
console.error($event);
}
scanFailureHandler($event) {
console.error($event);
}
stateToEmoji(state: boolean): string {
const states = {
// not checked
undefined: '❔',
// failed to check
null: '⭕',
// success
true: '✔',
// can't touch that
false: '❌'
};
return states['' + state];
}
}

View File

@@ -1,3 +1,4 @@
import { BarcodeSearchModule } from './barcode-search/barcode-search.module';
import { NgModule } from '@angular/core';
import { HeaderComponent } from 'src/app/components/header/header.component';
import { ProcessHeaderComponent } from 'src/app/components/process-header/process-header.component';
@@ -39,7 +40,8 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll';
CommonModule,
AppRoutingModule,
FormsModule,
InfiniteScrollModule
InfiniteScrollModule,
BarcodeSearchModule
],
exports: [
HeaderComponent,
@@ -59,4 +61,4 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll';
InfiniteScrollModule
]
})
export class ComponentsModule { }
export class ComponentsModule {}

View File

@@ -1,3 +1,4 @@
import { BarcodeSearchComponent } from './../../modules/barcode-search/barcode-search.component';
import { Routes } from '@angular/router';
import { DashboardComponent } from 'src/app/components/dashboard/dashboard.component';
import { ArticleSearchComponent } from 'src/app/components/article-search/article-search.component';
@@ -7,11 +8,12 @@ import { CustomerSearchComponent } from 'src/app/components/customer-search/cust
import { CustomerSearchResultComponent } from 'src/app/components/customer-search-result/customer-search-result.component';
export const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'article-search', component: ArticleSearchComponent },
{ path: 'customer-search', component: CustomerSearchComponent },
{ path: 'customer-search-result', component: CustomerSearchResultComponent },
{ path: 'search-results#start', component: SearchResultsComponent },
{ path: 'product-details/:id', component: ProductDetailsComponent }
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'article-search', component: ArticleSearchComponent },
{ path: 'article-scan', component: BarcodeSearchComponent },
{ path: 'customer-search', component: CustomerSearchComponent },
{ path: 'customer-search-result', component: CustomerSearchResultComponent },
{ path: 'search-results#start', component: SearchResultsComponent },
{ path: 'product-details/:id', component: ProductDetailsComponent }
];

1131
yarn.lock
View File

File diff suppressed because it is too large Load Diff