Skip to content

Commit

Permalink
Merge pull request #209 from swisstopo/feature/assets-202-search-flow
Browse files Browse the repository at this point in the history
Feature/assets 202 search flow
  • Loading branch information
TIL-EBP authored Jul 15, 2024
2 parents 337d509 + 0813b34 commit 6b65fef
Show file tree
Hide file tree
Showing 20 changed files with 193 additions and 148 deletions.
2 changes: 1 addition & 1 deletion apps/client-asset-sg/src/app/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const deAppTranslations = {
closeInstructions: 'Anleitung schliessen',
searchControl: 'Suchsteuerung',
refineSearch: 'Suche verfeinern',
searchResults: 'Suchtreffer',
searchResults: 'Assets',
author: 'Autor',
documentDate: 'Dokumentdatum',
usage: 'Nutzung',
Expand Down
2 changes: 1 addition & 1 deletion apps/client-asset-sg/src/app/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const enAppTranslations: AppTranslations = {
closeInstructions: 'Close instructions',
searchControl: 'Search control',
refineSearch: 'Refine search',
searchResults: 'Search results',
searchResults: 'Assets',
author: 'Author',
documentDate: 'Document date',
usage: 'Usage',
Expand Down
2 changes: 1 addition & 1 deletion apps/client-asset-sg/src/app/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const frAppTranslations: AppTranslations = {
closeInstructions: "Fermer le mode d'emploi",
searchControl: 'Commande de recherche',
refineSearch: 'Affiner la recherche',
searchResults: 'Résultats de recherche',
searchResults: 'Assets',
author: 'Auteurr',
documentDate: 'Date du document',
usage: 'Utilisation',
Expand Down
2 changes: 1 addition & 1 deletion apps/client-asset-sg/src/app/i18n/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const itAppTranslations: AppTranslations = {
closeInstructions: 'IT Anleitung schliessen',
searchControl: 'IT Suchsteuerung',
refineSearch: 'IT Suche verfeinern',
searchResults: 'IT Suchtreffer',
searchResults: 'IT Assets',
author: 'IT Autor',
documentDate: 'IT Dokumentdatum',
usage: 'IT Nutzung',
Expand Down
2 changes: 1 addition & 1 deletion apps/client-asset-sg/src/app/i18n/rm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const rmAppTranslations: AppTranslations = {
closeInstructions: 'RM Anleitung schliessen',
searchControl: 'RM Suchsteuerung',
refineSearch: 'RM Suche verfeinern',
searchResults: 'RM Suchtreffer',
searchResults: 'RM Assets',
author: 'RM Autor',
documentDate: 'RM Dokumentdatum',
usage: 'RM Nutzung',
Expand Down
3 changes: 0 additions & 3 deletions apps/client-asset-sg/src/app/state/app-shared.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import * as R from 'fp-ts/Record';
const initialState: AppSharedState = {
rdUserProfile: RD.initial,
rdReferenceData: RD.initial,
isPanelOpen: false,
lang: 'de',
};

Expand All @@ -23,8 +22,6 @@ export const appSharedStateReducer = createReducer(
(state, rdReferenceData): AppSharedState => ({ ...state, rdReferenceData })
),
on(appSharedStateActions.logout, (): AppSharedState => initialState),
on(appSharedStateActions.openPanel, (state): AppSharedState => ({ ...state, isPanelOpen: true })),
on(appSharedStateActions.closePanel, (state): AppSharedState => ({ ...state, isPanelOpen: false })),
on(appSharedStateActions.setLang, (state, { lang }): AppSharedState => ({ ...state, lang })),
on(
appSharedStateActions.createContactResult,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export class AssetSearchFilterListComponent<T extends string> {
}
this.store.dispatch(
actions.searchByFilterConfiguration({
filterConfiguration: { [filter.queryKey]: [...activeValues] },
filterConfiguration: { [filter.queryKey]: activeValues.size > 0 ? [...activeValues] : undefined },
})
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,80 +11,75 @@
</div>
<ng-container *ngIf="isResultsOpen">
<div class="search-results">
<div *ngIf="(loadingState | async) === LoadingState.Loading; else results" class="loading-spinner">
<mat-progress-spinner mode="indeterminate" />
<div class="table-container" (scroll)="onScroll($event)" #scrollContainer>
<table mat-table [dataSource]="resultsToDisplay" class="mat-elevation-z8 table">
<ng-container matColumnDef="favourites">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let asset">
<button asset-sg-reset class="asset-favourite">
<svg-icon key="favourite" />
</button>
</td>
</ng-container>
<ng-container matColumnDef="titlePublic">
<th mat-header-cell *matHeaderCellDef translate>{{ "edit.tabs.references.assetTitlePublic" }}</th>
<td mat-cell *matCellDef="let asset">{{ asset.titlePublic }}</td>
</ng-container>
<ng-container matColumnDef="assetFormat">
<th mat-header-cell *matHeaderCellDef translate>{{ "search.kind" }}</th>
<td mat-cell *matCellDef="let asset">
{{ asset.assetKindItem | valueItemName }} &ndash; {{ asset.assetFormatItem | valueItemName }}
</td>
</ng-container>
<ng-container matColumnDef="manCatLabel">
<th mat-header-cell *matHeaderCellDef translate>{{ "search.topic" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let manCatLabelItem of asset.manCatLabelItems">
{{ manCatLabelItem | valueItemName }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="authors">
<th mat-header-cell *matHeaderCellDef translate>{{ "contactRoles.author" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let contact of asset.contacts.author">
{{ contact.name }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="initiators">
<th mat-header-cell *matHeaderCellDef translate>{{ "contactRoles.initiator" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let contact of asset.contacts.initiator">
{{ contact.name }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="suppliers">
<th mat-header-cell *matHeaderCellDef translate>{{ "contactRoles.supplier" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let contact of asset.contacts.supplier">
{{ contact.name }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="createDate">
<th mat-header-cell *matHeaderCellDef translate>{{ "search.createdDate" }}</th>
<td mat-cell *matCellDef="let asset">
{{ asset.createDate | assetSgDate }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="COLUMNS; sticky: true" class="table-header"></tr>
<tr
mat-row
*matRowDef="let row; columns: COLUMNS"
(click)="searchForAsset(row.assetId)"
(mouseover)="assetMouseOver.emit(row.assetId)"
(mouseleave)="assetMouseOver.emit(null)"
[ngClass]="{ selected: row.assetId === (currentAssetDetail$ | async)?.assetId }"
></tr>
</table>
</div>
<ng-template #results>
<div class="table-container">
<table mat-table [dataSource]="assets$" class="mat-elevation-z8 table">
<ng-container matColumnDef="favourites">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let asset">
<button asset-sg-reset class="asset-favourite">
<svg-icon key="favourite" />
</button>
</td>
</ng-container>
<ng-container matColumnDef="titlePublic">
<th mat-header-cell *matHeaderCellDef translate>{{ "edit.tabs.references.assetTitlePublic" }}</th>
<td mat-cell *matCellDef="let asset">{{ asset.titlePublic }}</td>
</ng-container>
<ng-container matColumnDef="assetFormat">
<th mat-header-cell *matHeaderCellDef translate>{{ "search.kind" }}</th>
<td mat-cell *matCellDef="let asset">
{{ asset.assetKindItem | valueItemName }} &ndash; {{ asset.assetFormatItem | valueItemName }}
</td>
</ng-container>
<ng-container matColumnDef="manCatLabel">
<th mat-header-cell *matHeaderCellDef translate>{{ "search.topic" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let manCatLabelItem of asset.manCatLabelItems">
{{ manCatLabelItem | valueItemName }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="authors">
<th mat-header-cell *matHeaderCellDef translate>{{ "contactRoles.author" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let contact of asset.contacts.author">
{{ contact.name }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="initiators">
<th mat-header-cell *matHeaderCellDef translate>{{ "contactRoles.initiator" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let contact of asset.contacts.initiator">
{{ contact.name }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="suppliers">
<th mat-header-cell *matHeaderCellDef translate>{{ "contactRoles.supplier" }}</th>
<td mat-cell *matCellDef="let asset">
<div *ngFor="let contact of asset.contacts.supplier">
{{ contact.name }}
</div>
</td>
</ng-container>
<ng-container matColumnDef="createDate">
<th mat-header-cell *matHeaderCellDef translate>{{ "search.createdDate" }}</th>
<td mat-cell *matCellDef="let asset">
{{ asset.createDate | assetSgDate }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="COLUMNS; sticky: true" class="table-header"></tr>
<tr
mat-row
*matRowDef="let row; columns: COLUMNS"
(click)="searchForAsset(row.assetId)"
(mouseover)="assetMouseOver.emit(row.assetId)"
(mouseleave)="assetMouseOver.emit(null)"
[ngClass]="{ selected: row.assetId === (currentAssetDetail$ | async)?.assetId }"
></tr>
</table>
</div>
</ng-template>
</div>
</ng-container>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,6 @@
color: variables.$cyan-09;
}

.loading-spinner {
position: absolute;
inset: 0;
z-index: 100;
display: grid;
place-items: center;
background-color: variables.$grey-03;
}

.mat-mdc-header-row .mat-mdc-cell {
background-color: variables.$grey-01;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import { ChangeDetectionStrategy, Component, EventEmitter, inject, Output } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import {
ChangeDetectionStrategy,
Component,
ElementRef,
EventEmitter,
inject,
OnDestroy,
OnInit,
Output,
ViewChild,
} from '@angular/core';
import { Store } from '@ngrx/store';
import * as O from 'fp-ts/Option';
import { Observable } from 'rxjs';
import { Subscription } from 'rxjs';
import * as actions from '../../state/asset-search/asset-search.actions';
import { AppStateWithAssetSearch, LoadingState } from '../../state/asset-search/asset-search.reducer';
import { AppStateWithAssetSearch } from '../../state/asset-search/asset-search.reducer';
import {
AssetEditDetailVM,
selectAssetEditDetailVM,
selectAssetSearchPageData,
selectCurrentAssetDetail,
selectIsResultsOpen,
selectSearchLoadingState,
} from '../../state/asset-search/asset-search.selector';

@Component({
Expand All @@ -19,7 +27,8 @@ import {
styleUrls: ['./asset-search-results.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AssetSearchResultsComponent {
export class AssetSearchResultsComponent implements OnInit, OnDestroy {
@ViewChild('scrollContainer') scrollContainer?: ElementRef;
@Output() closeSearchResultsClicked = new EventEmitter<void>();
@Output() assetMouseOver = new EventEmitter<number | null>();

Expand All @@ -33,16 +42,25 @@ export class AssetSearchResultsComponent {
'createDate',
];

private _store = inject(Store<AppStateWithAssetSearch>);
private _router = inject(Router);
private _route = inject(ActivatedRoute);
public isResultsOpen$ = this._store.select(selectIsResultsOpen);
public assets$ = this._store.select(selectAssetEditDetailVM);
public loadingState = this._store.select(selectSearchLoadingState);
public pageStats$ = this._store.select(selectAssetSearchPageData);
public currentAssetDetail$ = this._store.select(selectCurrentAssetDetail);
public allResults: AssetEditDetailVM[] = [];
public resultsToDisplay: AssetEditDetailVM[] = [];
private size = 0;
private limit = 100;

private readonly _store = inject(Store<AppStateWithAssetSearch>);
public readonly isResultsOpen$ = this._store.select(selectIsResultsOpen);
public readonly assets$ = this._store.select(selectAssetEditDetailVM);
public readonly pageStats$ = this._store.select(selectAssetSearchPageData);
public readonly currentAssetDetail$ = this._store.select(selectCurrentAssetDetail);
private readonly subscriptions: Subscription = new Subscription();

public ngOnInit() {
this.initSubscriptions();
}

protected readonly LoadingState = LoadingState;
public ngOnDestroy() {
this.subscriptions.unsubscribe();
}

public searchForAsset(assetId: number) {
this._store.dispatch(actions.assetClicked({ assetId }));
Expand All @@ -55,4 +73,26 @@ export class AssetSearchResultsComponent {
this._store.dispatch(actions.openResults());
}
}

public onScroll(event: Event) {
const target = event.target as HTMLElement;

if (target.offsetHeight + target.scrollTop >= target.scrollHeight) {
this.size += this.limit;
this.resultsToDisplay = this.allResults.slice(0, this.size);
}
}

private initSubscriptions() {
this.subscriptions.add(
this.assets$.subscribe((assets) => {
this.allResults = assets;
this.size = this.limit;
this.resultsToDisplay = this.allResults.slice(0, this.size);
if (this.scrollContainer) {
this.scrollContainer.nativeElement.scrollTop = 0;
}
})
);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<mat-progress-bar *ngIf="isLoading$ | async" mode="indeterminate" class="loading-bar" />
<asset-sg-map
[highlightedAssetId]="highlightedAssetId"
(assetsClick)="assetClicked$.next($event)"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
@use "../../styles/variables";

:host {
position: relative;
position: relative;
height: 100%;
overflow: hidden;
Expand All @@ -14,6 +13,13 @@
grid-template-columns: auto 1fr auto;
}

.loading-bar {
position: absolute;
inset: 0;
z-index: 100;
background-color: variables.$grey-03;
}

asset-sg-map,
asset-sg-map {
grid-area: map;
Expand Down
Loading

0 comments on commit 6b65fef

Please sign in to comment.