66155: Show more/less incremental on item pages + loading component for entities

This commit is contained in:
Kristof De Langhe
2019-11-14 13:29:39 +01:00
parent 576b5328c3
commit aedd4b99ee
5 changed files with 119 additions and 48 deletions

View File

@@ -405,8 +405,8 @@
"item.page.link.full": "Full item page", "item.page.link.full": "Full item page",
"item.page.link.simple": "Simple item page", "item.page.link.simple": "Simple item page",
"item.page.person.search.title": "Articles by this author", "item.page.person.search.title": "Articles by this author",
"item.page.related-items.view-more": "View more", "item.page.related-items.view-more": "Show {{ amount }} more",
"item.page.related-items.view-less": "View less", "item.page.related-items.view-less": "Hide last {{ amount }}",
"item.page.subject": "Keywords", "item.page.subject": "Keywords",
"item.page.uri": "URI", "item.page.uri": "URI",

View File

@@ -1,11 +1,18 @@
<ds-metadata-field-wrapper *ngIf="representations$ && (representations$ | async)?.length > 0" [label]="label"> <ds-metadata-field-wrapper [label]="label">
<ds-item-type-switcher *ngFor="let rep of (representations$ | async)" <ng-container *ngVar="(representations$ | async) as representations">
<ds-item-type-switcher *ngFor="let rep of representations"
[object]="rep" [viewMode]="viewMode"> [object]="rep" [viewMode]="viewMode">
</ds-item-type-switcher> </ds-item-type-switcher>
<div *ngIf="(representations$ | async)?.length < total" class="mt-2"> <ds-loading *ngIf="loading" message="{{'loading.default' | translate}}"></ds-loading>
<a [routerLink]="" (click)="viewMore()">{{'item.page.related-items.view-more' | translate}}</a> <div class="d-inline-block w-100 mt-2" *ngIf="representations?.length > 0">
<div *ngIf="representations?.length < total" class="float-left">
<a [routerLink]="" (click)="viewMore()">{{'item.page.related-items.view-more' |
translate:{ amount: (total - representations?.length < incrementBy) ? total - representations?.length : incrementBy } }}</a>
</div> </div>
<div *ngIf="limit > originalLimit" class="mt-2"> <div *ngIf="limit > originalLimit" class="float-right">
<a [routerLink]="" (click)="viewLess()">{{'item.page.related-items.view-less' | translate}}</a> <a [routerLink]="" (click)="viewLess()">{{'item.page.related-items.view-less' |
translate:{ amount: (representations?.length < limit) ? limit - representations?.length : incrementBy } }}</a>
</div> </div>
</div>
</ng-container>
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>

View File

@@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model'; import { MetadataRepresentation } from '../../../core/shared/metadata-representation/metadata-representation.model';
import { ItemViewMode } from '../../../shared/items/item-type-decorator'; import { ItemViewMode } from '../../../shared/items/item-type-decorator';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
@@ -12,6 +12,8 @@ import { filter, map, switchMap } from 'rxjs/operators';
import { getSucceededRemoteData } from '../../../core/shared/operators'; import { getSucceededRemoteData } from '../../../core/shared/operators';
import { Relationship } from '../../../core/shared/item-relationships/relationship.model'; import { Relationship } from '../../../core/shared/item-relationships/relationship.model';
import { ItemMetadataRepresentation } from '../../../core/shared/metadata-representation/item/item-metadata-representation.model'; import { ItemMetadataRepresentation } from '../../../core/shared/metadata-representation/item/item-metadata-representation.model';
import { Subscription } from 'rxjs/internal/Subscription';
import { PaginatedList } from '../../../core/data/paginated-list';
@Component({ @Component({
selector: 'ds-metadata-representation-list', selector: 'ds-metadata-representation-list',
@@ -23,7 +25,7 @@ import { ItemMetadataRepresentation } from '../../../core/shared/metadata-repres
* It expects an itemType to resolve the metadata to a an item * It expects an itemType to resolve the metadata to a an item
* It expects a label to put on top of the list * It expects a label to put on top of the list
*/ */
export class MetadataRepresentationListComponent implements OnInit { export class MetadataRepresentationListComponent implements OnInit, OnDestroy {
/** /**
* The parent of the list of related items to display * The parent of the list of related items to display
*/ */
@@ -51,6 +53,18 @@ export class MetadataRepresentationListComponent implements OnInit {
*/ */
@Input() limit = 10; @Input() limit = 10;
/**
* The amount to increment the list by when clicking "view more"
* Defaults to 10
* The default can optionally be overridden by providing the limit as input to the component
*/
@Input() incrementBy = 10;
/**
* Is the list (re-)loading?
*/
loading = false;
/** /**
* A list of metadata-representations to display * A list of metadata-representations to display
*/ */
@@ -73,6 +87,11 @@ export class MetadataRepresentationListComponent implements OnInit {
*/ */
total: number; total: number;
/**
* Subscription on representations used to update the "loading" property of this component
*/
representationsSub: Subscription;
constructor(public relationshipService: RelationshipService) { constructor(public relationshipService: RelationshipService) {
} }
@@ -88,6 +107,9 @@ export class MetadataRepresentationListComponent implements OnInit {
const metadata = this.parentItem.findMetadataSortedByPlace(this.metadataField); const metadata = this.parentItem.findMetadataSortedByPlace(this.metadataField);
this.total = metadata.length; this.total = metadata.length;
this.representations$ = this.resolveMetadataRepresentations(metadata); this.representations$ = this.resolveMetadataRepresentations(metadata);
this.representationsSub = this.representations$.subscribe((represenations: MetadataRepresentation[]) => {
this.loading = represenations.length !== this.limit && represenations.length !== this.total;
});
} }
/** /**
@@ -124,18 +146,31 @@ export class MetadataRepresentationListComponent implements OnInit {
} }
/** /**
* Expand the list to display all metadata representations * Expand the list to display more metadata representations
*/ */
viewMore() { viewMore() {
this.limit = 9999; this.limit = this.limit + this.incrementBy;
this.loading = true;
this.setRepresentations(); this.setRepresentations();
} }
/** /**
* Collapse the list to display the originally displayed metadata representations * Collapse the list to display less metadata representations
*/ */
viewLess() { viewLess() {
this.limit = this.originalLimit; if (this.limit > this.originalLimit) {
this.limit = this.limit - this.incrementBy;
}
this.loading = true;
this.setRepresentations(); this.setRepresentations();
} }
/**
* Unsubscribe from the representations subscription
*/
ngOnDestroy(): void {
if (this.representationsSub) {
this.representationsSub.unsubscribe();
}
}
} }

View File

@@ -32,10 +32,24 @@ export class RelatedItemsComponent implements OnInit, OnDestroy {
@Input() relationType: string; @Input() relationType: string;
/** /**
* Default options to start a search request with * The max amount of relations to display
* Optional input, should you wish a different page size (or other options) * Defaults to 5
* The default can optionally be overridden by providing the limit as input to the component
*/ */
@Input() options = Object.assign(new FindAllOptions(), { elementsPerPage: 5 }); @Input() limit = 5;
/**
* The amount to increment the list by when clicking "view more"
* Defaults to 5
* The default can optionally be overridden by providing the limit as input to the component
*/
@Input() incrementBy = 5;
/**
* Default options to start a search request with
* Optional input
*/
@Input() options = new FindAllOptions();
/** /**
* An i18n label to use as a title for the list (usually describes the relation) * An i18n label to use as a title for the list (usually describes the relation)
@@ -43,20 +57,15 @@ export class RelatedItemsComponent implements OnInit, OnDestroy {
@Input() label: string; @Input() label: string;
/** /**
* Completely hide the component until there's at least one item visible * Is the list (re-)loading?
*/ */
@HostBinding('class.d-none') hidden = true; loading = false;
/** /**
* The list of related items * The list of related items
*/ */
items$: Observable<RemoteData<PaginatedList<Item>>>; items$: Observable<RemoteData<PaginatedList<Item>>>;
/**
* Search options for displaying all elements in a list
*/
allOptions = Object.assign(new FindAllOptions(), { elementsPerPage: 9999 });
/** /**
* The view-mode we're currently on * The view-mode we're currently on
* @type {ElementViewMode} * @type {ElementViewMode}
@@ -64,12 +73,13 @@ export class RelatedItemsComponent implements OnInit, OnDestroy {
viewMode = ItemViewMode.Element; viewMode = ItemViewMode.Element;
/** /**
* Whether or not the list is currently expanded to show all related items * The originally provided limit
* Used for comparing the current size with the original
*/ */
showingAll = false; originalLimit: number;
/** /**
* Subscription on items used to update the "hidden" property of this component * Subscription on items used to update the "loading" property of this component
*/ */
itemSub: Subscription; itemSub: Subscription;
@@ -77,26 +87,38 @@ export class RelatedItemsComponent implements OnInit, OnDestroy {
} }
ngOnInit(): void { ngOnInit(): void {
this.items$ = this.relationshipService.getRelatedItemsByLabel(this.parentItem, this.relationType, this.options); this.originalLimit = this.limit;
this.reloadItems();
}
/**
* Reload the current list of items (using the current limit)
*/
reloadItems() {
this.items$ = this.relationshipService.getRelatedItemsByLabel(this.parentItem, this.relationType, Object.assign(this.options, { elementsPerPage: this.limit }));
this.itemSub = this.items$.subscribe((itemsRD: RemoteData<PaginatedList<Item>>) => { this.itemSub = this.items$.subscribe((itemsRD: RemoteData<PaginatedList<Item>>) => {
this.hidden = !(itemsRD.hasSucceeded && itemsRD.payload && itemsRD.payload.page.length > 0); this.loading = !(itemsRD.hasSucceeded && itemsRD.payload && itemsRD.payload.page.length > 0);
}); });
} }
/** /**
* Expand the list to display all related items * Expand the list to display more
*/ */
viewMore() { viewMore() {
this.items$ = this.relationshipService.getRelatedItemsByLabel(this.parentItem, this.relationType, this.allOptions); this.limit = this.limit + this.incrementBy;
this.showingAll = true; this.loading = true;
this.reloadItems();
} }
/** /**
* Collapse the list to display the originally displayed items * Collapse the list to display less
*/ */
viewLess() { viewLess() {
this.items$ = this.relationshipService.getRelatedItemsByLabel(this.parentItem, this.relationType, this.options); if (this.limit > this.originalLimit) {
this.showingAll = false; this.limit = this.limit - this.incrementBy;
}
this.loading = true;
this.reloadItems();
} }
/** /**

View File

@@ -1,11 +1,18 @@
<ds-metadata-field-wrapper *ngIf="(items$ | async)?.payload?.page?.length > 0" [label]="label"> <ds-metadata-field-wrapper [label]="label">
<ds-item-type-switcher *ngFor="let item of (items$ | async)?.payload?.page" <ng-container *ngVar="(items$ | async) as itemsRD">
<ds-item-type-switcher *ngFor="let item of itemsRD?.payload?.page"
[object]="item" [viewMode]="viewMode"> [object]="item" [viewMode]="viewMode">
</ds-item-type-switcher> </ds-item-type-switcher>
<div *ngIf="(items$ | async)?.payload?.page?.length < (items$ | async)?.payload?.totalElements" class="mt-2" id="view-more"> <ds-loading *ngIf="loading" message="{{'loading.default' | translate}}"></ds-loading>
<a [routerLink]="" (click)="viewMore()">{{'item.page.related-items.view-more' | translate}}</a> <div class="d-inline-block w-100 mt-2" *ngIf="itemsRD?.payload?.page?.length > 0">
<div *ngIf="itemsRD?.payload?.page?.length < itemsRD?.payload?.totalElements" class="float-left" id="view-more">
<a [routerLink]="" (click)="viewMore()">{{'item.page.related-items.view-more' |
translate:{ amount: (itemsRD?.payload?.totalElements - itemsRD?.payload?.page?.length < incrementBy) ? itemsRD?.payload?.totalElements - itemsRD?.payload?.page?.length : incrementBy } }}</a>
</div> </div>
<div *ngIf="showingAll" class="mt-2" id="view-less"> <div *ngIf="limit > originalLimit" class="float-right" id="view-less">
<a [routerLink]="" (click)="viewLess()">{{'item.page.related-items.view-less' | translate}}</a> <a [routerLink]="" (click)="viewLess()">{{'item.page.related-items.view-less' |
translate:{ amount: (itemsRD?.payload?.page?.length < limit) ? limit - itemsRD?.payload?.page?.length : incrementBy } }}</a>
</div> </div>
</div>
</ng-container>
</ds-metadata-field-wrapper> </ds-metadata-field-wrapper>