mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
66155: Show more/less incremental on item pages + loading component for entities
This commit is contained in:
@@ -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",
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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>
|
||||||
|
Reference in New Issue
Block a user