mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
[HIMA-888] Artikel suche: article card font resize if more than one line of the article title implementation
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user