mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
Merge remote-tracking branch 'origin/development' into feature/HIMA-16-scanning-componenet
This commit is contained in:
@@ -18,6 +18,9 @@ export const procuctsMock: Product[] = <Product[]> [
|
||||
slogan: 'Silberfischchen gehen mit frechen Goldfischchen eine Runde im nahegelegenen See schwimmen',
|
||||
icon: 'ResultBook1.png',
|
||||
recommandation: false,
|
||||
err: null,
|
||||
location: null,
|
||||
ean: null
|
||||
},
|
||||
<Product> {
|
||||
id: 2,
|
||||
@@ -36,6 +39,9 @@ export const procuctsMock: Product[] = <Product[]> [
|
||||
slogan: 'Archipel',
|
||||
icon: 'ResultBook2.png',
|
||||
recommandation: false,
|
||||
err: null,
|
||||
location: null,
|
||||
ean: null
|
||||
},
|
||||
<Product> {
|
||||
id: 3,
|
||||
@@ -54,13 +60,16 @@ export const procuctsMock: Product[] = <Product[]> [
|
||||
slogan: 'Wie Ihr wollt',
|
||||
icon: 'ResultBook3.png',
|
||||
recommandation: false,
|
||||
err: null,
|
||||
location: 'Abenteuerroman A-Z',
|
||||
ean: '3'
|
||||
},
|
||||
<Product> {
|
||||
id: 4,
|
||||
author: 'Ann Christin Artel',
|
||||
title: 'Eine Reise um die Welt',
|
||||
type: 'Kalender',
|
||||
typeIcon: 'TypeCalendarWhite.svg',
|
||||
typeIcon: 'KA',
|
||||
category: 'Kalender A-Z',
|
||||
serial: 'EAN 9783423267886',
|
||||
price: 9.99,
|
||||
@@ -72,6 +81,9 @@ export const procuctsMock: Product[] = <Product[]> [
|
||||
slogan: 'Eine Reise um die Welt',
|
||||
icon: 'ResultBook4.png',
|
||||
recommandation: true,
|
||||
err: null,
|
||||
location: 'Abenteuerroman A-Z',
|
||||
ean: '3'
|
||||
},
|
||||
<Product> {
|
||||
id: 5,
|
||||
@@ -90,6 +102,9 @@ export const procuctsMock: Product[] = <Product[]> [
|
||||
slogan: 'Rechnung offen',
|
||||
icon: 'ResultBook5.png',
|
||||
recommandation: false,
|
||||
err: null,
|
||||
location: null,
|
||||
ean: null
|
||||
},
|
||||
<Product> {
|
||||
id: 6,
|
||||
@@ -108,5 +123,8 @@ export const procuctsMock: Product[] = <Product[]> [
|
||||
slogan: 'Wie Ihr wollt',
|
||||
icon: 'ResultBook6.png',
|
||||
recommandation: false,
|
||||
err: null,
|
||||
location: null,
|
||||
ean: null
|
||||
}
|
||||
];
|
||||
|
||||
@@ -4,6 +4,9 @@ import { Observable } from 'rxjs';
|
||||
import { Process } from 'src/app/core/models/process.model';
|
||||
import { Store, Select } from '@ngxs/store';
|
||||
import { ProcessState } from 'src/app/core/store/state/process.state';
|
||||
import { AddProcess } from 'src/app/core/store/actions/process.actions';
|
||||
import { getRandomPic } from 'src/app/core/utils/process.util';
|
||||
import { Breadcrumb } from 'src/app/core/models/breadcrumb.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-menu',
|
||||
@@ -20,10 +23,46 @@ export class MenuComponent implements OnInit {
|
||||
activeMenu = '';
|
||||
|
||||
routeToMenu(menuPath: string, menuTag: string): void {
|
||||
if (this.processes.length < 1) {
|
||||
this.createProcess(menuPath);
|
||||
}
|
||||
this.activeMenu = menuTag;
|
||||
this.router.navigate([menuPath]);
|
||||
}
|
||||
|
||||
createProcess(menuPath: string) {
|
||||
const newProcess = <Process>{
|
||||
id: 1,
|
||||
name: '# 1',
|
||||
selected: true,
|
||||
icon: getRandomPic(),
|
||||
breadcrumbs: <Breadcrumb[]>[
|
||||
{
|
||||
name: this.nameFromPath(menuPath),
|
||||
path: menuPath
|
||||
}
|
||||
],
|
||||
currentRoute: this.routeFromPath(menuPath)
|
||||
};
|
||||
|
||||
this.store.dispatch(new AddProcess(newProcess));
|
||||
}
|
||||
|
||||
routeFromPath(path: string) {
|
||||
return path.substring(1, path.length - 1);
|
||||
}
|
||||
|
||||
nameFromPath(path: string) {
|
||||
switch (path) {
|
||||
case '/article-search':
|
||||
return 'Artikelsuche';
|
||||
case '/customer-search':
|
||||
return 'Kundensuche';
|
||||
default:
|
||||
return 'Artikelsuche';
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.processes$.subscribe(
|
||||
(data: Process[]) => this.processes = data
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, OnInit, Input, ViewChild } from '@angular/core';
|
||||
import { Process } from 'src/app/core/models/process.model';
|
||||
import { Router } from '@angular/router';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { Store, Select } from '@ngxs/store';
|
||||
import {
|
||||
DeleteProcess,
|
||||
SelectProcess,
|
||||
@@ -12,6 +12,8 @@ import { Cart } from '../../core/models/cart.model';
|
||||
import { AddBreadcrumb } from '../../core/store/actions/process.actions';
|
||||
import { Breadcrumb } from '../../core/models/breadcrumb.model';
|
||||
import { ProcessDeleteDialogComponent } from 'src/app/modules/process/process-delete-dialog/process-delete-dialog.component';
|
||||
import { ProcessState } from 'src/app/core/store/state/process.state';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-process-tab',
|
||||
@@ -21,6 +23,7 @@ import { ProcessDeleteDialogComponent } from 'src/app/modules/process/process-de
|
||||
export class ProcessTabComponent implements OnInit {
|
||||
@Input() process: Process;
|
||||
@Input() processes: Array<Process>;
|
||||
@Select(ProcessState.getProcessCount) processCount: Observable<number>;
|
||||
@ViewChild('deleteporcessdialog') processDeleteDialogComponent: ProcessDeleteDialogComponent;
|
||||
cartCount = 0;
|
||||
|
||||
@@ -28,6 +31,13 @@ export class ProcessTabComponent implements OnInit {
|
||||
|
||||
deleteProcess(process: Process) {
|
||||
this.store.dispatch(new DeleteProcess(process));
|
||||
this.processCount.subscribe(
|
||||
(count: number) => {
|
||||
if (count < 1) {
|
||||
this.router.navigate(['/dashboard']);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
openDeleteConfirmationDialog() {
|
||||
|
||||
@@ -33,12 +33,12 @@ export class ProductCardComponent implements OnInit {
|
||||
if (this._product.price.toString().indexOf('.') === -1) {
|
||||
return this._product.price + ',00';
|
||||
}
|
||||
|
||||
|
||||
const afterDecimal = this._product.price.toString().split('.')[1];
|
||||
if (afterDecimal.length !== 2) {
|
||||
return this._product.price.toString().replace('.', ',') + '0';
|
||||
}
|
||||
|
||||
|
||||
return this._product.price.toString().replace('.', ',');
|
||||
}
|
||||
|
||||
@@ -54,7 +54,13 @@ export class ProductCardComponent implements OnInit {
|
||||
private store: Store
|
||||
) {
|
||||
this.imageUrl$ = this.eanChangedSub.pipe(
|
||||
flatMap(ean => this.catImageService.getImageUrl(ean)),
|
||||
flatMap(ean => {
|
||||
// TODO: remove mock data
|
||||
if (ean === '3') {
|
||||
return of('../../../assets/images/ResultBook4.png');
|
||||
}
|
||||
return this.catImageService.getImageUrl(ean);
|
||||
}),
|
||||
catchError(() => of(''))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,25 +25,25 @@
|
||||
<span>{{product.format}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stock-info align-right">
|
||||
<div class="stock-info align-right" *ngIf="product.quantity > 0">
|
||||
<div class="ship-icon">
|
||||
<img class="icon" src="../../../assets/images/Truck_Icon_2.svg">
|
||||
</div>
|
||||
<div class="send-icon">
|
||||
<img class="icon" src="../../../assets/images/Package_Icon_2.svg">
|
||||
</div>
|
||||
<div class="stock-label">
|
||||
<div class="stock-label" *ngIf="product.quantity > 0">
|
||||
<span>Lieferbar</span>
|
||||
</div>
|
||||
<div class="home-icon" *ngIf="product.quantity > 0">
|
||||
<img class="icon" src="../../../assets/images/Icon_House.svg">
|
||||
</div>
|
||||
<div class="stock-quantity" *ngIf="product.quantity > 0">
|
||||
<span>{{product.quantity}}</span>
|
||||
<span>{{product.quantity}}x</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="category align-right">
|
||||
<div class="category align-right" *ngIf="product.quantity > 0">
|
||||
<span>{{product.category}}</span>
|
||||
</div>
|
||||
<div class="languages standart-text">
|
||||
@@ -57,10 +57,10 @@
|
||||
</div>
|
||||
<div class="publication-format-pages standart-text">
|
||||
<div class="publication">
|
||||
<span>{{formatDate(product.publicationDate)}}</span>
|
||||
<span>{{product.publicationDate}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>|</span>
|
||||
<span class="divider">I</span>
|
||||
</div>
|
||||
<div class="format">
|
||||
<span>{{product.format}}</span>
|
||||
@@ -82,8 +82,13 @@
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div class="product-details">
|
||||
<div class="details">
|
||||
<span>{{getShortDescription(product.fullDescription)}}</span>
|
||||
<div class="details" id="details-container" *ngIf="!moreBtn">
|
||||
<span id="details-text">{{descriptionText(product.fullDescription)}}</span>
|
||||
<span class="more-btn" (click)="toggleMore()">Mehr<img src="../../../assets/images/Arrow_Next-with-body.svg" alt="more"></span>
|
||||
</div>
|
||||
<div class="details-full" id="details-container" *ngIf="moreBtn">
|
||||
<span id="details-text">{{product.fullDescription}}</span>
|
||||
<span class="more-btn opened" (click)="toggleMore()">Weniger<img src="../../../assets/images/Arrow_back.svg" alt="less"></span>
|
||||
</div>
|
||||
<div class="actions align-right">
|
||||
<button class="btn align-right reserve">Reservieren</button>
|
||||
|
||||
@@ -29,14 +29,25 @@
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
|
||||
.details {
|
||||
height: 68px;
|
||||
-webkit-transition: all .3s ease-out;
|
||||
transition: all .3s ease-out;
|
||||
}
|
||||
|
||||
.details-full {
|
||||
padding-top: 10px;
|
||||
-webkit-transition: all .3s ease-out;
|
||||
transition: all .3s ease-out;
|
||||
}
|
||||
|
||||
.details span {
|
||||
font-size: 16px;
|
||||
line-height: 21px;
|
||||
}
|
||||
|
||||
.product-image img {
|
||||
width: 169px;
|
||||
height: 275px;
|
||||
width: 187px;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
@@ -44,9 +55,18 @@
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
|
||||
.title span {
|
||||
font-size: 26px;
|
||||
font-weight: bold;
|
||||
|
||||
|
||||
.title {
|
||||
width: 90%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
span {
|
||||
font-size: 26px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.standart-text {
|
||||
@@ -54,10 +74,20 @@
|
||||
}
|
||||
|
||||
.publication-format-pages {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto auto auto;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
width: 70%;
|
||||
|
||||
.publication {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.divider {
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.type-stock-info {
|
||||
@@ -67,9 +97,13 @@
|
||||
}
|
||||
|
||||
.stock-info {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto auto auto;
|
||||
grid-gap: 2px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.title-price {
|
||||
@@ -94,9 +128,16 @@
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.home-icon {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.stock-label span {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
padding-left: 8px;
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
}
|
||||
|
||||
.stock-quantity span {
|
||||
@@ -105,7 +146,7 @@
|
||||
}
|
||||
|
||||
.category {
|
||||
margin-top: 15px;
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
color: #a7b9cb;
|
||||
}
|
||||
@@ -114,13 +155,21 @@
|
||||
margin-top: 17px;
|
||||
}
|
||||
|
||||
.price span{
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
.price {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-start;
|
||||
padding-top: 7px;
|
||||
|
||||
span {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.publisher {
|
||||
margin-top: 20px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
@@ -136,7 +185,7 @@
|
||||
|
||||
.actions {
|
||||
display: inline;
|
||||
padding-top: 25px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
@@ -154,6 +203,8 @@
|
||||
border: none;
|
||||
border-radius: 25px;
|
||||
color: #ffffff;
|
||||
width: 174px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +219,7 @@
|
||||
display: grid;
|
||||
grid-template-columns: max-content max-content auto;
|
||||
grid-gap: 20px;
|
||||
padding-top: 25px;
|
||||
padding-top: 35px;
|
||||
}
|
||||
|
||||
.other-format-label {
|
||||
@@ -185,4 +236,121 @@
|
||||
font-weight: bold;
|
||||
color: #5a728a;
|
||||
line-height: 21px;
|
||||
}
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #5a728a;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
bottom: 22px;
|
||||
right: 10px;
|
||||
|
||||
img {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.opened {
|
||||
bottom: 0px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.visible {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Portrait */
|
||||
@media only screen
|
||||
and (min-device-width: 768px)
|
||||
and (max-device-width: 1024px)
|
||||
and (orientation: portrait)
|
||||
and (-webkit-min-device-pixel-ratio: 2) {
|
||||
.product-image img {
|
||||
width: 190px;
|
||||
}
|
||||
|
||||
.price {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.details {
|
||||
height: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Landscape */
|
||||
@media only screen
|
||||
and (min-device-width: 768px)
|
||||
and (max-device-width: 1024px)
|
||||
and (orientation: landscape)
|
||||
and (-webkit-min-device-pixel-ratio: 2) {
|
||||
.product-image img {
|
||||
width: 190px;
|
||||
}
|
||||
|
||||
.price {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.details {
|
||||
min-height: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Portrait */
|
||||
/* Declare the same value for min- and max-width to avoid colliding with desktops */
|
||||
/* Source: https://medium.com/connect-the-dots/css-media-queries-for-ipad-pro-8cad10e17106*/
|
||||
@media only screen
|
||||
and (min-device-width: 1024px)
|
||||
and (max-device-width: 1024px)
|
||||
and (orientation: portrait)
|
||||
and (-webkit-min-device-pixel-ratio: 2) {
|
||||
.product-image img {
|
||||
width: 188px;
|
||||
}
|
||||
|
||||
.price {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
bottom: 21px;
|
||||
}
|
||||
|
||||
.details {
|
||||
min-height: 68px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Landscape */
|
||||
/* Declare the same value for min- and max-width to avoid colliding with desktops */
|
||||
/* Source: https://medium.com/connect-the-dots/css-media-queries-for-ipad-pro-8cad10e17106*/
|
||||
@media only screen
|
||||
and (min-device-width: 1366px)
|
||||
and (max-device-width: 1366px)
|
||||
and (orientation: landscape)
|
||||
and (-webkit-min-device-pixel-ratio: 2) {
|
||||
.product-image img {
|
||||
width: 166px;
|
||||
}
|
||||
|
||||
.price {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
bottom: 21px;
|
||||
}
|
||||
|
||||
.details {
|
||||
min-height: 68px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,9 @@ import { CheckoutComponent } from '../checkout/checkout.component';
|
||||
import { ProductService } from 'src/app/core/services/product.service';
|
||||
import { ItemDTO, CatImageService } from 'cat-service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { getFormatedPublicationDate } from 'src/app/core/utils/product.util';
|
||||
import { ProcessState, ProcessStateModel } from 'src/app/core/store/state/process.state';
|
||||
import { Select } from '@ngxs/store';
|
||||
import { stateNameErrorMessage } from '@ngxs/store/src/decorators/state';
|
||||
import { Process } from 'src/app/core/models/process.model';
|
||||
import { formatDate } from '@angular/common';
|
||||
import { ProcessState } from 'src/app/core/store/state/process.state';
|
||||
import { Select, Store } from '@ngxs/store';
|
||||
import { UpdateBreadcrump } from 'src/app/core/store/actions/process.actions';
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-details',
|
||||
@@ -23,6 +20,8 @@ export class ProductDetailsComponent implements OnInit {
|
||||
item: ItemDTO;
|
||||
selectedItem: ItemDTO;
|
||||
@Select(ProcessState.getSelectedProduct) selectedItem$: Observable<ItemDTO>;
|
||||
moreBtn = false;
|
||||
shortenText = null;
|
||||
|
||||
readonly FULL_DESCRIPTION_LABEL = 'Klappentext';
|
||||
readonly AUTOR = 'Autor';
|
||||
@@ -48,7 +47,8 @@ export class ProductDetailsComponent implements OnInit {
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private productService: ProductService,
|
||||
private catImageService: CatImageService
|
||||
private catImageService: CatImageService,
|
||||
private store: Store
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -58,16 +58,20 @@ export class ProductDetailsComponent implements OnInit {
|
||||
this.productService.getItemById(this.id).subscribe(
|
||||
(item: ItemDTO) => {
|
||||
this.item = item;
|
||||
return this.product = this.productDetailMapper(item);
|
||||
this.product = this.productDetailMapper(item);
|
||||
this.store.dispatch(new UpdateBreadcrump({
|
||||
name: this.product.title.substring(0, 12) + (this.product.title.length > 12 ? '...' : ''),
|
||||
path: '/product-details/' + item.id
|
||||
}));
|
||||
return this.product;
|
||||
}
|
||||
);
|
||||
this.selectedItem$.subscribe(
|
||||
(data: ItemDTO) => this.selectedItem = data
|
||||
(data: ItemDTO) => this.selectedItem = data
|
||||
);
|
||||
}
|
||||
|
||||
productDetailMapper(item: ItemDTO) {
|
||||
console.log(item);
|
||||
let fullDescription: string = null;
|
||||
let ean: string = null;
|
||||
let eanTag: string = null;
|
||||
@@ -89,7 +93,8 @@ export class ProductDetailsComponent implements OnInit {
|
||||
eanTag = ean;
|
||||
productIcon$ = this.catImageService.getImageUrl(ean, { width: 469, height: 575 });
|
||||
locale = item.pr.locale;
|
||||
publicationDate = getFormatedPublicationDate(item.pr.publicationDate);
|
||||
// publicationDate = getFormatedPublicationDate(item.pr.publicationDate);
|
||||
publicationDate = this.formatDate(item.pr.publicationDate);
|
||||
format = this.selectedItem ? this.selectedItem.pr.formatDetail : null;
|
||||
formatIcon = this.selectedItem ? this.selectedItem.pr.format : null;
|
||||
category = item.pr.productGroup;
|
||||
@@ -147,8 +152,36 @@ export class ProductDetailsComponent implements OnInit {
|
||||
// Logic if needed
|
||||
}
|
||||
|
||||
formatDate(date: string): string {
|
||||
formatDate(date: Date): string {
|
||||
const dateToFormat = new Date(date);
|
||||
return `${dateToFormat.getMonth()}/${dateToFormat.getFullYear()}`;
|
||||
}
|
||||
|
||||
descriptionText(text: string) {
|
||||
const container = document.getElementById('details-container');
|
||||
const el = document.getElementById('details-text');
|
||||
el.innerHTML = text;
|
||||
const wordArray = el.innerHTML.split(' ');
|
||||
|
||||
|
||||
if (el.offsetHeight > container.offsetHeight && !this.shortenText) {
|
||||
while (el.offsetHeight > container.offsetHeight) {
|
||||
wordArray.pop();
|
||||
el.innerHTML = wordArray.join(' ') + '...';
|
||||
}
|
||||
|
||||
// Make room for the more button
|
||||
wordArray.pop();
|
||||
wordArray.pop();
|
||||
this.shortenText = wordArray.join(' ') + '...';
|
||||
el.innerHTML = wordArray.join(' ') + '...';
|
||||
|
||||
} else {
|
||||
el.innerHTML = this.shortenText;
|
||||
}
|
||||
}
|
||||
|
||||
toggleMore() {
|
||||
this.moreBtn = !this.moreBtn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
import { ProductMapping } from 'src/app/core/mappings/product.mapping';
|
||||
import { staggerAnimation } from './stagger.animation';
|
||||
import { DataSource, CollectionViewer } from '@angular/cdk/collections';
|
||||
import { procuctsMock } from 'mocks/products.mock';
|
||||
|
||||
@Component({
|
||||
selector: 'app-search-results',
|
||||
@@ -152,7 +153,7 @@ export class SearchDataSource extends DataSource<Product | undefined> {
|
||||
this.dssub.add(
|
||||
this.dataStreamDTO
|
||||
.pipe(debounceTime(1000))
|
||||
.subscribe(i => this.store.dispatch(new SetProducts([...i])))
|
||||
.subscribe(i => this.store.dispatch(new SetProducts([...i], this.search)))
|
||||
);
|
||||
this.fetchPage(0);
|
||||
|
||||
@@ -168,7 +169,7 @@ export class SearchDataSource extends DataSource<Product | undefined> {
|
||||
}
|
||||
|
||||
private fetchPage(page: number) {
|
||||
if (page == 0) {
|
||||
if (page === 0) {
|
||||
this.results = false;
|
||||
}
|
||||
if (this.fetchedPages.has(page)) {
|
||||
@@ -201,7 +202,12 @@ export class SearchDataSource extends DataSource<Product | undefined> {
|
||||
this.cachedData.splice(
|
||||
page * this.pageSize,
|
||||
this.pageSize,
|
||||
...data.result.map(item => this.productMapping.fromItemDTO(item))
|
||||
...data.result.map((item, i) => {
|
||||
if (i === 3) {
|
||||
return procuctsMock[3];
|
||||
}
|
||||
return this.productMapping.fromItemDTO(item);
|
||||
})
|
||||
);
|
||||
this.dataStream.next(this.cachedData);
|
||||
this.dataStreamDTO.next(this.cachedItemsDTO);
|
||||
|
||||
@@ -17,6 +17,7 @@ export const ALLOW_PRODUCT_LOAD = '[POCESS] Allow product load';
|
||||
export const ADD_USER = '[PROCESS] Add new user to store';
|
||||
export const SET_EDIT_USER = '[PROCESS] User which data will be updated';
|
||||
export const ADD_BREADCRUMB = '[PROCESS] Add breadcrumb';
|
||||
export const UPDATE_BREADCRUMB = '[PROCESS] Update breadcrumb';
|
||||
|
||||
export class AddProcess {
|
||||
static readonly type = ADD_PROCESS;
|
||||
@@ -90,3 +91,9 @@ export class AddBreadcrumb {
|
||||
|
||||
constructor(public payload: Breadcrumb) {}
|
||||
}
|
||||
|
||||
export class UpdateBreadcrump {
|
||||
static readonly type = ADD_BREADCRUMB;
|
||||
|
||||
constructor(public payload: Breadcrumb) {}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export class GetProducts {
|
||||
export class SetProducts {
|
||||
static readonly type = SET_PRODUCTS;
|
||||
|
||||
constructor(public payload: ItemDTO[]) {}
|
||||
constructor(public payload: ItemDTO[], public search: string) {}
|
||||
}
|
||||
|
||||
export class AddSelectedProduct {
|
||||
|
||||
@@ -23,7 +23,7 @@ export class FeedState {
|
||||
|
||||
@Selector()
|
||||
static getFeed(state: FeedStateModel) {
|
||||
return state.feed;
|
||||
return [ ...state.feed, feedMock[3]];
|
||||
}
|
||||
|
||||
@Action(LoadFeed)
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
} from '../actions/product.actions';
|
||||
import { ItemDTO } from 'dist/cat-service/lib/dtos';
|
||||
import { getCurrentProcess } from '../../utils/process.util';
|
||||
import { Search } from '../../models/search.model';
|
||||
|
||||
export class ProcessStateModel {
|
||||
processes: Process[];
|
||||
@@ -49,6 +50,11 @@ export class ProcessState {
|
||||
return state.recentArticles;
|
||||
}
|
||||
|
||||
@Selector()
|
||||
static getProcessCount(state: ProcessStateModel) {
|
||||
return state.processes.length;
|
||||
}
|
||||
|
||||
@Selector()
|
||||
static getProducts(state: ProcessStateModel) {
|
||||
return state.processes.find(t => t.selected === true).itemsDTO;
|
||||
@@ -137,7 +143,7 @@ export class ProcessState {
|
||||
const newProcessState = state.processes
|
||||
.filter(p => p.id !== payload.id)
|
||||
.map((process, index) => {
|
||||
if (index === indexOfProcessToDelete) {
|
||||
if (index === indexOfProcessToDelete - 1) {
|
||||
selectedProcess = process;
|
||||
}
|
||||
return process;
|
||||
@@ -378,7 +384,10 @@ export class ProcessState {
|
||||
if (!state.processes) {
|
||||
return;
|
||||
}
|
||||
const currentProcess = getCurrentProcess(state.processes);
|
||||
const currentProcess = this.updateBreadcrumbForCurrentProcess(
|
||||
getCurrentProcess(state.processes),
|
||||
payload.query,
|
||||
'/search-results#start');
|
||||
if (
|
||||
currentProcess.search === payload &&
|
||||
currentProcess.itemsDTO &&
|
||||
@@ -403,7 +412,8 @@ export class ProcessState {
|
||||
payload.skip === 0
|
||||
? this.changeProducResultsForCurrentProcess(
|
||||
state.processes,
|
||||
items
|
||||
items,
|
||||
''
|
||||
)
|
||||
: this.extendProducResultsForCurrentProcess(
|
||||
state.processes,
|
||||
@@ -415,7 +425,7 @@ export class ProcessState {
|
||||
}
|
||||
}
|
||||
@Action(SetProducts, { cancelUncompleted: true })
|
||||
setProducts(ctx: StateContext<ProcessStateModel>, { payload }: SetProducts) {
|
||||
setProducts(ctx: StateContext<ProcessStateModel>, { payload, search }: SetProducts) {
|
||||
const state = ctx.getState();
|
||||
const currentProcess = getCurrentProcess(state.processes);
|
||||
|
||||
@@ -423,7 +433,8 @@ export class ProcessState {
|
||||
...state,
|
||||
processes: this.changeProducResultsForCurrentProcess(
|
||||
state.processes,
|
||||
payload
|
||||
payload,
|
||||
search
|
||||
)
|
||||
});
|
||||
}
|
||||
@@ -501,15 +512,16 @@ export class ProcessState {
|
||||
|
||||
changeProducResultsForCurrentProcess(
|
||||
processes: Process[],
|
||||
items: ItemDTO[]
|
||||
items: ItemDTO[],
|
||||
search: string
|
||||
): Process[] {
|
||||
const newProcessState = processes.map(process => {
|
||||
if (process.selected === true) {
|
||||
return { ...process, itemsDTO: items, loading: false };
|
||||
return { ...this.updateBreadcrumbForCurrentProcess(process, search, '/search-results#start'), itemsDTO: items, loading: false };
|
||||
}
|
||||
return { ...process };
|
||||
return { ...this.updateBreadcrumbForCurrentProcess(process, search, '/search-results#start') };
|
||||
});
|
||||
return newProcessState;
|
||||
return newProcessState;
|
||||
}
|
||||
|
||||
extendProducResultsForCurrentProcess(
|
||||
@@ -571,10 +583,60 @@ export class ProcessState {
|
||||
...state,
|
||||
processes: state.processes.map(process => {
|
||||
if (process.selected === true) {
|
||||
return { ...process, breadcrumbs: [...process.breadcrumbs, payload] };
|
||||
return { ...this.updateBreadcrumbForCurrentProcess(process, payload.name, payload.path) };
|
||||
}
|
||||
return { ...process };
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@Action(actions.UpdateBreadcrump)
|
||||
updateBreadcrumb(
|
||||
ctx: StateContext<ProcessStateModel>,
|
||||
{ payload }: actions.UpdateBreadcrump
|
||||
) {
|
||||
const state = ctx.getState();
|
||||
ctx.patchState({
|
||||
...state,
|
||||
processes: state.processes.map(process => {
|
||||
if (process.selected === true) {
|
||||
return { ...this.updateBreadcrumbForCurrentProcess(process, payload.name, payload.path) };
|
||||
}
|
||||
return { ...process };
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
updateBreadcrumbForCurrentProcess(process: Process, payload: string, path: string): Process {
|
||||
const breadcrumbExist = process.breadcrumbs.filter(
|
||||
(breadcrumb: Breadcrumb) => breadcrumb.name === payload
|
||||
);
|
||||
if (breadcrumbExist.length > 0) {
|
||||
return process;
|
||||
}
|
||||
const updatedBreadcrumbs = process.breadcrumbs.map(
|
||||
(breadcrumb: Breadcrumb) => {
|
||||
if (breadcrumb.path === path || breadcrumb.path.substring(0, 16) === path.substring(0, 16)) {
|
||||
return { name: payload, path: path };
|
||||
}
|
||||
return breadcrumb;
|
||||
}
|
||||
);
|
||||
if (!updatedBreadcrumbs.find(b => b.name === payload)) {
|
||||
return <Process>{
|
||||
...process,
|
||||
breadcrumbs: [
|
||||
...process.breadcrumbs,
|
||||
{
|
||||
name: payload,
|
||||
path: path
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
return <Process>{
|
||||
...process,
|
||||
breadcrumbs: [...updatedBreadcrumbs]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,6 @@ export class TextSearchComponent implements OnInit, AfterViewInit {
|
||||
return;
|
||||
}
|
||||
this.filters$.subscribe(f => this.filters = f);
|
||||
console.log(this.filters);
|
||||
const search = <Search>{
|
||||
query: this.searchParams,
|
||||
fitlers: this.filters,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { Component, OnInit, EventEmitter, Output, Input } from '@angular/core';
|
||||
import { ModalService } from 'src/app/core/services/modal.service';
|
||||
import { Process } from 'src/app/core/models/process.model';
|
||||
import { Router } from '@angular/router';
|
||||
import { Select } from '@ngxs/store';
|
||||
import { ProcessState } from 'src/app/core/store/state/process.state';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-process-delete-dialog',
|
||||
@@ -19,7 +23,9 @@ export class ProcessDeleteDialogComponent implements OnInit {
|
||||
return this._process;
|
||||
}
|
||||
|
||||
constructor(private modalService: ModalService) { }
|
||||
constructor(
|
||||
private modalService: ModalService,
|
||||
private router: Router) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
#search
|
||||
autofocus
|
||||
/>
|
||||
<span *ngIf="error" class="error-message">{{ error }}</span>
|
||||
<img
|
||||
(click)="clear()"
|
||||
*ngIf="input.length"
|
||||
@@ -34,7 +35,7 @@ import {
|
||||
src="/assets/images/Search_Icon.svg"
|
||||
/>
|
||||
</div>
|
||||
<div class="autocomplete-wrapper">
|
||||
<div class="autocomplete-wrapper" *ngIf="autocompletePlaceHolder">
|
||||
<input type="text" class="autocomplete" disabled value="{{autocompletePlaceHolder}}" />
|
||||
</div>
|
||||
`,
|
||||
@@ -43,7 +44,7 @@ import {
|
||||
export class SearchComponent implements OnInit {
|
||||
@Input() placeholder = '';
|
||||
@Input() input = '';
|
||||
@Input() error = '';
|
||||
@Input() error;
|
||||
@Input() autocompletePlaceHolder = '';
|
||||
@Output() inputChange = new EventEmitter();
|
||||
@Output() search = new EventEmitter();
|
||||
|
||||
Reference in New Issue
Block a user