[HIMA-888] Artikel suche: article card font resize if more than one line of the article title implementation

This commit is contained in:
Mikuta Aleksandras
2020-04-03 08:05:20 +02:00
parent f7b4e65b2a
commit f7804645c8
4 changed files with 71 additions and 91 deletions

View File

@@ -26,7 +26,6 @@ import { AddBreadcrumb } from 'apps/sales/src/app/core/store/actions/breadcrumb.
})
export class ProductCardComponent implements OnInit, OnDestroy, AfterViewChecked {
private _product: Product;
@Input() processId: number;
@Input() index: number;
@Input()

View File

@@ -1,14 +1,13 @@
import { DataSource, CollectionViewer } from '@angular/cdk/collections';
import { procuctsMock } from 'mock';
import { Product } from '../../../../core/models/product.model';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { debounceTime, take, takeUntil } from 'rxjs/operators';
import { DataSource, CollectionViewer } from '@angular/cdk/collections';
import { Store } from '@ngxs/store';
import { ItemDTO } from 'swagger';
import { Product } from '../../../../core/models/product.model';
import { ProductMapping } from '../../../../core/mappings/product.mapping';
import { ProductService } from '../../../../core/services/product.service';
import { Store } from '@ngxs/store';
import { debounceTime, take, takeUntil } from 'rxjs/operators';
import { SetProducts, SetProductCachedResults } from '../../../../core/store/actions/product.actions';
import { AppState } from 'apps/sales/src/app/core/store/state/app.state';
import { ItemDTO } from 'swagger';
import { Search } from 'apps/sales/src/app/core/models/search.model';
export class SearchDataSource extends DataSource<Product | undefined> {
@@ -16,15 +15,18 @@ export class SearchDataSource extends DataSource<Product | undefined> {
public cachedData = Array.from<Product>({ length: 0 });
private cachedItemsDTO = Array.from<ItemDTO>({ length: 0 });
private fetchedPages = new Set<number>();
private dataStream = new BehaviorSubject<(Product | undefined)[]>(this.cachedData);
public dataStreamDTO = new BehaviorSubject<(ItemDTO | undefined)[]>(this.cachedItemsDTO);
destroy$ = new Subject();
public loading = true;
public results = false;
private productMapping = new ProductMapping();
private dataStream = new BehaviorSubject<(Product | undefined)[]>(this.cachedData);
dataStreamDTO = new BehaviorSubject<(ItemDTO | undefined)[]>(this.cachedItemsDTO);
loading = true;
results = false;
destroy$ = new Subject();
static getPageForIndex(index: number): number {
return Math.floor(index / SearchDataSource.pageSize);
}
constructor(
public id: number,
private searchService: ProductService,
private search: Search,
private store: Store,
@@ -36,8 +38,8 @@ export class SearchDataSource extends DataSource<Product | undefined> {
}
connect(collectionViewer: CollectionViewer): Observable<(Product | undefined)[]> {
collectionViewer.viewChange.pipe(takeUntil(this.destroy$)).subscribe(range => {
const startPage = this.getPageForIndex(range.start);
const endPage = this.getPageForIndex(range.end - 1);
const startPage = SearchDataSource.getPageForIndex(range.start);
const endPage = SearchDataSource.getPageForIndex(range.end - 1);
for (let i = startPage; i <= endPage; i++) {
this.fetchPage(i);
}
@@ -52,20 +54,18 @@ export class SearchDataSource extends DataSource<Product | undefined> {
return this.dataStream;
}
disconnect(): void {
this.dataStream.complete();
this.dataStreamDTO.complete();
this.destroy$.next();
}
getProductsUpTo(page: number) {
for (let i = 0; i < page; i++) {
this.fetchPage(i);
}
}
disconnect(): void {
this.destroy$.next();
}
public getPageForIndex(index: number): number {
return Math.floor(index / SearchDataSource.pageSize);
}
private fetchPage(page: number) {
if (page === 0) {
this.results = false;
@@ -107,9 +107,7 @@ export class SearchDataSource extends DataSource<Product | undefined> {
this.cachedData.splice(
page * SearchDataSource.pageSize,
SearchDataSource.pageSize,
...data.result.map((item, i) => {
return this.productMapping.fromItemDTO(item);
})
...data.result.map((item, i) => this.productMapping.fromItemDTO(item))
);
this.dataStream.next(this.cachedData);
this.dataStreamDTO.next(this.cachedItemsDTO);

View File

@@ -1,5 +1,6 @@
<div class="result-container" *ngIf="!loading">
<app-interactive-filters (filtersUpdated)="filtersClicked($event)"></app-interactive-filters>
<div class="filter-mode-switcher">
<lib-small-double-choice-switch
leftValue="Filtern nach"
@@ -8,7 +9,9 @@
[selectedSide]="selectedFilterMode"
></lib-small-double-choice-switch>
</div>
<app-filter (toggle)="filterMoreToggle($event)" (filtersChanged)="updateSearch()" [selectedFilterMode]="selectedFilterMode"></app-filter>
<div *ngIf="!ds || (ds.loading && !ds.results)">
<div [@stagger]="'yes'">
<div *ngFor="let dummy of dummies" [style.marginTop.px]="10">
@@ -16,23 +19,24 @@
</div>
</div>
</div>
<div *ngIf="ds && !ds.loading && !loading && ds.cachedData.length === 0" class="no-results-text">Keine Suchergebnisse gefunden</div>
<cdk-virtual-scroll-viewport
autosize #scroller
autosize
#scroller
class="scrollbar-visible"
[ngClass]="{ 'cdk-stop-scrolling': scrollDisabled }">
<ng-container *cdkVirtualFor="let product of ds; let i = index; let last = last">
<div class="product-item">
<app-product-card
#productCard
[processId]="id"
[product]="product"
[index]="i"
*ngIf="product != null"
(authorFilter)="authorFilter($event)"
(saveProductPosition)="saveProductPositionHandler($event)"
>
</app-product-card>
></app-product-card>
<div class="loading-card-wrapper" *ngIf="product == null">
<app-product-card-loading></app-product-card-loading>
</div>
@@ -40,6 +44,7 @@
<div class="bottom-spacer" *ngIf="last"></div>
</ng-container>
</cdk-virtual-scroll-viewport>
<app-loading
*ngIf="!ds || ds.loading"
[style.marginTop.px]="60"
@@ -48,4 +53,5 @@
text="Inhalte werden geladen"
></app-loading>
</div>
<div class="overlay" *ngIf="scrollDisabled" [ngStyle]="{ height: filterContainerHeight }"></div>

View File

@@ -13,7 +13,6 @@ import {
import { Search } from '../../../../core/models/search.model';
import { Process } from '../../../../core/models/process.model';
import { Product } from '../../../../core/models/product.model';
import { Router } from '@angular/router';
import { Select, Store } from '@ngxs/store';
import { Observable, Subject } from 'rxjs';
import { staggerAnimation } from './stagger.animation';
@@ -76,14 +75,9 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
get areFiltersNegative() {
if (this.selectedFilterMode) {
return this.selectedFilterMode === Side.RIGHT;
} else {
const currentFilterType = this.store.selectSnapshot(SharedSelectors.getFilterType);
if (currentFilterType) {
return currentFilterType === FilterType.Negative;
} else {
return false;
}
}
const currentFilterType = this.store.selectSnapshot(SharedSelectors.getFilterType);
return (currentFilterType) ? currentFilterType === FilterType.Negative : false;
}
get filterContainerHeight() {
@@ -98,8 +92,7 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
private store: Store,
private productService: ProductService,
private cdr: ChangeDetectorRef,
private productUtils: ProductUtilService,
private router: Router
private productUtils: ProductUtilService
) {}
ngOnInit() {
@@ -109,17 +102,14 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
distinctUntilChanged((prev, curr) => prev && curr && JSON.stringify(prev) === JSON.stringify(curr)),
takeUntil(this.destroy$),
filter(data => !isNullOrUndefined(data) && data.id !== this.id),
switchMap(data => {
return this.store.select(SharedSelectors.getFilterType).pipe(
switchMap(data =>
this.store.select(SharedSelectors.getFilterType).pipe(
filter(fType => !isNullOrUndefined(fType)),
takeUntil(this.destroy$),
map(fType => {
return { filterType: fType, process: data };
})
);
})
)
.subscribe(({ filterType, process }) => {
return {filterType: fType, process: data};
}))))
.subscribe(({filterType, process}) => {
this.currentProcess = process;
this.currentSearch = process.search;
this.id = process.id;
@@ -133,7 +123,7 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
this.loadCountOfPage += 1;
this.loadDataSource(false);
if (this.loadCountOfPage === 1) {
this.store.dispatch(new AddSearch({ ...this.currentSearch, firstLoad: false }));
this.store.dispatch(new AddSearch({...this.currentSearch, firstLoad: false}));
}
}
});
@@ -171,16 +161,23 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
}
}
loadDataSource(skipCache: boolean) {
initiateDataSource(search: Search, filters: any[], areFiltersNegative: boolean, skipCache: boolean) {
this.ds = new SearchDataSource(
this.id,
this.productService,
this.currentSearch,
search,
this.store,
this.currentSearch.fitlers ? this.currentSearch.fitlers : [],
this.areFiltersNegative,
filters,
areFiltersNegative,
skipCache
);
}
loadDataSource(skipCache: boolean) {
this.initiateDataSource(
this.currentSearch,
this.currentSearch.fitlers ? this.currentSearch.fitlers : [],
this.areFiltersNegative,
skipCache);
// Load products up to the previous page
const [pageSize] = this.getSelectedProductScrollInformation();
@@ -241,16 +238,12 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
this.radioButtonGroup.radioButtons && this.radioButtonGroup.radioButtons.find(t => t.selected)
? this.radioButtonGroup.radioButtons.find(t => t.selected).key
: undefined;
const search = { ...currentSearch, type: type };
this.ds = new SearchDataSource(
this.id,
this.productService,
const search = {...currentSearch, type: type};
this.initiateDataSource(
search,
this.store,
!isNullOrUndefined(fil) ? fil : [],
this.areFiltersNegative,
true
);
true);
this.loading = false;
}
setTimeout(() => {
@@ -278,7 +271,7 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
this.store.dispatch(new AddSearch(this.currentSearch));
if (!this.searchFired) {
this.searchFired = true;
this.ds = new SearchDataSource(this.id, this.productService, this.currentSearch, this.store, [], this.areFiltersNegative, true);
this.initiateDataSource(this.currentSearch, [], this.areFiltersNegative, true);
this.loading = false;
this.searchFired = false;
this.cdr.detectChanges();
@@ -307,7 +300,7 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
};
this.store.dispatch(new AddSearch(exists));
this.ds = new SearchDataSource(this.id, this.productService, exists, this.store, filters, this.areFiltersNegative, true);
this.initiateDataSource(exists, filters, this.areFiltersNegative, true);
this.loading = false;
this.cdr.detectChanges();
@@ -322,24 +315,12 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
private activeFilters(): Filter[] {
let filters: Filter[] = [];
if (this.currentSearch.fitlers) {
filters = this.currentSearch.fitlers.map((filter: Filter) => {
if (filter.id === 'cattype') {
let fil = {
...filter,
items: filter.items.map((filterItm: FilterItem) => {
if (filterItm.id === '2') {
let itm = { ...filterItm, selected: this.acrhiveFilter };
return itm;
}
return { ...filterItm, selected: false };
})
};
return fil;
}
return filter;
});
filters = this.currentSearch.fitlers.map((f: Filter) => (f.id === 'cattype') ?
{
...f,
items: f.items.map((fi: FilterItem) => (fi.id === '2') ?
{...fi, selected: this.acrhiveFilter} : {...fi, selected: false})
} : f);
}
return filters;
}
@@ -347,16 +328,12 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
private selectAuthorFilter() {
if (this.radioButtonGroup) {
let radioButtons = this.radioButtonGroup.radioButtons;
radioButtons = radioButtons.map(radio => {
if (radio.key === 'author') {
return { ...radio, selected: true };
}
return { ...radio, selected: false };
});
radioButtons = radioButtons.map(radio => (radio.key === 'author') ?
{...radio, selected: true} : {...radio, selected: false});
const updatedRadios: RadioButtonGroup = { radioButtons };
const updatedRadios: RadioButtonGroup = {radioButtons};
this.radioButtonGroup = updatedRadios;
this.store.dispatch(new SetProcessProductFilters({ radioButtonGroup: updatedRadios, archiveFilters: this.acrhiveFilter }));
this.store.dispatch(new SetProcessProductFilters({radioButtonGroup: updatedRadios, archiveFilters: this.acrhiveFilter}));
}
}
@@ -395,10 +372,10 @@ export class ProductResultsComponent implements OnInit, OnDestroy, AfterViewInit
this.radioButtonGroup.radioButtons && this.radioButtonGroup.radioButtons.find(t => t.selected)
? this.radioButtonGroup.radioButtons.find(t => t.selected).key
: undefined;
const search = { ...currentSearch, type: type };
const search = {...currentSearch, type: type};
if (!this.searchFired) {
this.searchFired = true;
this.ds = new SearchDataSource(this.id, this.productService, search, this.store, [], false, true);
this.initiateDataSource(search, [], false, true);
this.loading = false;
this.searchFired = false;
}