mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
[HIMA-16] - Added QR code scanner module
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
34
src/app/modules/barcode-search/barcode-search.component.scss
Normal file
34
src/app/modules/barcode-search/barcode-search.component.scss
Normal 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;
|
||||
}
|
||||
12
src/app/modules/barcode-search/barcode-search.component.ts
Normal file
12
src/app/modules/barcode-search/barcode-search.component.ts
Normal 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() {}
|
||||
}
|
||||
14
src/app/modules/barcode-search/barcode-search.module.ts
Normal file
14
src/app/modules/barcode-search/barcode-search.module.ts
Normal 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 {}
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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 }
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user