mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
[CST-4499] Version history (WIP) - Version page added (redirecting to item's page)
This commit is contained in:
@@ -34,5 +34,14 @@ export function getEntityEditRoute(entityType: string, itemId: string) {
|
||||
return new URLCombiner(getEntityPageRoute(entityType, itemId), ITEM_EDIT_PATH).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the route to an item's version
|
||||
* @param versionId the ID of the version for which the route will be retrieved
|
||||
*/
|
||||
export function getItemVersionRoute(versionId: string) {
|
||||
return new URLCombiner(getItemModuleRoute(), ITEM_VERSION_PATH, versionId).toString();
|
||||
}
|
||||
|
||||
export const ITEM_EDIT_PATH = 'edit';
|
||||
export const ITEM_VERSION_PATH = 'version';
|
||||
export const UPLOAD_BITSTREAM_PATH = 'bitstreams/new';
|
||||
|
@@ -3,6 +3,7 @@ import { RouterModule } from '@angular/router';
|
||||
import { ItemPageResolver } from './item-page.resolver';
|
||||
import { AuthenticatedGuard } from '../core/auth/authenticated.guard';
|
||||
import { ItemBreadcrumbResolver } from '../core/breadcrumbs/item-breadcrumb.resolver';
|
||||
import { VersionResolver } from './version-page/version.resolver';
|
||||
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
|
||||
import { LinkService } from '../core/cache/builders/link.service';
|
||||
import { UploadBitstreamComponent } from './bitstreams/upload/upload-bitstream.component';
|
||||
@@ -12,6 +13,7 @@ import { MenuItemType } from '../shared/menu/initial-menus-state';
|
||||
import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
|
||||
import { ThemedItemPageComponent } from './simple/themed-item-page.component';
|
||||
import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component';
|
||||
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -58,6 +60,18 @@ import { ThemedFullItemPageComponent } from './full/themed-full-item-page.compon
|
||||
}],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'version',
|
||||
children: [
|
||||
{
|
||||
path: ':id',
|
||||
component: VersionPageComponent,
|
||||
resolve: {
|
||||
dso: VersionResolver,
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
])
|
||||
],
|
||||
@@ -67,6 +81,7 @@ import { ThemedFullItemPageComponent } from './full/themed-full-item-page.compon
|
||||
DSOBreadcrumbsService,
|
||||
LinkService,
|
||||
ItemPageAdministratorGuard,
|
||||
VersionResolver,
|
||||
]
|
||||
|
||||
})
|
||||
|
@@ -31,6 +31,7 @@ import { MediaViewerComponent } from './media-viewer/media-viewer.component';
|
||||
import { MediaViewerVideoComponent } from './media-viewer/media-viewer-video/media-viewer-video.component';
|
||||
import { MediaViewerImageComponent } from './media-viewer/media-viewer-image/media-viewer-image.component';
|
||||
import { NgxGalleryModule } from '@kolkov/ngx-gallery';
|
||||
import { VersionPageComponent } from './version-page/version-page/version-page.component';
|
||||
|
||||
const ENTRY_COMPONENTS = [
|
||||
// put only entry components that use custom decorator
|
||||
@@ -60,7 +61,8 @@ const DECLARATIONS = [
|
||||
AbstractIncrementalListComponent,
|
||||
MediaViewerComponent,
|
||||
MediaViewerVideoComponent,
|
||||
MediaViewerImageComponent
|
||||
MediaViewerImageComponent,
|
||||
VersionPageComponent,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
@@ -72,7 +74,7 @@ const DECLARATIONS = [
|
||||
StatisticsModule.forRoot(),
|
||||
JournalEntitiesModule.withEntryComponents(),
|
||||
ResearchEntitiesModule.withEntryComponents(),
|
||||
NgxGalleryModule,
|
||||
NgxGalleryModule,
|
||||
],
|
||||
declarations: [
|
||||
...DECLARATIONS
|
||||
|
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { VersionPageComponent } from './version-page.component';
|
||||
|
||||
describe('VersionPageComponent', () => {
|
||||
let component: VersionPageComponent;
|
||||
let fixture: ComponentFixture<VersionPageComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ VersionPageComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(VersionPageComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@@ -0,0 +1,61 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AuthService } from '../../../core/auth/auth.service';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import {
|
||||
getFirstCompletedRemoteData,
|
||||
getFirstSucceededRemoteDataPayload,
|
||||
redirectOn4xx
|
||||
} from '../../../core/shared/operators';
|
||||
import { VersionDataService } from '../../../core/data/version-data.service';
|
||||
import { Version } from '../../../core/shared/version.model';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
import { getItemPageRoute } from '../../item-page-routing-paths';
|
||||
import { getPageNotFoundRoute } from '../../../app-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-version-page',
|
||||
templateUrl: './version-page.component.html',
|
||||
styleUrls: ['./version-page.component.scss']
|
||||
})
|
||||
export class VersionPageComponent implements OnInit {
|
||||
|
||||
versionRD$: Observable<RemoteData<Version>>;
|
||||
itemRD$: Observable<RemoteData<Item>>;
|
||||
|
||||
constructor(
|
||||
protected route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private versionService: VersionDataService,
|
||||
private authService: AuthService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
/* Retrieve version from resolver or redirect on 4xx */
|
||||
this.versionRD$ = this.route.data.pipe(
|
||||
map((data) => data.dso as RemoteData<Version>),
|
||||
redirectOn4xx(this.router, this.authService),
|
||||
);
|
||||
|
||||
/* Retrieve item from version and reroute to item's page or handle missing item */
|
||||
this.versionRD$.pipe(
|
||||
getFirstSucceededRemoteDataPayload(),
|
||||
switchMap((version) => version.item),
|
||||
redirectOn4xx(this.router, this.authService),
|
||||
getFirstCompletedRemoteData(),
|
||||
).subscribe((itemRD) => {
|
||||
console.log(JSON.stringify(itemRD));
|
||||
if (itemRD.hasNoContent) {
|
||||
this.router.navigateByUrl(getPageNotFoundRoute(), { skipLocationChange: true });
|
||||
} else {
|
||||
const itemUrl = getItemPageRoute(itemRD.payload);
|
||||
this.router.navigateByUrl(itemUrl);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
54
src/app/item-page/version-page/version.resolver.ts
Normal file
54
src/app/item-page/version-page/version.resolver.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
|
||||
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { ResolvedAction } from '../../core/resolving/resolver.actions';
|
||||
import { Version } from '../../core/shared/version.model';
|
||||
import { VersionDataService } from '../../core/data/version-data.service';
|
||||
|
||||
/**
|
||||
* The self links defined in this list are expected to be requested somewhere in the near future
|
||||
* Requesting them as embeds will limit the number of requests
|
||||
*/
|
||||
export const VERSION_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig<Version>[] = [
|
||||
followLink('item'),
|
||||
];
|
||||
|
||||
/**
|
||||
* This class represents a resolver that requests a specific version before the route is activated
|
||||
*/
|
||||
@Injectable()
|
||||
export class VersionResolver implements Resolve<RemoteData<Version>> {
|
||||
constructor(
|
||||
protected versionService: VersionDataService,
|
||||
protected store: Store<any>,
|
||||
protected router: Router
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for resolving a version based on the parameters in the current route
|
||||
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
|
||||
* @param {RouterStateSnapshot} state The current RouterStateSnapshot
|
||||
* @returns Observable<<RemoteData<Item>> Emits the found item based on the parameters in the current route,
|
||||
* or an error if something went wrong
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<RemoteData<Version>> {
|
||||
const versionRD$ = this.versionService.findById(route.params.id,
|
||||
true,
|
||||
false,
|
||||
...VERSION_PAGE_LINKS_TO_FOLLOW
|
||||
).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
);
|
||||
|
||||
versionRD$.subscribe((versionRD: RemoteData<Version>) => {
|
||||
this.store.dispatch(new ResolvedAction(state.url, versionRD.payload));
|
||||
});
|
||||
|
||||
return versionRD$;
|
||||
}
|
||||
}
|
@@ -24,13 +24,18 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let version of versions?.page" [id]="'version-row-' + version.id">
|
||||
<td class="version-row-element-version">{{version?.version}}</td>
|
||||
<td class="version-row-element-version">
|
||||
<a [routerLink]="getVersionRoute(version.id)">{{version.version}}</a>
|
||||
<span *ngIf="version?.id === itemVersion?.id">*</span>
|
||||
</td>
|
||||
<td *ngIf="(hasEpersons$ | async)" class="version-row-element-editor">
|
||||
<span *ngVar="(version?.eperson | async)?.payload as eperson">
|
||||
<a *ngIf="eperson" [href]="'mailto:' + eperson?.email">{{eperson?.name}}</a>
|
||||
</span>
|
||||
</td>
|
||||
<td class="version-row-element-date">{{version?.created | date : 'yyyy-MM-dd HH:mm:ss'}}</td>
|
||||
<td class="version-row-element-date">
|
||||
{{version?.created | date : 'yyyy-MM-dd HH:mm:ss'}}
|
||||
</td>
|
||||
<td class="version-row-element-summary">
|
||||
<ng-container *ngIf="isThisBeingEdited(version); then editSummary else showSummary"></ng-container>
|
||||
<ng-template #showSummary>{{version?.summary}}</ng-template>
|
||||
|
@@ -21,7 +21,7 @@ import { AlertType } from '../../alert/aletr-type';
|
||||
import { followLink } from '../../utils/follow-link-config.model';
|
||||
import { hasValue, hasValueOperator } from '../../empty.util';
|
||||
import { PaginationService } from '../../../core/pagination/pagination.service';
|
||||
import { getItemPageRoute } from '../../../item-page/item-page-routing-paths';
|
||||
import { getItemPageRoute, getItemVersionRoute } from '../../../item-page/item-page-routing-paths';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ItemVersionsSummaryModalComponent } from './item-versions-summary-modal/item-versions-summary-modal.component';
|
||||
@@ -192,6 +192,14 @@ export class ItemVersionsComponent implements OnInit {
|
||||
this.versionBeingEditedId = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the route to the specified version
|
||||
* @param versionId the ID of the version for which the route will be retrieved
|
||||
*/
|
||||
getVersionRoute(versionId: string) {
|
||||
return getItemVersionRoute(versionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies changes to version currently being edited
|
||||
*/
|
||||
@@ -250,6 +258,7 @@ export class ItemVersionsComponent implements OnInit {
|
||||
}
|
||||
);
|
||||
});
|
||||
// TODO non usare subscribe annidate
|
||||
/*version.item.pipe(
|
||||
getFirstSucceededRemoteDataPayload(),
|
||||
switchMap((getItemRes) => this.itemService.delete(getItemRes.id))
|
||||
|
Reference in New Issue
Block a user