mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge branch 'w2p-117287_fix-item-version-performance-issues_contribute-7.6' into w2p-117287_fix-item-version-performance-issues_contribute-7_x
# Conflicts: # src/app/item-page/versions/item-versions.component.html
This commit is contained in:
@@ -1,145 +1,149 @@
|
||||
<div *ngVar="(versionsRD$ | async)?.payload as versions">
|
||||
<div *ngVar="(versionRD$ | async)?.payload as itemVersion">
|
||||
<div class="mb-2" *ngIf="versions?.page?.length > 0 || displayWhenEmpty">
|
||||
<h2 *ngIf="displayTitle" class="h4">{{"item.version.history.head" | translate}}</h2>
|
||||
<ds-alert [type]="AlertTypeEnum.Info" *ngIf="itemVersion">
|
||||
{{ "item.version.history.selected.alert" | translate : {version: itemVersion.version} }}
|
||||
</ds-alert>
|
||||
<ds-pagination *ngIf="versions?.page?.length > 0"
|
||||
(paginationChange)="onPageChange()"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
[paginationOptions]="options"
|
||||
[collectionSize]="versions?.totalElements"
|
||||
[retainScrollPosition]="true">
|
||||
<table class="table table-striped table-bordered align-middle my-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{"item.version.history.table.version" | translate}}</th>
|
||||
<th scope="col" *ngIf="(showSubmitter() | 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" [id]="'version-row-' + version.id">
|
||||
<td class="version-row-element-version">
|
||||
<!-- Get the ID of the workspace/workflow item (`undefined` if they don't exist).
|
||||
Conditionals inside *ngVar are needed in order to avoid useless calls. -->
|
||||
<ng-container *ngVar="((hasDraftVersion$ | async) ? getWorkspaceId(version?.item) : undefined) as workspaceId$">
|
||||
<ng-container *ngVar=" ((workspaceId$ | async) ? undefined : getWorkflowId(version?.item)) as workflowId$">
|
||||
<div *ngIf="(versionsDTO$ | async) as versionsDTO; else noItemVersion" class="mb-2">
|
||||
<div *ngIf="(versionRD$ | async)?.payload as itemVersion">
|
||||
<h2 *ngIf="displayTitle" class="h4">{{ "item.version.history.head" | translate }}</h2>
|
||||
<ds-alert [type]="AlertTypeEnum.Info">
|
||||
{{ "item.version.history.selected.alert" | translate : { version: itemVersion.version } }}
|
||||
</ds-alert>
|
||||
<ds-pagination *ngIf="versionsDTO.versionDTOs.length > 0"
|
||||
(paginationChange)="onPageChange()"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="true"
|
||||
[paginationOptions]="options"
|
||||
[collectionSize]="versionsDTO.totalElements"
|
||||
[retainScrollPosition]="true">
|
||||
<table class="table table-striped table-bordered align-middle my-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{ "item.version.history.table.version" | translate }}</th>
|
||||
<th scope="col" *ngIf="(showSubmitter() | 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 versionDTO of versionsDTO.versionDTOs" [id]="'version-row-' + versionDTO.version.id">
|
||||
<td class="version-row-element-version">
|
||||
<!-- Get the ID of the workspace/workflow item (`undefined` if they don't exist).
|
||||
Conditionals inside *ngVar are needed in order to avoid useless calls. -->
|
||||
<ng-container
|
||||
*ngVar="((hasDraftVersion$ | async) ? getWorkspaceId(versionDTO.version.item) : undefined) as workspaceId$">
|
||||
<ng-container
|
||||
*ngVar=" ((workspaceId$ | async) ? undefined : getWorkflowId(versionDTO.version.item)) as workflowId$">
|
||||
|
||||
<div class="left-column">
|
||||
<div class="left-column">
|
||||
|
||||
<span *ngIf="(workspaceId$ | async) || (workflowId$ | async); then versionNumberWithoutLink else versionNumberWithLink"></span>
|
||||
<ng-template #versionNumberWithLink>
|
||||
<a [routerLink]="getVersionRoute(version.id)">{{version.version}}</a>
|
||||
</ng-template>
|
||||
<ng-template #versionNumberWithoutLink>
|
||||
{{version.version}}
|
||||
</ng-template>
|
||||
<span *ngIf="version?.id === itemVersion?.id">*</span>
|
||||
<span
|
||||
*ngIf="(workspaceId$ | async) || (workflowId$ | async); then versionNumberWithoutLink else versionNumberWithLink"></span>
|
||||
<ng-template #versionNumberWithLink>
|
||||
<a [routerLink]="getVersionRoute(versionDTO.version.id)">{{ versionDTO.version.version }}</a>
|
||||
</ng-template>
|
||||
<ng-template #versionNumberWithoutLink>
|
||||
{{ versionDTO.version.version }}
|
||||
</ng-template>
|
||||
<span *ngIf="versionDTO.version.id === itemVersion?.id">*</span>
|
||||
|
||||
<span *ngIf="workspaceId$ | async" class="text-light badge badge-primary ml-3">
|
||||
<span *ngIf="workspaceId$ | async" class="text-light badge badge-primary ml-3">
|
||||
{{ "item.version.history.table.workspaceItem" | translate }}
|
||||
</span>
|
||||
|
||||
<span *ngIf="workflowId$ | async" class="text-light badge badge-info ml-3">
|
||||
<span *ngIf="workflowId$ | async" class="text-light badge badge-info ml-3">
|
||||
{{ "item.version.history.table.workflowItem" | translate }}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right-column">
|
||||
<div class="right-column">
|
||||
|
||||
<div class="btn-group edit-field space-children-mr" *ngIf="displayActions">
|
||||
<!--EDIT WORKSPACE ITEM-->
|
||||
<button class="btn btn-outline-primary btn-sm version-row-element-edit"
|
||||
*ngIf="workspaceId$ | async"
|
||||
(click)="editWorkspaceItem(workspaceId$)"
|
||||
title="{{'item.version.history.table.action.editWorkspaceItem' | translate }}">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i>
|
||||
<div class="btn-group edit-field space-children-mr" *ngIf="displayActions">
|
||||
<!--EDIT WORKSPACE ITEM-->
|
||||
<button class="btn btn-outline-primary btn-sm version-row-element-edit"
|
||||
*ngIf="workspaceId$ | async"
|
||||
(click)="editWorkspaceItem(workspaceId$)"
|
||||
title="{{'item.version.history.table.action.editWorkspaceItem' | translate }}">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i>
|
||||
</button>
|
||||
<!--CREATE-->
|
||||
<ng-container *ngIf="canCreateVersion$ | async">
|
||||
<button class="btn btn-outline-primary btn-sm version-row-element-create"
|
||||
[disabled]="isAnyBeingEdited() || (hasDraftVersion$ | async)"
|
||||
(click)="createNewVersion(versionDTO.version)"
|
||||
title="{{createVersionTitle$ | async | translate }}">
|
||||
<i class="fas fa-code-branch fa-fw"></i>
|
||||
</button>
|
||||
<!--CREATE-->
|
||||
<ng-container *ngIf="canCreateVersion$ | async">
|
||||
<button class="btn btn-outline-primary btn-sm version-row-element-create"
|
||||
[disabled]="isAnyBeingEdited() || (hasDraftVersion$ | async)"
|
||||
(click)="createNewVersion(version)"
|
||||
title="{{createVersionTitle$ | async | translate }}">
|
||||
<i class="fas fa-code-branch fa-fw"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
<!--DELETE-->
|
||||
<ng-container *ngIf="canDeleteVersion$(version) | async">
|
||||
<button class="btn btn-sm version-row-element-delete"
|
||||
[ngClass]="isAnyBeingEdited() ? 'btn-outline-primary' : 'btn-outline-danger'"
|
||||
[disabled]="isAnyBeingEdited()"
|
||||
(click)="deleteVersion(version, version.id==itemVersion.id)"
|
||||
title="{{'item.version.history.table.action.deleteVersion' | translate}}">
|
||||
<i class="fas fa-trash fa-fw"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
<!--DELETE-->
|
||||
<ng-container *ngIf="versionDTO.canDeleteVersion">
|
||||
<button class="btn btn-sm version-row-element-delete"
|
||||
[ngClass]="isAnyBeingEdited() ? 'btn-outline-primary' : 'btn-outline-danger'"
|
||||
[disabled]="isAnyBeingEdited()"
|
||||
(click)="deleteVersion(versionDTO.version, versionDTO.version.id==itemVersion.id)"
|
||||
title="{{'item.version.history.table.action.deleteVersion' | translate}}">
|
||||
<i class="fas fa-trash fa-fw"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
</td>
|
||||
<td class="version-row-element-editor" *ngIf="(showSubmitter() | async)">
|
||||
{{version?.submitterName}}
|
||||
</td>
|
||||
<td class="version-row-element-date">
|
||||
{{version?.created | date : 'yyyy-MM-dd HH:mm:ss'}}
|
||||
</td>
|
||||
<td class="version-row-element-summary">
|
||||
<div class="float-left">
|
||||
<ng-container *ngIf="isThisBeingEdited(version); then editSummary else showSummary"></ng-container>
|
||||
<ng-template #showSummary>{{version?.summary}}</ng-template>
|
||||
<ng-template #editSummary>
|
||||
<input [attr.aria-label]="'item.version.history.table.action.editSummary' | translate"
|
||||
[(ngModel)]="versionBeingEditedSummary" (keyup.enter)="onSummarySubmit()"
|
||||
class="form-control" type="text"/>
|
||||
</ng-template>
|
||||
</div>
|
||||
</ng-container>
|
||||
</td>
|
||||
<td class="version-row-element-editor" *ngIf="(showSubmitter() | async)">
|
||||
{{ versionDTO.version.submitterName }}
|
||||
</td>
|
||||
<td class="version-row-element-date">
|
||||
{{ versionDTO.version.created | date : 'yyyy-MM-dd HH:mm:ss' }}
|
||||
</td>
|
||||
<td class="version-row-element-summary">
|
||||
<div class="float-left">
|
||||
<ng-container
|
||||
*ngIf="isThisBeingEdited(versionDTO.version); then editSummary else showSummary"></ng-container>
|
||||
<ng-template #showSummary>{{ versionDTO.version.summary }}</ng-template>
|
||||
<ng-template #editSummary>
|
||||
<input [attr.aria-label]="'item.version.history.table.action.editSummary' | translate"
|
||||
[(ngModel)]="versionBeingEditedSummary" (keyup.enter)="onSummarySubmit()"
|
||||
class="form-control" type="text"/>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<div class="float-right btn-group edit-field space-children-mr" *ngIf="displayActions">
|
||||
<!--DISCARD EDIT -->
|
||||
<ng-container *ngIf="(canEditVersion$(version) | async) && isThisBeingEdited(version)">
|
||||
<button class="btn btn-sm"
|
||||
[ngClass]="isThisBeingEdited(version) ? 'btn-outline-warning' : 'btn-outline-primary'"
|
||||
(click)="disableVersionEditing()"
|
||||
title="{{'item.version.history.table.action.discardSummary' | translate}}">
|
||||
<i class="fas fa-undo-alt fa-fw"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
<!--EDIT / SAVE-->
|
||||
<ng-container *ngIf="canEditVersion$(version) | async">
|
||||
<button class="btn btn-outline-primary btn-sm version-row-element-edit"
|
||||
*ngIf="!isThisBeingEdited(version)"
|
||||
[disabled]="isAnyBeingEdited()"
|
||||
(click)="enableVersionEditing(version)"
|
||||
title="{{'item.version.history.table.action.editSummary' | translate}}">
|
||||
<i class="fas fa-edit fa-fw"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-success btn-sm"
|
||||
*ngIf="isThisBeingEdited(version)"
|
||||
(click)="onSummarySubmit()"
|
||||
title="{{'item.version.history.table.action.saveSummary' | translate}}">
|
||||
<i class="fas fa-check fa-fw"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div>* {{"item.version.history.selected" | translate}}</div>
|
||||
</ds-pagination>
|
||||
<ds-alert *ngIf="!itemVersion || versions?.page?.length === 0" [content]="'item.version.history.empty'"
|
||||
[type]="AlertTypeEnum.Info"></ds-alert>
|
||||
</div>
|
||||
<div class="float-right btn-group edit-field space-children-mr" *ngIf="displayActions">
|
||||
<!--DISCARD EDIT -->
|
||||
<ng-container *ngIf="(versionDTO.canEditVersion | async) && isThisBeingEdited(versionDTO.version)">
|
||||
<button class="btn btn-sm"
|
||||
[ngClass]="isThisBeingEdited(versionDTO.version) ? 'btn-outline-warning' : 'btn-outline-primary'"
|
||||
(click)="disableVersionEditing()"
|
||||
title="{{'item.version.history.table.action.discardSummary' | translate}}">
|
||||
<i class="fas fa-undo-alt fa-fw"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
<!--EDIT / SAVE-->
|
||||
<ng-container *ngIf="versionDTO.canEditVersion | async">
|
||||
<button class="btn btn-outline-primary btn-sm version-row-element-edit"
|
||||
*ngIf="!isThisBeingEdited(versionDTO.version)"
|
||||
[disabled]="isAnyBeingEdited()"
|
||||
(click)="enableVersionEditing(versionDTO.version)"
|
||||
title="{{'item.version.history.table.action.editSummary' | translate}}">
|
||||
<i class="fas fa-edit fa-fw"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-success btn-sm"
|
||||
*ngIf="isThisBeingEdited(versionDTO.version)"
|
||||
(click)="onSummarySubmit()"
|
||||
title="{{'item.version.history.table.action.saveSummary' | translate}}">
|
||||
<i class="fas fa-check fa-fw"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div>* {{ "item.version.history.selected" | translate }}</div>
|
||||
</ds-pagination>
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #noItemVersion>
|
||||
<ds-alert *ngIf="displayWhenEmpty"
|
||||
[content]="'item.version.history.empty'"
|
||||
[type]="AlertTypeEnum.Info">
|
||||
</ds-alert>
|
||||
</ng-template>
|
||||
|
@@ -3,7 +3,6 @@ import { Item } from '../../core/shared/item.model';
|
||||
import { Version } from '../../core/shared/version.model';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import {
|
||||
BehaviorSubject,
|
||||
combineLatest,
|
||||
Observable,
|
||||
of,
|
||||
@@ -49,6 +48,17 @@ import { WorkspaceitemDataService } from '../../core/submission/workspaceitem-da
|
||||
import { WorkflowItemDataService } from '../../core/submission/workflowitem-data.service';
|
||||
import { ConfigurationDataService } from '../../core/data/configuration-data.service';
|
||||
|
||||
interface VersionsDTO {
|
||||
totalElements: number;
|
||||
versionDTOs: VersionDTO[];
|
||||
}
|
||||
|
||||
interface VersionDTO {
|
||||
version: Version;
|
||||
canEditVersion: Observable<boolean>;
|
||||
canDeleteVersion: Observable<boolean>;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-versions',
|
||||
templateUrl: './item-versions.component.html',
|
||||
@@ -109,16 +119,15 @@ export class ItemVersionsComponent implements OnDestroy, OnInit {
|
||||
versionHistory$: Observable<VersionHistory>;
|
||||
|
||||
/**
|
||||
* The version history's list of versions
|
||||
* The version history information that is used to render the HTML
|
||||
*/
|
||||
versionsRD$: BehaviorSubject<RemoteData<PaginatedList<Version>>> = new BehaviorSubject<RemoteData<PaginatedList<Version>>>(null);
|
||||
versionsDTO$: Observable<VersionsDTO>;
|
||||
|
||||
/**
|
||||
* 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>;
|
||||
|
||||
/**
|
||||
* Verify if there is an inprogress submission in the version history
|
||||
* Used to disable the "Create version" button
|
||||
@@ -421,16 +430,23 @@ export class ItemVersionsComponent implements OnDestroy, OnInit {
|
||||
*/
|
||||
getAllVersions(versionHistory$: Observable<VersionHistory>): void {
|
||||
const currentPagination = this.paginationService.getCurrentPagination(this.options.id, this.options);
|
||||
combineLatest([versionHistory$, currentPagination]).pipe(
|
||||
this.versionsDTO$ = combineLatest([versionHistory$, currentPagination]).pipe(
|
||||
switchMap(([versionHistory, options]: [VersionHistory, PaginationComponentOptions]) => {
|
||||
return this.versionHistoryService.getVersions(versionHistory.id,
|
||||
new PaginatedSearchOptions({pagination: Object.assign({}, options, {currentPage: options.currentPage})}),
|
||||
false, true, followLink('item'), followLink('eperson'));
|
||||
}),
|
||||
getFirstCompletedRemoteData(),
|
||||
).subscribe((res: RemoteData<PaginatedList<Version>>) => {
|
||||
this.versionsRD$.next(res);
|
||||
});
|
||||
getRemoteDataPayload(),
|
||||
map((versions: PaginatedList<Version>) => ({
|
||||
totalElements: versions.totalElements,
|
||||
versionDTOs: (versions?.page ?? []).map((version: Version) => ({
|
||||
version: version,
|
||||
canEditVersion: this.canEditVersion$(version),
|
||||
canDeleteVersion: this.canDeleteVersion$(version),
|
||||
})),
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,16 +525,12 @@ export class ItemVersionsComponent implements OnDestroy, OnInit {
|
||||
);
|
||||
|
||||
this.getAllVersions(this.versionHistory$);
|
||||
this.hasEpersons$ = this.versionsRD$.pipe(
|
||||
getAllSucceededRemoteData(),
|
||||
getRemoteDataPayload(),
|
||||
hasValueOperator(),
|
||||
map((versions: PaginatedList<Version>) => versions.page.filter((version: Version) => version.eperson !== undefined).length > 0),
|
||||
this.hasEpersons$ = this.versionsDTO$.pipe(
|
||||
map((versionsDTO: VersionsDTO) => versionsDTO.versionDTOs.filter((versionDTO: VersionDTO) => versionDTO.version.eperson !== undefined).length > 0),
|
||||
startWith(false)
|
||||
);
|
||||
this.itemPageRoutes$ = this.versionsRD$.pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
switchMap((versions) => combineLatest(versions.page.map((version) => version.item.pipe(getAllSucceededRemoteDataPayload())))),
|
||||
this.itemPageRoutes$ = this.versionsDTO$.pipe(
|
||||
switchMap((versionsDTO: VersionsDTO) => combineLatest(versionsDTO.versionDTOs.map((versionDTO: VersionDTO) => versionDTO.version.item.pipe(getAllSucceededRemoteDataPayload())))),
|
||||
map((versions) => {
|
||||
const itemPageRoutes = {};
|
||||
versions.forEach((item) => itemPageRoutes[item.uuid] = getItemPageRoute(item));
|
||||
|
Reference in New Issue
Block a user