1
0

68729: ItemVersionsComponent + changes to Version(History) model and services

This commit is contained in:
Kristof De Langhe
2020-02-19 11:48:17 +01:00
parent d4ff4aab36
commit 173f14c41f
11 changed files with 243 additions and 2 deletions

View File

@@ -981,6 +981,22 @@
"item.version.history.head": "Version History",
"item.version.history.selected": "Selected version",
"item.version.history.table.version": "Version",
"item.version.history.table.item": "Item",
"item.version.history.table.editor": "Editor",
"item.version.history.table.date": "Date",
"item.version.history.table.summary": "Summary",
"journal.listelement.badge": "Journal",
"journal.page.description": "Description",

View File

@@ -29,6 +29,7 @@ import { MetadataFieldWrapperComponent } from './field-components/metadata-field
import { TabbedRelatedEntitiesSearchComponent } from './simple/related-entities/tabbed-related-entities-search/tabbed-related-entities-search.component';
import { StatisticsModule } from '../statistics/statistics.module';
import { AbstractIncrementalListComponent } from './simple/abstract-incremental-list/abstract-incremental-list.component';
import { ItemVersionsComponent } from './item-versions/item-versions.component';
@NgModule({
imports: [
@@ -59,7 +60,8 @@ import { AbstractIncrementalListComponent } from './simple/abstract-incremental-
MetadataRepresentationListComponent,
RelatedEntitiesSearchComponent,
TabbedRelatedEntitiesSearchComponent,
AbstractIncrementalListComponent
AbstractIncrementalListComponent,
ItemVersionsComponent
],
exports: [
ItemComponent,

View File

@@ -0,0 +1,44 @@
<div *ngVar="(versionsRD$ | async)?.payload as versions">
<div *ngVar="(versionRD$ | async)?.payload as itemVersion">
<div *ngIf="versions?.page?.length > 0">
<h2>{{"item.version.history.head" | translate}}</h2>
<ds-pagination [hideGear]="true"
[hidePagerWhenSinglePage]="true"
[paginationOptions]="options"
[pageInfoState]="versions"
[collectionSize]="versions?.totalElements"
(pageChange)="switchPage($event)">
<table class="table table-striped my-2">
<thead>
<tr>
<th scope="col">{{"item.version.history.table.version" | translate}}</th>
<th scope="col">{{"item.version.history.table.item" | translate}}</th>
<th scope="col" *ngIf="(hasEpersons$ | async)">{{"item.version.history.table.editor" | translate}}</th>
<th scope="col">{{"item.version.history.table.date" | translate}}</th>
<th scope="col">{{"item.version.history.table.summary" | translate}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let version of versions?.page">
<td>{{version?.version}}</td>
<td>
<span *ngVar="(version?.item | async)?.payload as item">
<a *ngIf="item" [routerLink]="['/items', item?.id]">{{item?.handle}}</a>
<span *ngIf="version?.id === itemVersion?.id">*</span>
</span>
</td>
<td *ngIf="(hasEpersons$ | async)">
<span *ngVar="(version?.eperson | async)?.payload as eperson">
<a *ngIf="eperson" [href]="'mailto:' + eperson?.email">{{eperson?.name}}</a>
</span>
</td>
<td>{{version?.created}}</td>
<td>{{version?.summary}}</td>
</tr>
</tbody>
</table>
<div>*&nbsp;{{"item.version.history.selected" | translate}}</div>
</ds-pagination>
</div>
</div>
</div>

View File

@@ -0,0 +1,108 @@
import { Component, Input, OnInit } from '@angular/core';
import { Item } from '../../core/shared/item.model';
import { Version } from '../../core/shared/version.model';
import { RemoteData } from '../../core/data/remote-data';
import { Observable } from 'rxjs/internal/Observable';
import { VersionHistory } from '../../core/shared/version-history.model';
import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../core/shared/operators';
import { map, startWith, switchMap } from 'rxjs/operators';
import { combineLatest as observableCombineLatest } from 'rxjs';
import { PaginatedList } from '../../core/data/paginated-list';
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
import { BehaviorSubject } from 'rxjs/internal/BehaviorSubject';
import { VersionHistoryDataService } from '../../core/data/version-history-data.service';
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
@Component({
selector: 'ds-item-versions',
templateUrl: './item-versions.component.html'
})
/**
* Component listing all available versions of the history the provided item is a part of
*/
export class ItemVersionsComponent implements OnInit {
/**
* The item to display a version history for
*/
@Input() item: Item;
/**
* The item's version
*/
versionRD$: Observable<RemoteData<Version>>;
/**
* The item's full version history
*/
versionHistoryRD$: Observable<RemoteData<VersionHistory>>;
/**
* The version history's list of versions
*/
versionsRD$: Observable<RemoteData<PaginatedList<Version>>>;
/**
* Verify if the list of versions has at least one e-person to display
* Used to hide the "Editor" column when no e-persons are present to display
*/
hasEpersons$: Observable<boolean>;
/**
* The amount of versions to display per page
*/
pageSize = 10;
/**
* The page options to use for fetching the versions
* Start at page 1 and always use the set page size
*/
options = Object.assign(new PaginationComponentOptions(),{
id: 'item-versions-options',
currentPage: 1,
pageSize: this.pageSize
});
/**
* The current page being displayed
*/
currentPage$ = new BehaviorSubject<number>(1);
constructor(private versionHistoryService: VersionHistoryDataService) {
}
/**
* Initialize all observables
*/
ngOnInit(): void {
this.versionRD$ = this.item.version;
this.versionHistoryRD$ = this.versionRD$.pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload(),
switchMap((version: Version) => version.versionhistory)
);
const versionHistory$ = this.versionHistoryRD$.pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload(),
);
this.versionsRD$ = observableCombineLatest(versionHistory$, this.currentPage$).pipe(
switchMap(([versionHistory, page]: [VersionHistory, number]) =>
this.versionHistoryService.getVersions(versionHistory.id,
new PaginatedSearchOptions({pagination: Object.assign({}, this.options, { currentPage: page })})))
);
this.hasEpersons$ = this.versionsRD$.pipe(
getAllSucceededRemoteData(),
getRemoteDataPayload(),
map((versions: PaginatedList<Version>) => versions.page.filter((version: Version) => version.eperson !== undefined).length > 0),
startWith(false)
);
}
/**
* Update the current page
* @param page
*/
switchPage(page: number) {
this.currentPage$.next(page);
}
}

View File

@@ -3,6 +3,7 @@
<div *ngIf="itemRD?.payload as item">
<ds-view-tracker [object]="item"></ds-view-tracker>
<ds-listable-object-component-loader [object]="item" [viewMode]="viewMode"></ds-listable-object-component-loader>
<ds-item-versions class="mt-2" [item]="item"></ds-item-versions>
</div>
</div>
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.item' | translate}}"></ds-error>

View File

@@ -6,6 +6,7 @@ import { mapsTo, relationship } from '../builders/build-decorators';
import { Collection } from '../../shared/collection.model';
import { Relationship } from '../../shared/item-relationships/relationship.model';
import { Bundle } from '../../shared/bundle.model';
import { Version } from '../../shared/version.model';
/**
* Normalized model class for a DSpace Item
@@ -69,4 +70,11 @@ export class NormalizedItem extends NormalizedDSpaceObject<Item> {
@relationship(Relationship, true)
relationships: string[];
/**
* The version this item represents in its history
*/
@deserialize
@relationship(Version, false)
version: string;
}

View File

@@ -5,6 +5,7 @@ import { TypedObject } from '../object-cache.reducer';
import { NormalizedObject } from './normalized-object.model';
import { Item } from '../../shared/item.model';
import { VersionHistory } from '../../shared/version-history.model';
import { EPerson } from '../../eperson/models/eperson.model';
/**
* Normalized model class for a DSpace Version
@@ -49,4 +50,11 @@ export class NormalizedVersion extends NormalizedObject<Version> implements Type
@deserialize
@relationship(Item, false)
item: string;
/**
* The e-person who created this version
*/
@deserialize
@relationship(EPerson, false)
eperson: string;
}

View File

@@ -14,6 +14,9 @@ import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
import { FindListOptions } from './request.models';
import { Observable } from 'rxjs/internal/Observable';
/**
* Service responsible for handling requests related to the Version object
*/
@Injectable()
export class VersionDataService extends DataService<Version> {
protected linkPath = 'versions';

View File

@@ -11,12 +11,21 @@ import { HALEndpointService } from '../shared/hal-endpoint.service';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { HttpClient } from '@angular/common/http';
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
import { FindListOptions } from './request.models';
import { FindListOptions, GetRequest } from './request.models';
import { Observable } from 'rxjs/internal/Observable';
import { PaginatedSearchOptions } from '../../shared/search/paginated-search-options.model';
import { RemoteData } from './remote-data';
import { PaginatedList } from './paginated-list';
import { Version } from '../shared/version.model';
import { map, switchMap, take } from 'rxjs/operators';
/**
* Service responsible for handling requests related to the VersionHistory object
*/
@Injectable()
export class VersionHistoryDataService extends DataService<VersionHistory> {
protected linkPath = 'versionhistories';
protected versionsEndpoint = 'versions';
constructor(
protected requestService: RequestService,
@@ -37,4 +46,33 @@ export class VersionHistoryDataService extends DataService<VersionHistory> {
getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable<string> {
return this.halService.getEndpoint(this.linkPath);
}
/**
* Get the versions endpoint for a version history
* @param versionHistoryId
*/
getVersionsEndpoint(versionHistoryId: number): Observable<string> {
return this.getBrowseEndpoint().pipe(
switchMap((href: string) => this.halService.getEndpoint(this.versionsEndpoint, `${href}/${versionHistoryId}`))
);
}
/**
* Get a version history's versions using paginated search options
* @param versionHistoryId The version history's ID
* @param searchOptions The search options to use
*/
getVersions(versionHistoryId: number, searchOptions?: PaginatedSearchOptions): Observable<RemoteData<PaginatedList<Version>>> {
const hrefObs = this.getVersionsEndpoint(versionHistoryId).pipe(
map((href) => searchOptions ? searchOptions.toRestUrl(href) : href)
);
hrefObs.pipe(
take(1)
).subscribe((href) => {
const request = new GetRequest(this.requestService.generateRequestId(), href);
this.requestService.configure(request);
});
return this.rdbService.buildList<Version>(hrefObs);
}
}

View File

@@ -14,6 +14,7 @@ import { Bundle } from './bundle.model';
import { GenericConstructor } from './generic-constructor';
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
import { DEFAULT_ENTITY_TYPE } from '../../shared/metadata-representation/metadata-representation.decorator';
import { Version } from './version.model';
/**
* Class representing a DSpace Item
@@ -67,6 +68,11 @@ export class Item extends DSpaceObject {
relationships: Observable<RemoteData<PaginatedList<Relationship>>>;
/**
* The version this item represents in its history
*/
version: Observable<RemoteData<Version>>;
/**
* Retrieves the thumbnail of this item
* @returns {Observable<Bitstream>} the primaryBitstream of the 'THUMBNAIL' bundle

View File

@@ -7,6 +7,7 @@ import { Item } from './item.model';
import { RemoteData } from '../data/remote-data';
import { Observable } from 'rxjs/internal/Observable';
import { VersionHistory } from './version-history.model';
import { EPerson } from '../eperson/models/eperson.model';
/**
* Class representing a DSpace Version
@@ -52,6 +53,12 @@ export class Version extends ListableObject implements CacheableObject {
@excludeFromEquals
item: Observable<RemoteData<Item>>;
/**
* The e-person who created this version
*/
@excludeFromEquals
eperson: Observable<RemoteData<EPerson>>;
/**
* Method that returns as which type of object this object should be rendered
*/