#665 Customize Searchbar for Desktop

This commit is contained in:
Sebastian
2020-06-22 18:58:21 +02:00
parent a2c35ec67b
commit ba7be52b85
14 changed files with 186 additions and 24 deletions

View File

@@ -28,7 +28,7 @@
<button
*ngSwitchDefault
class="isa-input-submit"
[class.scan]="!errorMessage && !(searchQuery$ | async)"
[class.scan]="!errorMessage && !(searchQuery$ | async) && isIPad"
type="submit"
(click)="triggerSearch()"
></button>

View File

@@ -7,16 +7,12 @@ import {
EventEmitter,
ChangeDetectionStrategy,
} from '@angular/core';
import { Router } from '@angular/router';
import { Store } from '@ngxs/store';
import { Process } from 'apps/sales/src/app/core/models/process.model';
import { AddProcess } from 'apps/sales/src/app/core/store/actions/process.actions';
import { AddBreadcrumb } from 'apps/sales/src/app/core/store/actions/breadcrumb.actions';
import { Breadcrumb } from 'apps/sales/src/app/core/models/breadcrumb.model';
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
import { Subject, Observable } from 'rxjs';
import { map, first, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
import { isNullOrUndefined } from 'util';
import { FormControl } from '@angular/forms';
@@ -31,11 +27,12 @@ export class ShelfSearchbarComponent implements OnInit, OnDestroy {
searchQuery$: Observable<string>;
autocompleteResults$: Observable<any[]>;
@Input() isIPad: boolean;
@Input() isIPad = false;
@Input() isFetchingData = false;
@Input() errorMessage = '';
@Input() placeholder =
'Kundenname, Abholfach, Abholschein, Kundenkartennummer';
@Output() reset = new EventEmitter<void>();
@Output() search = new EventEmitter<{
type: 'scan' | 'search';
value: string;
@@ -60,7 +57,7 @@ export class ShelfSearchbarComponent implements OnInit, OnDestroy {
resetForm() {
this.searchForm.reset();
this.resetError();
this.reset.emit();
}
setError(message: string) {
@@ -90,10 +87,6 @@ export class ShelfSearchbarComponent implements OnInit, OnDestroy {
return this.searchForm.value && this.searchForm.value.length;
}
private resetError() {
this.errorMessage = '';
}
/* search2(searchParams: string) {
const branchNumber = this.store.selectSnapshot(
BranchSelectors.getUserBranch

View File

@@ -0,0 +1,4 @@
// start:ng42.barrel
export * from './shell-search-device.model';
// end:ng42.barrel

View File

@@ -0,0 +1,7 @@
import { BehaviorSubject } from 'rxjs';
export abstract class ShelfSearchDeviceComponent {
isFetchingData$: BehaviorSubject<boolean>;
errorMessage$: BehaviorSubject<string>;
triggerSearch({ type, value }: { type: 'search' | 'scan'; value: string }) {}
}

View File

@@ -1,4 +1,5 @@
// start:ng42.barrel
export * from './shelf-search-desktop.component';
export * from './shelf-search-desktop.module';
// end:ng42.barrel

View File

@@ -0,0 +1,8 @@
<div class="container">
<app-shelf-searchbar
[isFetchingData]="isFetchingData$ | async"
[errorMessage]="errorMessage$ | async"
(search)="triggerSearch($event)"
(reset)="reset()"
></app-shelf-searchbar>
</div>

View File

@@ -0,0 +1,8 @@
.container {
display: flex;
align-items: center;
flex-direction: column;
user-select: none;
margin-bottom: 90px;
height: calc(100% - 55px);
}

View File

@@ -1,4 +1,14 @@
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, OnDestroy } from '@angular/core';
import { Subject, BehaviorSubject } from 'rxjs';
import {
ShelfSearchFacadeService,
ShelfStoreFacadeService,
ShelfNavigationService,
} from '../../../shared/services';
import { ShelfSearchDeviceComponent } from '../../../defs';
import { takeUntil, first } from 'rxjs/operators';
import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
import { ListResponseArgsOfOrderItemListItemDTO } from '@swagger/oms/lib';
@Component({
selector: 'app-shelf-search-desktop',
@@ -6,8 +16,92 @@ import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
styleUrls: ['./shelf-search-desktop.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShelfSearchDesktopComponent implements OnInit {
constructor() {}
export class ShelfSearchDesktopComponent
implements OnDestroy, ShelfSearchDeviceComponent {
destroy$ = new Subject();
isFetchingData$ = new BehaviorSubject<boolean>(false);
errorMessage$ = new BehaviorSubject<string>('');
ngOnInit() {}
constructor(
private shelfSearchService: ShelfSearchFacadeService,
private shelfStoreFacade: ShelfStoreFacadeService,
private shelfNavigationService: ShelfNavigationService
) {}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
reset() {
this.setIsFetchingData(false);
this.resetError();
}
triggerSearch({ value }: { value: string }) {
this.setIsFetchingData(true);
this.resetError();
this.shelfSearchService
.search(value)
.pipe(takeUntil(this.destroy$), first())
.subscribe(
(result) => this.handleSearchResult(result, value),
this.handleSearchResultError
);
}
private handleSearchResult(
result: ListResponseArgsOfOrderItemListItemDTO,
value: string
) {
this.setIsFetchingData(false);
if (this.hasNoResult(result)) {
this.setErrorMessage('Ergibt keine Suchergebnisse');
} else if (this.hasMultipleSearchResults(result)) {
this.shelfStoreFacade.setShelfSearch(value);
this.shelfNavigationService.navigateToResultList({
searchQuery: value,
numberOfHits: result.hits,
});
this.resetSessionStorage();
} else {
this.shelfNavigationService.navigateToDetails(this.getDetails(result));
}
}
private hasNoResult(result: ListResponseArgsOfOrderItemListItemDTO): boolean {
return !!result.result && !result.result.length;
}
private hasMultipleSearchResults(
result: ListResponseArgsOfOrderItemListItemDTO
): boolean {
return !!result.result && result.result.length > 1;
}
private getDetails(result: ListResponseArgsOfOrderItemListItemDTO) {
return result.result && result.result[0];
}
private handleSearchResultError() {
this.setErrorMessage('Ein Fehler ist aufgetreten');
this.setIsFetchingData(false);
}
private resetSessionStorage(key: string = SHELF_SCROLL_INDEX) {
sessionStorage.removeItem(key);
}
private setIsFetchingData(isFetching: boolean) {
this.isFetchingData$.next(isFetching);
}
private resetError() {
this.setErrorMessage('');
}
private setErrorMessage(message: string) {
this.errorMessage$.next(message);
}
}

View File

@@ -0,0 +1,12 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ShelfSearchDesktopComponent } from './shelf-search-desktop.component';
import { ShelfSearchBarModule } from '../../../components';
@NgModule({
imports: [CommonModule, ShelfSearchBarModule],
exports: [ShelfSearchDesktopComponent],
declarations: [ShelfSearchDesktopComponent],
providers: [],
})
export class ShelfSearchDesktopModule {}

View File

@@ -2,7 +2,9 @@
<app-shelf-searchbar
[isFetchingData]="isFetchingData$ | async"
[errorMessage]="errorMessage$ | async"
[isIPad]="true"
(search)="triggerSearch($event)"
(reset)="reset()"
></app-shelf-searchbar>
<lib-collecting-shelf-scanner

View File

@@ -8,12 +8,13 @@ import { BarcodeScannerScanditComponent } from 'shared/lib/barcode-scanner';
import { ShelfSearchFacadeService } from '../../../shared/services/shelf-search.facade.service';
import { ListResponseArgsOfOrderItemListItemDTO } from 'apps/swagger/oms/src/lib';
import { Observable, Subject, BehaviorSubject } from 'rxjs';
import { map, first, takeUntil } from 'rxjs/operators';
import { first, takeUntil } from 'rxjs/operators';
import {
ShelfStoreFacadeService,
ShelfNavigationService,
} from '../../../shared/services';
import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
import { ShelfSearchDeviceComponent } from '../../../defs';
@Component({
selector: 'app-shelf-search-ipad',
@@ -21,7 +22,8 @@ import { SHELF_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants'
styleUrls: ['./shelf-search-ipad.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShelfSearchIpadComponent implements OnDestroy {
export class ShelfSearchIpadComponent
implements OnDestroy, ShelfSearchDeviceComponent {
@ViewChild('scanner', { static: false })
scanner: BarcodeScannerScanditComponent;
destroy$ = new Subject();
@@ -39,6 +41,11 @@ export class ShelfSearchIpadComponent implements OnDestroy {
this.destroy$.complete();
}
reset() {
this.setIsFetchingData(false);
this.resetError();
}
triggerBarcodeSearch(barcode: string) {
this.triggerSearch({ type: 'scan', value: barcode });
}
@@ -46,6 +53,8 @@ export class ShelfSearchIpadComponent implements OnDestroy {
triggerSearch({ type, value }: { type: 'search' | 'scan'; value: string }) {
let result$: Observable<ListResponseArgsOfOrderItemListItemDTO>;
this.setIsFetchingData(true);
this.resetError();
if (type === 'search') {
result$ = this.shelfSearchService.search(value);
} else if (type === 'scan') {
@@ -91,7 +100,7 @@ export class ShelfSearchIpadComponent implements OnDestroy {
private hasMultipleSearchResults(
result: ListResponseArgsOfOrderItemListItemDTO
): boolean {
return !!result.result && !!result.result.length;
return !!result.result && result.result.length > 1;
}
private getDetails(result: ListResponseArgsOfOrderItemListItemDTO) {
@@ -106,6 +115,10 @@ export class ShelfSearchIpadComponent implements OnDestroy {
this.isFetchingData$.next(isFetching);
}
private resetError() {
this.setErrorMessage('');
}
private setErrorMessage(message: string) {
this.errorMessage$.next(message);
}

View File

@@ -1,13 +1,13 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ShelfSearchComponent } from './shelf-search.component';
import { ShelfSearchIpadModule } from './shelf-search-ipad';
import { CommonModule } from '@angular/common';
import { ShelfSearchDesktopComponent } from './shelf-search-desktop';
import { ShelfSearchDesktopModule } from './shelf-search-desktop';
@NgModule({
imports: [CommonModule, ShelfSearchIpadModule],
exports: [ShelfSearchComponent, ShelfSearchDesktopComponent],
declarations: [ShelfSearchComponent, ShelfSearchDesktopComponent],
imports: [CommonModule, ShelfSearchIpadModule, ShelfSearchDesktopModule],
exports: [ShelfSearchComponent],
declarations: [ShelfSearchComponent],
providers: [],
})
export class ShelfSearchModule {}

View File

@@ -5,7 +5,6 @@ import { Pipe, PipeTransform } from '@angular/core';
})
export class ShowSearchResetPipe implements PipeTransform {
transform(queryString: string, minimumNumberOfChars?: number): boolean {
console.log({ queryString });
return (
!!queryString && !!(queryString.length > (minimumNumberOfChars || 0))
);

View File

@@ -42,6 +42,7 @@
width: 27px;
background-size: cover;
top: 17px;
cursor: pointer;
&.scan {
top: 0;
@@ -59,10 +60,30 @@
top: 19px;
outline: none;
position: absolute;
cursor: pointer;
}
.isa-input-error {
color: $isa-red;
font-size: 14px;
font-weight: 700;
animation: errorShake 0.3s cubic-bezier(0.7, 0.07, 0.19, 0.97) both;
}
@keyframes errorShake {
10% {
transform: translate3d(-1px, 0, 0);
}
50% {
transform: translate3d(2px, 0, 0);
}
70% {
transform: translate3d(-3px, 0, 0);
}
90% {
transform: translate3d(3px, 0, 0);
}
}