mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge pull request #1001 from atmire/Item-page-redirects
DS-4283: (Google Scholar) Provide Entity Type Label/Name as part of URL path
This commit is contained in:
@@ -7,7 +7,8 @@ import {
|
||||
of as observableOf,
|
||||
Subscription,
|
||||
BehaviorSubject,
|
||||
combineLatest as observableCombineLatest, ObservedValueOf,
|
||||
combineLatest as observableCombineLatest,
|
||||
ObservedValueOf,
|
||||
} from 'rxjs';
|
||||
import { map, mergeMap, switchMap, take } from 'rxjs/operators';
|
||||
import { buildPaginatedList, PaginatedList } from '../../../../../core/data/paginated-list.model';
|
||||
@@ -19,7 +20,8 @@ import { Group } from '../../../../../core/eperson/models/group.model';
|
||||
import {
|
||||
getRemoteDataPayload,
|
||||
getFirstSucceededRemoteData,
|
||||
getFirstCompletedRemoteData, getAllCompletedRemoteData
|
||||
getFirstCompletedRemoteData,
|
||||
getAllCompletedRemoteData
|
||||
} from '../../../../../core/shared/operators';
|
||||
import { NotificationsService } from '../../../../../shared/notifications/notifications.service';
|
||||
import { PaginationComponentOptions } from '../../../../../shared/pagination/pagination-component-options.model';
|
||||
|
@@ -56,19 +56,19 @@ describe('ItemAdminSearchResultActionsComponent', () => {
|
||||
it('should render an edit button with the correct link', () => {
|
||||
const button = fixture.debugElement.query(By.css('a.edit-link'));
|
||||
const link = button.nativeElement.href;
|
||||
expect(link).toContain(getItemEditRoute(id));
|
||||
expect(link).toContain(getItemEditRoute(item));
|
||||
});
|
||||
|
||||
it('should render a delete button with the correct link', () => {
|
||||
const button = fixture.debugElement.query(By.css('a.delete-link'));
|
||||
const link = button.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_DELETE_PATH).toString());
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(item), ITEM_EDIT_DELETE_PATH).toString());
|
||||
});
|
||||
|
||||
it('should render a move button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.move-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_MOVE_PATH).toString());
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(item), ITEM_EDIT_MOVE_PATH).toString());
|
||||
});
|
||||
|
||||
describe('when the item is not withdrawn', () => {
|
||||
@@ -80,7 +80,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
|
||||
it('should render a withdraw button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.withdraw-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_WITHDRAW_PATH).toString());
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(item), ITEM_EDIT_WITHDRAW_PATH).toString());
|
||||
});
|
||||
|
||||
it('should not render a reinstate button with the correct link', () => {
|
||||
@@ -103,7 +103,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
|
||||
it('should render a reinstate button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.reinstate-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_REINSTATE_PATH).toString());
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(item), ITEM_EDIT_REINSTATE_PATH).toString());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -116,7 +116,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
|
||||
it('should render a make private button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.private-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_PRIVATE_PATH).toString());
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(item), ITEM_EDIT_PRIVATE_PATH).toString());
|
||||
});
|
||||
|
||||
it('should not render a make public button with the correct link', () => {
|
||||
@@ -139,7 +139,7 @@ describe('ItemAdminSearchResultActionsComponent', () => {
|
||||
it('should render a make private button with the correct link', () => {
|
||||
const a = fixture.debugElement.query(By.css('a.public-link'));
|
||||
const link = a.nativeElement.href;
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(id), ITEM_EDIT_PUBLIC_PATH).toString());
|
||||
expect(link).toContain(new URLCombiner(getItemEditRoute(item), ITEM_EDIT_PUBLIC_PATH).toString());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -34,7 +34,7 @@ export class ItemAdminSearchResultActionsComponent {
|
||||
* Returns the path to the edit page of this item
|
||||
*/
|
||||
getEditRoute(): string {
|
||||
return getItemEditRoute(this.item.uuid);
|
||||
return getItemEditRoute(this.item);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -18,10 +18,14 @@ import { hasValue } from '../../shared/empty.util';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { FileSizePipe } from '../../shared/utils/file-size-pipe';
|
||||
import { VarDirective } from '../../shared/utils/var.directive';
|
||||
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import {
|
||||
createSuccessfulRemoteDataObject,
|
||||
createSuccessfulRemoteDataObject$
|
||||
} from '../../shared/remote-data.utils';
|
||||
import { RouterStub } from '../../shared/testing/router.stub';
|
||||
import { getItemEditRoute } from '../../+item-page/item-page-routing-paths';
|
||||
import { getEntityEditRoute, getItemEditRoute } from '../../+item-page/item-page-routing-paths';
|
||||
import { createPaginatedList } from '../../shared/testing/utils.test';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
const infoNotification: INotification = new Notification('id', NotificationType.Info, 'info');
|
||||
const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning');
|
||||
@@ -109,9 +113,9 @@ describe('EditBitstreamPageComponent', () => {
|
||||
self: 'bitstream-selflink'
|
||||
},
|
||||
bundle: createSuccessfulRemoteDataObject$({
|
||||
item: createSuccessfulRemoteDataObject$({
|
||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||
uuid: 'some-uuid'
|
||||
})
|
||||
}))
|
||||
})
|
||||
});
|
||||
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
||||
@@ -237,14 +241,14 @@ describe('EditBitstreamPageComponent', () => {
|
||||
it('should redirect to the item edit page on the bitstreams tab with the itemId from the component', () => {
|
||||
comp.itemId = 'some-uuid1';
|
||||
comp.navigateToItemEditBitstreams();
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute('some-uuid1'), 'bitstreams']);
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getEntityEditRoute(null, 'some-uuid1'), 'bitstreams']);
|
||||
});
|
||||
});
|
||||
describe('when navigateToItemEditBitstreams is called, and the component does not have an itemId', () => {
|
||||
it('should redirect to the item edit page on the bitstreams tab with the itemId from the bundle links ', () => {
|
||||
comp.itemId = undefined;
|
||||
comp.navigateToItemEditBitstreams();
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute('some-uuid'), 'bitstreams']);
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getEntityEditRoute(null, 'some-uuid'), 'bitstreams']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -33,9 +33,8 @@ import { Metadata } from '../../core/shared/metadata.utils';
|
||||
import { Location } from '@angular/common';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../core/data/paginated-list.model';
|
||||
import { getItemEditRoute } from '../../+item-page/item-page-routing-paths';
|
||||
import { getEntityEditRoute, getItemEditRoute } from '../../+item-page/item-page-routing-paths';
|
||||
import { Bundle } from '../../core/shared/bundle.model';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-edit-bitstream-page',
|
||||
@@ -264,9 +263,17 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* The ID of the item the bitstream originates from
|
||||
* Taken from the current query parameters when present
|
||||
* This will determine the route of the item edit page to return to
|
||||
*/
|
||||
itemId: string;
|
||||
|
||||
/**
|
||||
* The entity type of the item the bitstream originates from
|
||||
* Taken from the current query parameters when present
|
||||
* This will determine the route of the item edit page to return to
|
||||
*/
|
||||
entityType: string;
|
||||
|
||||
/**
|
||||
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||
* @type {Array}
|
||||
@@ -293,6 +300,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
this.formGroup = this.formService.createFormGroup(this.formModel);
|
||||
|
||||
this.itemId = this.route.snapshot.queryParams.itemId;
|
||||
this.entityType = this.route.snapshot.queryParams.entityType;
|
||||
this.bitstreamRD$ = this.route.data.pipe(map((data) => data.bitstream));
|
||||
this.bitstreamFormatsRD$ = this.bitstreamFormatService.findAll(this.findAllOptions);
|
||||
|
||||
@@ -499,10 +507,10 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
navigateToItemEditBitstreams() {
|
||||
if (hasValue(this.itemId)) {
|
||||
this.router.navigate([getItemEditRoute(this.itemId), 'bitstreams']);
|
||||
this.router.navigate([getEntityEditRoute(this.entityType, this.itemId), 'bitstreams']);
|
||||
} else {
|
||||
this.bitstream.bundle.pipe(getFirstSucceededRemoteDataPayload(),
|
||||
mergeMap((bundle: Bundle) => bundle.item.pipe(getFirstSucceededRemoteDataPayload(), map((item: Item) => item.uuid))))
|
||||
mergeMap((bundle: Bundle) => bundle.item.pipe(getFirstSucceededRemoteDataPayload())))
|
||||
.subscribe((item) => {
|
||||
this.router.navigate(([getItemEditRoute(item), 'bitstreams']));
|
||||
});
|
||||
|
@@ -35,7 +35,7 @@
|
||||
</ds-comcol-page-content>
|
||||
</header>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'collections'" [dso]="collection" [tooltipMsg]="'collection.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="collectionPageRoute$ | async" [dso]="collection" [tooltipMsg]="'collection.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<section class="comcol-page-browse-section">
|
||||
|
@@ -15,13 +15,19 @@ import { Bitstream } from '../core/shared/bitstream.model';
|
||||
import { Collection } from '../core/shared/collection.model';
|
||||
import { DSpaceObjectType } from '../core/shared/dspace-object-type.model';
|
||||
import { Item } from '../core/shared/item.model';
|
||||
import { getFirstSucceededRemoteData, redirectOn4xx, toDSpaceObjectListRD } from '../core/shared/operators';
|
||||
import {
|
||||
getAllSucceededRemoteDataPayload,
|
||||
getFirstSucceededRemoteData,
|
||||
redirectOn4xx,
|
||||
toDSpaceObjectListRD
|
||||
} from '../core/shared/operators';
|
||||
|
||||
import { fadeIn, fadeInOut } from '../shared/animations/fade';
|
||||
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||
import { AuthService } from '../core/auth/auth.service';
|
||||
import {PaginationChangeEvent} from '../shared/pagination/paginationChangeEvent.interface';
|
||||
import { getCollectionPageRoute } from './collection-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-collection-page',
|
||||
@@ -44,6 +50,11 @@ export class CollectionPageComponent implements OnInit {
|
||||
sortConfig: SortOptions
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Route to the community page
|
||||
*/
|
||||
collectionPageRoute$: Observable<string>;
|
||||
|
||||
constructor(
|
||||
private collectionDataService: CollectionDataService,
|
||||
private searchService: SearchService,
|
||||
@@ -94,6 +105,11 @@ export class CollectionPageComponent implements OnInit {
|
||||
)
|
||||
);
|
||||
|
||||
this.collectionPageRoute$ = this.collectionRD$.pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map((collection) => getCollectionPageRoute(collection.id))
|
||||
);
|
||||
|
||||
this.route.queryParams.pipe(take(1)).subscribe((params) => {
|
||||
this.metadata.processRemoteData(this.collectionRD$);
|
||||
});
|
||||
|
@@ -21,7 +21,7 @@
|
||||
</ds-comcol-page-content>
|
||||
</header>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'communities'" [dso]="communityPayload" [tooltipMsg]="'community.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="communityPageRoute$ | async" [dso]="communityPayload" [tooltipMsg]="'community.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<section class="comcol-page-browse-section">
|
||||
|
@@ -13,8 +13,9 @@ import { MetadataService } from '../core/metadata/metadata.service';
|
||||
|
||||
import { fadeInOut } from '../shared/animations/fade';
|
||||
import { hasValue } from '../shared/empty.util';
|
||||
import { redirectOn4xx } from '../core/shared/operators';
|
||||
import { getAllSucceededRemoteDataPayload, redirectOn4xx } from '../core/shared/operators';
|
||||
import { AuthService } from '../core/auth/auth.service';
|
||||
import { getCommunityPageRoute } from './community-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-community-page',
|
||||
@@ -36,6 +37,12 @@ export class CommunityPageComponent implements OnInit {
|
||||
* The logo of this community
|
||||
*/
|
||||
logoRD$: Observable<RemoteData<Bitstream>>;
|
||||
|
||||
/**
|
||||
* Route to the community page
|
||||
*/
|
||||
communityPageRoute$: Observable<string>;
|
||||
|
||||
constructor(
|
||||
private communityDataService: CommunityDataService,
|
||||
private metadata: MetadataService,
|
||||
@@ -55,6 +62,10 @@ export class CommunityPageComponent implements OnInit {
|
||||
map((rd: RemoteData<Community>) => rd.payload),
|
||||
filter((community: Community) => hasValue(community)),
|
||||
mergeMap((community: Community) => community.logo));
|
||||
this.communityPageRoute$ = this.communityRD$.pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map((community) => getCommunityPageRoute(community.id))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ import { getFirstSucceededRemoteDataPayload } from '../../../core/shared/operato
|
||||
import { UploaderComponent } from '../../../shared/uploader/uploader.component';
|
||||
import { RequestService } from '../../../core/data/request.service';
|
||||
import { getBitstreamModuleRoute } from '../../../app-routing-paths';
|
||||
import { getItemEditRoute } from '../../item-page-routing-paths';
|
||||
import { getEntityEditRoute } from '../../item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-upload-bitstream',
|
||||
@@ -37,6 +37,12 @@ export class UploadBitstreamComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
itemId: string;
|
||||
|
||||
/**
|
||||
* The entity type of the item
|
||||
* This is fetched from the current URL and will determine the item's page route
|
||||
*/
|
||||
entityType: string;
|
||||
|
||||
/**
|
||||
* The item to upload a bitstream to
|
||||
*/
|
||||
@@ -100,6 +106,7 @@ export class UploadBitstreamComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.itemId = this.route.snapshot.params.id;
|
||||
this.entityType = this.route.snapshot.params['entity-type'];
|
||||
this.itemRD$ = this.route.data.pipe(map((data) => data.dso));
|
||||
this.bundlesRD$ = this.itemRD$.pipe(
|
||||
switchMap((itemRD: RemoteData<Item>) => itemRD.payload.bundles)
|
||||
@@ -167,7 +174,7 @@ export class UploadBitstreamComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
// Bring over the item ID as a query parameter
|
||||
const queryParams = { itemId: this.itemId };
|
||||
const queryParams = { itemId: this.itemId, entityType: this.entityType };
|
||||
this.router.navigate([getBitstreamModuleRoute(), bitstream.id, 'edit'], { queryParams: queryParams });
|
||||
}
|
||||
|
||||
@@ -193,7 +200,7 @@ export class UploadBitstreamComponent implements OnInit, OnDestroy {
|
||||
* When cancel is clicked, navigate back to the item's edit bitstreams page
|
||||
*/
|
||||
onCancel() {
|
||||
this.router.navigate([getItemEditRoute(this.itemId), 'bitstreams']);
|
||||
this.router.navigate([getEntityEditRoute(this.entityType, this.itemId), 'bitstreams']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -14,6 +14,7 @@ import { first, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { AbstractTrackableComponent } from '../../../shared/trackable/abstract-trackable.component';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
import { getItemPageRoute } from '../../item-page-routing-paths';
|
||||
import { ITEM_PAGE_LINKS_TO_FOLLOW } from '../../item-page.resolver';
|
||||
import { getAllSucceededRemoteData } from '../../../core/shared/operators';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
@@ -36,6 +37,11 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
||||
*/
|
||||
updates$: Observable<FieldUpdates>;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
/**
|
||||
* A subscription that checks when the item is deleted in cache and reloads the item by sending a new request
|
||||
* This is used to update the item in cache after bitstreams are deleted
|
||||
@@ -69,6 +75,7 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl
|
||||
getAllSucceededRemoteData()
|
||||
).subscribe((rd: RemoteData<Item>) => {
|
||||
this.item = rd.payload;
|
||||
this.itemPageRoute = getItemPageRoute(this.item);
|
||||
this.postItemInit();
|
||||
this.initializeUpdates();
|
||||
});
|
||||
|
@@ -55,6 +55,6 @@ export class EditItemPageComponent implements OnInit {
|
||||
* @param item The item for which the url is requested
|
||||
*/
|
||||
getItemPage(item: Item): string {
|
||||
return getItemPageRoute(item.id);
|
||||
return getItemPageRoute(item);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<div class="item-bitstreams" *ngVar="(bundles$ | async) as bundles">
|
||||
<div class="button-row top d-flex mt-2">
|
||||
<button class="mr-auto btn btn-success"
|
||||
[routerLink]="['/items/', item.id, 'bitstreams', 'new']"><i
|
||||
[routerLink]="[itemPageRoute, 'bitstreams', 'new']"><i
|
||||
class="fas fa-upload"></i>
|
||||
<span class="d-none d-sm-inline"> {{"item.edit.bitstreams.upload-button" | translate}}</span>
|
||||
</button>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<div class="{{columnSizes.columns[3].buildClasses()}} text-center row-element">
|
||||
<div class="btn-group bundle-action-buttons">
|
||||
<button [routerLink]="['/items/', item.id, 'bitstreams', 'new']"
|
||||
<button [routerLink]="[itemPageRoute, 'bitstreams', 'new']"
|
||||
[queryParams]="{bundle: bundle.id}"
|
||||
class="btn btn-outline-success btn-sm"
|
||||
title="{{'item.edit.bitstreams.bundle.edit.buttons.upload' | translate}}">
|
||||
|
@@ -3,6 +3,7 @@ import { Bundle } from '../../../../core/shared/bundle.model';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
import { ResponsiveColumnSizes } from '../../../../shared/responsive-table-sizes/responsive-column-sizes';
|
||||
import { ResponsiveTableSizes } from '../../../../shared/responsive-table-sizes/responsive-table-sizes';
|
||||
import { getItemPageRoute } from '../../../item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-edit-bitstream-bundle',
|
||||
@@ -49,11 +50,17 @@ export class ItemEditBitstreamBundleComponent implements OnInit {
|
||||
*/
|
||||
bundleNameColumn: ResponsiveColumnSizes;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
constructor(private viewContainerRef: ViewContainerRef) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.bundleNameColumn = this.columnSizes.combineColumns(0, 2);
|
||||
this.viewContainerRef.createEmbeddedView(this.bundleView);
|
||||
this.itemPageRoute = getItemPageRoute(this.item);
|
||||
}
|
||||
}
|
||||
|
@@ -55,6 +55,7 @@ describe('ItemCollectionMapperComponent', () => {
|
||||
const mockCollection = Object.assign(new Collection(), { id: 'collection1' });
|
||||
const mockItem: Item = Object.assign(new Item(), {
|
||||
id: '932c7d50-d85a-44cb-b9dc-b427b12877bd',
|
||||
uuid: '932c7d50-d85a-44cb-b9dc-b427b12877bd',
|
||||
name: 'test-item'
|
||||
});
|
||||
const mockItemRD: RemoteData<Item> = createSuccessfulRemoteDataObject(mockItem);
|
||||
@@ -212,7 +213,7 @@ describe('ItemCollectionMapperComponent', () => {
|
||||
});
|
||||
|
||||
it('should navigate to the item page', () => {
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/items/', mockItem.id]);
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/items/' + mockItem.uuid]);
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -26,6 +26,7 @@ import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-
|
||||
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
||||
import { SearchService } from '../../../core/shared/search/search.service';
|
||||
import { NoContent } from '../../../core/shared/NoContent.model';
|
||||
import { getItemPageRoute } from '../../item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-collection-mapper',
|
||||
@@ -312,7 +313,7 @@ export class ItemCollectionMapperComponent implements OnInit {
|
||||
getRemoteDataPayload(),
|
||||
take(1)
|
||||
).subscribe((item: Item) => {
|
||||
this.router.navigate(['/items/', item.id]);
|
||||
this.router.navigate([getItemPageRoute(item)]);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -89,7 +89,7 @@
|
||||
<button (click)="performAction()"
|
||||
class="btn btn-outline-secondary perform-action">{{confirmMessage | translate}}
|
||||
</button>
|
||||
<button [routerLink]="['/items/', item.id, 'edit']" class="btn btn-outline-secondary cancel">
|
||||
<button [routerLink]="[itemPageRoute, 'edit']" class="btn btn-outline-secondary cancel">
|
||||
{{cancelMessage| translate}}
|
||||
</button>
|
||||
|
||||
|
@@ -183,7 +183,7 @@ describe('ItemDeleteComponent', () => {
|
||||
describe('notify', () => {
|
||||
it('should navigate to the item edit page on failed deletion of the item', () => {
|
||||
comp.notify(false);
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute('fake-id')]);
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute(mockItem)]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -355,7 +355,7 @@ export class ItemDeleteComponent
|
||||
this.router.navigate(['']);
|
||||
} else {
|
||||
this.notificationsService.error(this.translateService.get('item.edit.' + this.messageKey + '.error'));
|
||||
this.router.navigate([getItemEditRoute(this.item.id)]);
|
||||
this.router.navigate([getItemEditRoute(this.item)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@
|
||||
{{'item.edit.move.processing' | translate}}
|
||||
</span>
|
||||
</button>
|
||||
<button [routerLink]="['/items/', (itemRD$ | async)?.payload?.id, 'edit']"
|
||||
<button [routerLink]="[(itemPageRoute$ | async), 'edit']"
|
||||
class="btn btn-outline-secondary">
|
||||
{{'item.edit.move.cancel' | translate}}
|
||||
</button>
|
||||
|
@@ -57,9 +57,9 @@ describe('ItemMoveComponent', () => {
|
||||
|
||||
const routeStub = {
|
||||
data: observableOf({
|
||||
dso: createSuccessfulRemoteDataObject({
|
||||
dso: createSuccessfulRemoteDataObject(Object.assign(new Item(), {
|
||||
id: 'item1'
|
||||
})
|
||||
}))
|
||||
})
|
||||
};
|
||||
|
||||
@@ -122,7 +122,10 @@ describe('ItemMoveComponent', () => {
|
||||
});
|
||||
describe('moveCollection', () => {
|
||||
it('should call itemDataService.moveToCollection', () => {
|
||||
comp.itemId = 'item-id';
|
||||
comp.item = Object.assign(new Item(), {
|
||||
id: 'item-id',
|
||||
uuid: 'item-id',
|
||||
});
|
||||
comp.selectedCollectionName = 'selected-collection-id';
|
||||
comp.selectedCollection = collection1;
|
||||
comp.moveCollection();
|
||||
|
@@ -10,7 +10,7 @@ import { NotificationsService } from '../../../shared/notifications/notification
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
getFirstSucceededRemoteData,
|
||||
getFirstCompletedRemoteData
|
||||
getFirstCompletedRemoteData, getAllSucceededRemoteDataPayload
|
||||
} from '../../../core/shared/operators';
|
||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
@@ -19,7 +19,7 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio
|
||||
import { SearchService } from '../../../core/shared/search/search.service';
|
||||
import { PaginatedSearchOptions } from '../../../shared/search/paginated-search-options.model';
|
||||
import { SearchResult } from '../../../shared/search/search-result.model';
|
||||
import { getItemEditRoute } from '../../item-page-routing-paths';
|
||||
import { getItemEditRoute, getItemPageRoute } from '../../item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-move',
|
||||
@@ -43,11 +43,16 @@ export class ItemMoveComponent implements OnInit {
|
||||
selectedCollection: Collection;
|
||||
canSubmit = false;
|
||||
|
||||
itemId: string;
|
||||
item: Item;
|
||||
processing = false;
|
||||
|
||||
pagination = new PaginationComponentOptions();
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute$: Observable<string>;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private notificationsService: NotificationsService,
|
||||
@@ -58,8 +63,12 @@ export class ItemMoveComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.itemRD$ = this.route.data.pipe(map((data) => data.dso), getFirstSucceededRemoteData()) as Observable<RemoteData<Item>>;
|
||||
this.itemPageRoute$ = this.itemRD$.pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map((item) => getItemPageRoute(item))
|
||||
);
|
||||
this.itemRD$.subscribe((rd) => {
|
||||
this.itemId = rd.payload.id;
|
||||
this.item = rd.payload;
|
||||
}
|
||||
);
|
||||
this.pagination.pageSize = 5;
|
||||
@@ -116,9 +125,9 @@ export class ItemMoveComponent implements OnInit {
|
||||
*/
|
||||
moveCollection() {
|
||||
this.processing = true;
|
||||
this.itemDataService.moveToCollection(this.itemId, this.selectedCollection).pipe(getFirstCompletedRemoteData()).subscribe(
|
||||
this.itemDataService.moveToCollection(this.item.id, this.selectedCollection).pipe(getFirstCompletedRemoteData()).subscribe(
|
||||
(response: RemoteData<Collection>) => {
|
||||
this.router.navigate([getItemEditRoute(this.itemId)]);
|
||||
this.router.navigate([getItemEditRoute(this.item)]);
|
||||
if (response.hasSucceeded) {
|
||||
this.notificationsService.success(this.translateService.get('item.edit.move.success'));
|
||||
} else {
|
||||
|
@@ -47,9 +47,9 @@ describe('ItemReinstateComponent', () => {
|
||||
|
||||
routeStub = {
|
||||
data: observableOf({
|
||||
dso: createSuccessfulRemoteDataObject({
|
||||
dso: createSuccessfulRemoteDataObject(Object.assign(new Item(), {
|
||||
id: 'fake-id'
|
||||
})
|
||||
}))
|
||||
})
|
||||
};
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
{{'item.edit.tabs.status.labels.itemPage' | translate}}:
|
||||
</div>
|
||||
<div class="col-9 float-left status-data" id="status-itemPage">
|
||||
<a [routerLink]="getItemPage((itemRD$ | async)?.payload)">{{getItemPage((itemRD$ | async)?.payload)}}</a>
|
||||
<a [routerLink]="itemPageRoute$ | async">{{itemPageRoute$ | async}}</a>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let operation of (operations$ | async)" class="w-100" [ngClass]="{'pt-3': operation}">
|
||||
|
@@ -20,6 +20,7 @@ describe('ItemStatusComponent', () => {
|
||||
|
||||
const mockItem = Object.assign(new Item(), {
|
||||
id: 'fake-id',
|
||||
uuid: 'fake-id',
|
||||
handle: 'fake/handle',
|
||||
lastModified: '2018',
|
||||
_links: {
|
||||
@@ -27,7 +28,7 @@ describe('ItemStatusComponent', () => {
|
||||
}
|
||||
});
|
||||
|
||||
const itemPageUrl = `items/${mockItem.id}`;
|
||||
const itemPageUrl = `/items/${mockItem.uuid}`;
|
||||
|
||||
const routeStub = {
|
||||
parent: {
|
||||
|
@@ -10,6 +10,7 @@ import { getItemEditRoute, getItemPageRoute } from '../../item-page-routing-path
|
||||
import { AuthorizationDataService } from '../../../core/data/feature-authorization/authorization-data.service';
|
||||
import { FeatureID } from '../../../core/data/feature-authorization/feature-id';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
import { getAllSucceededRemoteDataPayload } from '../../../core/shared/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-status',
|
||||
@@ -50,6 +51,11 @@ export class ItemStatusComponent implements OnInit {
|
||||
*/
|
||||
actionsKeys;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute$: Observable<string>;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private authorizationService: AuthorizationDataService) {
|
||||
}
|
||||
@@ -109,15 +115,10 @@ export class ItemStatusComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the url to the simple item page
|
||||
* @returns {string} url
|
||||
*/
|
||||
getItemPage(item: Item): string {
|
||||
return getItemPageRoute(item.id);
|
||||
this.itemPageRoute$ = this.itemRD$.pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map((item) => getItemPageRoute(item))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +126,7 @@ export class ItemStatusComponent implements OnInit {
|
||||
* @returns {string} url
|
||||
*/
|
||||
getCurrentUrl(item: Item): string {
|
||||
return getItemEditRoute(item.id);
|
||||
return getItemEditRoute(item);
|
||||
}
|
||||
|
||||
trackOperation(index: number, operation: ItemOperation) {
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<ds-modify-item-overview [item]="item"></ds-modify-item-overview>
|
||||
<button (click)="performAction()" class="btn btn-outline-secondary perform-action">{{confirmMessage | translate}}
|
||||
</button>
|
||||
<button [routerLink]="['/items/', item.id, 'edit']" class="btn btn-outline-secondary cancel">
|
||||
<button [routerLink]="[itemPageRoute, 'edit']" class="btn btn-outline-secondary cancel">
|
||||
{{cancelMessage| translate}}
|
||||
</button>
|
||||
|
||||
|
@@ -74,9 +74,9 @@ describe('AbstractSimpleItemActionComponent', () => {
|
||||
|
||||
routeStub = {
|
||||
data: observableOf({
|
||||
dso: createSuccessfulRemoteDataObject({
|
||||
dso: createSuccessfulRemoteDataObject(Object.assign(new Item(), {
|
||||
id: 'fake-id'
|
||||
})
|
||||
}))
|
||||
})
|
||||
};
|
||||
|
||||
@@ -136,14 +136,14 @@ describe('AbstractSimpleItemActionComponent', () => {
|
||||
comp.processRestResponse(successfulRemoteData);
|
||||
|
||||
expect(notificationsServiceStub.success).toHaveBeenCalled();
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute(mockItem.id)]);
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute(mockItem)]);
|
||||
});
|
||||
|
||||
it('should process a RemoteData to navigate and display success notification', () => {
|
||||
comp.processRestResponse(failedRemoteData);
|
||||
|
||||
expect(notificationsServiceStub.error).toHaveBeenCalled();
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute(mockItem.id)]);
|
||||
expect(routerStub.navigate).toHaveBeenCalledWith([getItemEditRoute(mockItem)]);
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -9,7 +9,7 @@ import { Observable } from 'rxjs';
|
||||
import { getFirstSucceededRemoteData } from '../../../core/shared/operators';
|
||||
import { first, map } from 'rxjs/operators';
|
||||
import { findSuccessfulAccordingTo } from '../edit-item-operators';
|
||||
import { getItemEditRoute } from '../../item-page-routing-paths';
|
||||
import { getItemEditRoute, getItemPageRoute } from '../../item-page-routing-paths';
|
||||
|
||||
/**
|
||||
* Component to render and handle simple item edit actions such as withdrawal and reinstatement.
|
||||
@@ -30,6 +30,11 @@ export class AbstractSimpleItemActionComponent implements OnInit {
|
||||
headerMessage: string;
|
||||
descriptionMessage: string;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
protected predicate: Predicate<RemoteData<Item>>;
|
||||
|
||||
constructor(protected route: ActivatedRoute,
|
||||
@@ -47,6 +52,7 @@ export class AbstractSimpleItemActionComponent implements OnInit {
|
||||
|
||||
this.itemRD$.pipe(first()).subscribe((rd) => {
|
||||
this.item = rd.payload;
|
||||
this.itemPageRoute = getItemPageRoute(this.item);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -71,11 +77,11 @@ export class AbstractSimpleItemActionComponent implements OnInit {
|
||||
this.itemDataService.findById(this.item.id).pipe(
|
||||
findSuccessfulAccordingTo(this.predicate)).subscribe(() => {
|
||||
this.notificationsService.success(this.translateService.get('item.edit.' + this.messageKey + '.success'));
|
||||
this.router.navigate([getItemEditRoute(this.item.id)]);
|
||||
this.router.navigate([getItemEditRoute(this.item)]);
|
||||
});
|
||||
} else {
|
||||
this.notificationsService.error(this.translateService.get('item.edit.' + this.messageKey + '.error'));
|
||||
this.router.navigate([getItemEditRoute(this.item.id)]);
|
||||
this.router.navigate([getItemEditRoute(this.item)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,11 +7,11 @@
|
||||
<div class="d-flex flex-row">
|
||||
<ds-item-page-title-field class="mr-auto" [item]="item"></ds-item-page-title-field>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="item" [tooltipMsg]="'item.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute$ | async" [dso]="item" [tooltipMsg]="'item.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="simple-view-link my-3">
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + item.id]">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[(itemPageRoute$ | async)]">
|
||||
{{"item.page.link.simple" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -1,4 +1,6 @@
|
||||
import { URLCombiner } from '../core/url-combiner/url-combiner';
|
||||
import { Item } from '../core/shared/item.model';
|
||||
import { isNotEmpty } from '../shared/empty.util';
|
||||
|
||||
export const ITEM_MODULE_PATH = 'items';
|
||||
|
||||
@@ -6,12 +8,30 @@ export function getItemModuleRoute() {
|
||||
return `/${ITEM_MODULE_PATH}`;
|
||||
}
|
||||
|
||||
export function getItemPageRoute(itemId: string) {
|
||||
return new URLCombiner(getItemModuleRoute(), itemId).toString();
|
||||
/**
|
||||
* Get the route to an item's page
|
||||
* Depending on the item's relationship type, the route will either start with /items or /entities
|
||||
* @param item The item to retrieve the route for
|
||||
*/
|
||||
export function getItemPageRoute(item: Item) {
|
||||
const type = item.firstMetadataValue('relationship.type');
|
||||
return getEntityPageRoute(type, item.uuid);
|
||||
}
|
||||
|
||||
export function getItemEditRoute(id: string) {
|
||||
return new URLCombiner(getItemModuleRoute(), id, ITEM_EDIT_PATH).toString();
|
||||
export function getItemEditRoute(item: Item) {
|
||||
return new URLCombiner(getItemPageRoute(item), ITEM_EDIT_PATH).toString();
|
||||
}
|
||||
|
||||
export function getEntityPageRoute(entityType: string, itemId: string) {
|
||||
if (isNotEmpty(entityType)) {
|
||||
return new URLCombiner('/entities', encodeURIComponent(entityType.toLowerCase()), itemId).toString();
|
||||
} else {
|
||||
return new URLCombiner(getItemModuleRoute(), itemId).toString();
|
||||
}
|
||||
}
|
||||
|
||||
export function getEntityEditRoute(entityType: string, itemId: string) {
|
||||
return new URLCombiner(getEntityPageRoute(entityType, itemId), ITEM_EDIT_PATH).toString();
|
||||
}
|
||||
|
||||
export const ITEM_EDIT_PATH = 'edit';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
|
||||
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemoteData } from '../core/data/remote-data';
|
||||
import { ItemDataService } from '../core/data/item-data.service';
|
||||
@@ -9,6 +9,9 @@ import { FindListOptions } from '../core/data/request.models';
|
||||
import { getFirstCompletedRemoteData } from '../core/shared/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { ResolvedAction } from '../core/resolving/resolver.actions';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { hasValue } from '../shared/empty.util';
|
||||
import { getItemPageRoute } from './item-page-routing-paths';
|
||||
|
||||
/**
|
||||
* The self links defined in this list are expected to be requested somewhere in the near future
|
||||
@@ -31,7 +34,8 @@ export const ITEM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig<Item>[] = [
|
||||
export class ItemPageResolver implements Resolve<RemoteData<Item>> {
|
||||
constructor(
|
||||
private itemService: ItemDataService,
|
||||
private store: Store<any>
|
||||
private store: Store<any>,
|
||||
private router: Router
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -49,6 +53,18 @@ export class ItemPageResolver implements Resolve<RemoteData<Item>> {
|
||||
...ITEM_PAGE_LINKS_TO_FOLLOW
|
||||
).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
map((rd: RemoteData<Item>) => {
|
||||
if (rd.hasSucceeded && hasValue(rd.payload)) {
|
||||
const itemRoute = getItemPageRoute(rd.payload);
|
||||
const thisRoute = state.url;
|
||||
if (!thisRoute.startsWith(itemRoute)) {
|
||||
const itemId = rd.payload.uuid;
|
||||
const subRoute = thisRoute.substring(thisRoute.indexOf(itemId) + itemId.length, thisRoute.length);
|
||||
this.router.navigateByUrl(itemRoute + subRoute);
|
||||
}
|
||||
}
|
||||
return rd;
|
||||
})
|
||||
);
|
||||
|
||||
itemRD$.subscribe((itemRD: RemoteData<Item>) => {
|
||||
|
@@ -11,9 +11,10 @@ import { Item } from '../../core/shared/item.model';
|
||||
import { MetadataService } from '../../core/metadata/metadata.service';
|
||||
|
||||
import { fadeInOut } from '../../shared/animations/fade';
|
||||
import { redirectOn4xx } from '../../core/shared/operators';
|
||||
import { getAllSucceededRemoteDataPayload, redirectOn4xx } from '../../core/shared/operators';
|
||||
import { ViewMode } from '../../core/shared/view-mode.model';
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { getItemPageRoute } from '../item-page-routing-paths';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -44,6 +45,11 @@ export class ItemPageComponent implements OnInit {
|
||||
*/
|
||||
viewMode = ViewMode.StandalonePage;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute$: Observable<string>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
@@ -61,5 +67,9 @@ export class ItemPageComponent implements OnInit {
|
||||
redirectOn4xx(this.router, this.authService)
|
||||
);
|
||||
this.metadataService.processRemoteData(this.itemRD$);
|
||||
this.itemPageRoute$ = this.itemRD$.pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map((item) => getItemPageRoute(item))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{{'publication.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'publication.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'publication.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -74,7 +74,7 @@
|
||||
</ds-item-page-uri-field>
|
||||
<ds-item-page-collections [item]="object"></ds-item-page-collections>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { BitstreamDataService } from '../../../../core/data/bitstream-data.service';
|
||||
import { Bitstream } from '../../../../core/shared/bitstream.model';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/operators';
|
||||
import { getItemPageRoute } from '../../../item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item',
|
||||
@@ -12,12 +13,21 @@ import { getFirstSucceededRemoteDataPayload } from '../../../../core/shared/oper
|
||||
/**
|
||||
* A generic component for displaying metadata and relations of an item
|
||||
*/
|
||||
export class ItemComponent {
|
||||
export class ItemComponent implements OnInit {
|
||||
@Input() object: Item;
|
||||
|
||||
/**
|
||||
* Route to the item page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
constructor(protected bitstreamDataService: BitstreamDataService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.itemPageRoute = getItemPageRoute(this.object);
|
||||
}
|
||||
|
||||
// TODO refactor to return RemoteData, and thumbnail template to deal with loading
|
||||
getThumbnail(): Observable<Bitstream> {
|
||||
return this.bitstreamDataService.getThumbnailFor(this.object).pipe(
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'item.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'item.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -59,7 +59,7 @@
|
||||
</ds-item-page-uri-field>
|
||||
<ds-item-page-collections [item]="object"></ds-item-page-collections>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -1,7 +1,14 @@
|
||||
import { HostWindowService } from '../shared/host-window.service';
|
||||
import { SidebarService } from '../shared/sidebar/sidebar.service';
|
||||
import { SearchComponent } from './search.component';
|
||||
import { ChangeDetectionStrategy, Component, Inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { pushInOut } from '../shared/animations/push';
|
||||
import { SEARCH_CONFIG_SERVICE } from '../+my-dspace-page/my-dspace-page.component';
|
||||
import { SearchConfigurationService } from '../core/shared/search/search-configuration.service';
|
||||
|
@@ -53,7 +53,7 @@ export function getDSORoute(dso: DSpaceObject): string {
|
||||
case Collection.type.value:
|
||||
return getCollectionPageRoute(dso.uuid);
|
||||
case Item.type.value:
|
||||
return getItemPageRoute(dso.uuid);
|
||||
return getItemPageRoute(dso as Item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -86,6 +86,11 @@ import { ForbiddenComponent } from './forbidden/forbidden.component';
|
||||
.then((m) => m.ItemPageModule),
|
||||
canActivate: [EndUserAgreementCurrentUserGuard]
|
||||
},
|
||||
{ path: 'entities/:entity-type',
|
||||
loadChildren: () => import('./+item-page/item-page.module')
|
||||
.then((m) => m.ItemPageModule),
|
||||
canActivate: [EndUserAgreementCurrentUserGuard]
|
||||
},
|
||||
{
|
||||
path: BITSTREAM_MODULE_PATH,
|
||||
loadChildren: () => import('./+bitstream-page/bitstream-page.module')
|
||||
|
@@ -12,6 +12,7 @@ import { DsoRedirectDataService } from './dso-redirect-data.service';
|
||||
import { GetRequest, IdentifierType } from './request.models';
|
||||
import { RequestService } from './request.service';
|
||||
import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
|
||||
import { Item } from '../shared/item.model';
|
||||
|
||||
describe('DsoRedirectDataService', () => {
|
||||
let scheduler: TestScheduler;
|
||||
@@ -48,10 +49,10 @@ describe('DsoRedirectDataService', () => {
|
||||
navigate: jasmine.createSpy('navigate')
|
||||
};
|
||||
|
||||
remoteData = createSuccessfulRemoteDataObject({
|
||||
remoteData = createSuccessfulRemoteDataObject(Object.assign(new Item(), {
|
||||
type: 'item',
|
||||
uuid: '123456789'
|
||||
});
|
||||
}));
|
||||
|
||||
rdbService = jasmine.createSpyObj('rdbService', {
|
||||
buildSingle: cold('a', {
|
||||
@@ -114,7 +115,24 @@ describe('DsoRedirectDataService', () => {
|
||||
redir.subscribe();
|
||||
scheduler.schedule(() => redir);
|
||||
scheduler.flush();
|
||||
expect(router.navigate).toHaveBeenCalledWith([remoteData.payload.type + 's/' + remoteData.payload.uuid]);
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/items/' + remoteData.payload.uuid]);
|
||||
});
|
||||
it('should navigate to entities route with the corresponding entity type', () => {
|
||||
remoteData.payload.type = 'item';
|
||||
remoteData.payload.metadata = {
|
||||
'relationship.type': [
|
||||
{
|
||||
language: 'en_US',
|
||||
value: 'Publication'
|
||||
}
|
||||
],
|
||||
};
|
||||
const redir = service.findByIdAndIDType(dsoHandle, IdentifierType.HANDLE);
|
||||
// The framework would normally subscribe but do it here so we can test navigation.
|
||||
redir.subscribe();
|
||||
scheduler.schedule(() => redir);
|
||||
scheduler.flush();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/entities/publication/' + remoteData.payload.uuid]);
|
||||
});
|
||||
|
||||
it('should navigate to collections route', () => {
|
||||
|
@@ -18,6 +18,8 @@ import { IdentifierType } from './request.models';
|
||||
import { RequestService } from './request.service';
|
||||
import { getFirstCompletedRemoteData } from '../shared/operators';
|
||||
import { DSpaceObject } from '../shared/dspace-object.model';
|
||||
import { Item } from '../shared/item.model';
|
||||
import { getItemPageRoute } from '../../+item-page/item-page-routing-paths';
|
||||
|
||||
@Injectable()
|
||||
export class DsoRedirectDataService extends DataService<any> {
|
||||
@@ -60,10 +62,18 @@ export class DsoRedirectDataService extends DataService<any> {
|
||||
getFirstCompletedRemoteData(),
|
||||
tap((response) => {
|
||||
if (response.hasSucceeded) {
|
||||
const uuid = response.payload.uuid;
|
||||
const newRoute = this.getEndpointFromDSOType(response.payload.type);
|
||||
if (hasValue(uuid) && hasValue(newRoute)) {
|
||||
this.router.navigate([newRoute + '/' + uuid]);
|
||||
const dso = response.payload;
|
||||
const uuid = dso.uuid;
|
||||
if (hasValue(uuid)) {
|
||||
let newRoute = this.getEndpointFromDSOType(response.payload.type);
|
||||
if (dso.type.startsWith('item')) {
|
||||
newRoute = getItemPageRoute(dso as Item);
|
||||
} else if (hasValue(newRoute)) {
|
||||
newRoute += '/' + uuid;
|
||||
}
|
||||
if (hasValue(newRoute)) {
|
||||
this.router.navigate([newRoute]);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -1,5 +1,13 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse, HttpXsrfTokenExtractor } from '@angular/common/http';
|
||||
import {
|
||||
HttpErrorResponse,
|
||||
HttpEvent,
|
||||
HttpHandler,
|
||||
HttpInterceptor,
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
HttpXsrfTokenExtractor
|
||||
} from '@angular/common/http';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { tap, catchError } from 'rxjs/operators';
|
||||
import { RESTURLCombiner } from '../url-combiner/rest-url-combiner';
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
@@ -36,7 +36,7 @@
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,9 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent('JournalIssueSearchResult', ViewMode.GridElement)
|
||||
@Component({
|
||||
@@ -16,5 +14,5 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
/**
|
||||
* The component for displaying a grid element for an item search result of the type Journal Issue
|
||||
*/
|
||||
export class JournalIssueSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> {
|
||||
export class JournalIssueSearchResultGridElementComponent extends ItemSearchResultGridElementComponent {
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
@@ -36,7 +36,7 @@
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,10 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
import { ItemSearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent('JournalVolumeSearchResult', ViewMode.GridElement)
|
||||
@Component({
|
||||
@@ -16,5 +14,5 @@ import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
/**
|
||||
* The component for displaying a grid element for an item search result of the type Journal Volume
|
||||
*/
|
||||
export class JournalVolumeSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> {
|
||||
export class JournalVolumeSearchResultGridElementComponent extends ItemSearchResultGridElementComponent {
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
@@ -40,7 +40,7 @@
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,9 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent('JournalSearchResult', ViewMode.GridElement)
|
||||
@Component({
|
||||
@@ -16,5 +14,5 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
/**
|
||||
* The component for displaying a grid element for an item search result of the type Journal
|
||||
*/
|
||||
export class JournalSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> {
|
||||
export class JournalSearchResultGridElementComponent extends ItemSearchResultGridElementComponent {
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[routerLink]="[itemPageRoute]" class="lead"
|
||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||
<span *ngIf="linkType == linkTypes.None"
|
||||
class="lead"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||
|
||||
@listableObjectComponent('JournalIssueSearchResult', ViewMode.ListElement)
|
||||
@Component({
|
||||
@@ -14,5 +12,5 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
/**
|
||||
* The component for displaying a list element for an item search result of the type Journal Issue
|
||||
*/
|
||||
export class JournalIssueSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||
export class JournalIssueSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[routerLink]="[itemPageRoute]" class="lead"
|
||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||
<span *ngIf="linkType == linkTypes.None"
|
||||
class="lead"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||
|
||||
@listableObjectComponent('JournalVolumeSearchResult', ViewMode.ListElement)
|
||||
@Component({
|
||||
@@ -14,5 +12,5 @@ import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
/**
|
||||
* The component for displaying a list element for an item search result of the type Journal Volume
|
||||
*/
|
||||
export class JournalVolumeSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||
export class JournalVolumeSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[routerLink]="[itemPageRoute]" class="lead"
|
||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||
<span *ngIf="linkType == linkTypes.None"
|
||||
class="lead"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||
|
||||
@listableObjectComponent('JournalSearchResult', ViewMode.ListElement)
|
||||
@Component({
|
||||
@@ -14,5 +12,5 @@ import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
/**
|
||||
* The component for displaying a list element for an item search result of the type Journal
|
||||
*/
|
||||
export class JournalSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||
export class JournalSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{{'journalissue.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'journalissue.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'journalissue.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -53,7 +53,7 @@
|
||||
[label]="'journalissue.page.keyword'">
|
||||
</ds-generic-item-page-field>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{{'journalvolume.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'journalvolume.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'journalvolume.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -36,7 +36,7 @@
|
||||
[label]="'journalvolume.page.description'">
|
||||
</ds-generic-item-page-field>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{{'journal.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'journal.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'journal.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -35,7 +35,7 @@
|
||||
[label]="'journal.page.description'">
|
||||
</ds-generic-item-page-field>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
@@ -42,7 +42,7 @@
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,9 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent('OrgUnitSearchResult', ViewMode.GridElement)
|
||||
@Component({
|
||||
@@ -16,5 +14,5 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
/**
|
||||
* The component for displaying a grid element for an item search result of the type Organisation Unit
|
||||
*/
|
||||
export class OrgUnitSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> {
|
||||
export class OrgUnitSearchResultGridElementComponent extends ItemSearchResultGridElementComponent {
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
@@ -36,7 +36,7 @@
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2,9 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent('PersonSearchResult', ViewMode.GridElement)
|
||||
@Component({
|
||||
@@ -16,5 +14,5 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
/**
|
||||
* The component for displaying a grid element for an item search result of the type Person
|
||||
*/
|
||||
export class PersonSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> {
|
||||
export class PersonSearchResultGridElementComponent extends ItemSearchResultGridElementComponent {
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
</div>
|
||||
<a *ngIf="linkType != linkTypes.None"
|
||||
[target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
@@ -30,7 +30,7 @@
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'"
|
||||
rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,10 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/search-result-grid-element.component';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
import { ItemSearchResultGridElementComponent } from '../../../../../shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component';
|
||||
|
||||
@listableObjectComponent('ProjectSearchResult', ViewMode.GridElement)
|
||||
@Component({
|
||||
@@ -16,5 +14,5 @@ import { focusShadow } from '../../../../../shared/animations/focus';
|
||||
/**
|
||||
* The component for displaying a grid element for an item search result of the type Project
|
||||
*/
|
||||
export class ProjectSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> {
|
||||
export class ProjectSearchResultGridElementComponent extends ItemSearchResultGridElementComponent {
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[routerLink]="[itemPageRoute]" class="lead"
|
||||
[innerHTML]="firstMetadataValue('organization.legalName')"></a>
|
||||
<span *ngIf="linkType == linkTypes.None"
|
||||
class="lead"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||
|
||||
@listableObjectComponent('OrgUnitSearchResult', ViewMode.ListElement)
|
||||
@Component({
|
||||
@@ -14,5 +12,5 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
/**
|
||||
* The component for displaying a list element for an item search result of the type Organisation Unit
|
||||
*/
|
||||
export class OrgUnitSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||
export class OrgUnitSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[routerLink]="[itemPageRoute]" class="lead"
|
||||
[innerHTML]="name"></a>
|
||||
<span *ngIf="linkType == linkTypes.None"
|
||||
class="lead"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||
|
||||
@listableObjectComponent('PersonSearchResult', ViewMode.ListElement)
|
||||
@Component({
|
||||
@@ -14,7 +12,7 @@ import { Item } from '../../../../../core/shared/item.model';
|
||||
/**
|
||||
* The component for displaying a list element for an item search result of the type Person
|
||||
*/
|
||||
export class PersonSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||
export class PersonSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
||||
|
||||
get name() {
|
||||
return this.value ?
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<ds-truncatable [id]="dso.id">
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[routerLink]="[itemPageRoute]" class="lead"
|
||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||
<span *ngIf="linkType == linkTypes.None"
|
||||
class="lead"
|
||||
|
@@ -1,9 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { SearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/search-result-list-element.component';
|
||||
import { ItemSearchResult } from '../../../../../shared/object-collection/shared/item-search-result.model';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { listableObjectComponent } from '../../../../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||
import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
import { ItemSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
|
||||
|
||||
@listableObjectComponent('ProjectSearchResult', ViewMode.ListElement)
|
||||
@Component({
|
||||
@@ -14,5 +12,5 @@ import { ViewMode } from '../../../../../core/shared/view-mode.model';
|
||||
/**
|
||||
* The component for displaying a list element for an item search result of the type Project
|
||||
*/
|
||||
export class ProjectSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||
export class ProjectSearchResultListElementComponent extends ItemSearchResultListElementComponent {
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{{'orgunit.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="object?.allMetadata(['organization.legalName'])"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'orgunit.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'orgunit.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -39,7 +39,7 @@
|
||||
[label]="'orgunit.page.description'">
|
||||
</ds-generic-item-page-field>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{{'person.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="[object?.firstMetadata('person.familyName'), object?.firstMetadata('person.givenName')]" [separator]="', '"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'person.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'person.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -52,7 +52,7 @@
|
||||
[label]="'person.page.firstname'">
|
||||
</ds-generic-item-page-field>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{{'project.page.titleprefix' | translate}}<ds-metadata-values [mdValues]="object?.allMetadata(['dc.title'])"></ds-metadata-values>
|
||||
</h2>
|
||||
<div class="pl-2">
|
||||
<ds-dso-page-edit-button [pageRoutePrefix]="'items'" [dso]="object" [tooltipMsg]="'project.page.edit'"></ds-dso-page-edit-button>
|
||||
<ds-dso-page-edit-button [pageRoute]="itemPageRoute" [dso]="object" [tooltipMsg]="'project.page.edit'"></ds-dso-page-edit-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -59,7 +59,7 @@
|
||||
[label]="'project.page.keyword'">
|
||||
</ds-generic-item-page-field>
|
||||
<div>
|
||||
<a class="btn btn-outline-primary" [routerLink]="['/items/' + object.id + '/full']">
|
||||
<a class="btn btn-outline-primary" [routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
</span>
|
||||
</ng-template>
|
||||
<ds-truncatable [id]="metadataRepresentation.id">
|
||||
<a [routerLink]="['/items/' + metadataRepresentation.id]"
|
||||
<a [routerLink]="[itemPageRoute]"
|
||||
[innerHTML]="metadataRepresentation.getValue()"
|
||||
[ngbTooltip]="metadataRepresentation.allMetadata(['dc.description']).length > 0 ? descTemplate : null"></a>
|
||||
</ds-truncatable>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
</span>
|
||||
</ng-template>
|
||||
<ds-truncatable [id]="metadataRepresentation.id">
|
||||
<a [routerLink]="['/items/' + metadataRepresentation.id]"
|
||||
<a [routerLink]="[itemPageRoute]"
|
||||
[innerHTML]="metadataRepresentation.getValue()"
|
||||
[ngbTooltip]="metadataRepresentation.allMetadata(['person.jobTitle']).length > 0 ? descTemplate : null"></a>
|
||||
</ds-truncatable>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<a *ngIf="isAuthorized$ | async"
|
||||
[routerLink]="['/' + pageRoutePrefix, dso.id, 'edit']"
|
||||
[routerLink]="[pageRoute, 'edit']"
|
||||
class="edit-button btn btn-dark text-light btn-sm"
|
||||
[ngbTooltip]="tooltipMsg | translate">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i>
|
||||
|
@@ -40,7 +40,7 @@ describe('DsoPageEditButtonComponent', () => {
|
||||
fixture = TestBed.createComponent(DsoPageEditButtonComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.dso = dso;
|
||||
component.pageRoutePrefix = 'test';
|
||||
component.pageRoute = 'test';
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@@ -21,7 +21,7 @@ export class DsoPageEditButtonComponent implements OnInit {
|
||||
/**
|
||||
* The prefix of the route to the edit page (before the object's UUID, e.g. "items")
|
||||
*/
|
||||
@Input() pageRoutePrefix: string;
|
||||
@Input() pageRoute: string;
|
||||
|
||||
/**
|
||||
* A message for the tooltip on the button
|
||||
|
@@ -5,6 +5,7 @@ import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../dso-selector-modal-wrapper.component';
|
||||
import { getItemEditRoute } from '../../../../+item-page/item-page-routing-paths';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
|
||||
/**
|
||||
* Component to wrap a list of existing items inside a modal
|
||||
@@ -28,6 +29,6 @@ export class EditItemSelectorComponent extends DSOSelectorModalWrapperComponent
|
||||
* Navigate to the item edit page
|
||||
*/
|
||||
navigate(dso: DSpaceObject) {
|
||||
this.router.navigate([getItemEditRoute(dso.uuid)]);
|
||||
this.router.navigate([getItemEditRoute(dso as Item)]);
|
||||
}
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<td class="version-row-element-version">{{version?.version}}</td>
|
||||
<td class="version-row-element-item">
|
||||
<span *ngVar="(version?.item | async)?.payload as item">
|
||||
<a *ngIf="item" [routerLink]="['/items', item?.id]">{{item?.handle}}</a>
|
||||
<a *ngIf="item" [routerLink]="[(itemPageRoutes$ | async)[item?.id]]">{{item?.handle}}</a>
|
||||
<span *ngIf="version?.id === itemVersion?.id">*</span>
|
||||
</span>
|
||||
</td>
|
||||
|
@@ -4,7 +4,11 @@ import { Version } from '../../../core/shared/version.model';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable } from 'rxjs';
|
||||
import { VersionHistory } from '../../../core/shared/version-history.model';
|
||||
import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../core/shared/operators';
|
||||
import {
|
||||
getAllSucceededRemoteData,
|
||||
getAllSucceededRemoteDataPayload,
|
||||
getRemoteDataPayload
|
||||
} from '../../../core/shared/operators';
|
||||
import { map, startWith, switchMap } from 'rxjs/operators';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||
import { PaginationComponentOptions } from '../../pagination/pagination-component-options.model';
|
||||
@@ -13,6 +17,7 @@ import { PaginatedSearchOptions } from '../../search/paginated-search-options.mo
|
||||
import { AlertType } from '../../alert/aletr-type';
|
||||
import { followLink } from '../../utils/follow-link-config.model';
|
||||
import { hasValueOperator } from '../../empty.util';
|
||||
import { getItemPageRoute } from '../../../+item-page/item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-versions',
|
||||
@@ -86,6 +91,15 @@ export class ItemVersionsComponent implements OnInit {
|
||||
*/
|
||||
currentPage$ = new BehaviorSubject<number>(1);
|
||||
|
||||
/**
|
||||
* The routes to the versions their item pages
|
||||
* Key: Item ID
|
||||
* Value: Route to item page
|
||||
*/
|
||||
itemPageRoutes$: Observable<{
|
||||
[itemId: string]: string
|
||||
}>;
|
||||
|
||||
constructor(private versionHistoryService: VersionHistoryDataService) {
|
||||
}
|
||||
|
||||
@@ -118,6 +132,15 @@ export class ItemVersionsComponent implements OnInit {
|
||||
map((versions: PaginatedList<Version>) => versions.page.filter((version: Version) => version.eperson !== undefined).length > 0),
|
||||
startWith(false)
|
||||
);
|
||||
this.itemPageRoutes$ = this.versionsRD$.pipe(
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
switchMap((versions) => observableCombineLatest(...versions.page.map((version) => version.item.pipe(getAllSucceededRemoteDataPayload())))),
|
||||
map((versions) => {
|
||||
const itemPageRoutes = {};
|
||||
versions.forEach((item) => itemPageRoutes[item.uuid] = getItemPageRoute(item));
|
||||
return itemPageRoutes;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -109,7 +109,7 @@ export class ItemVersionsNoticeComponent implements OnInit {
|
||||
*/
|
||||
getItemPage(item: Item): string {
|
||||
if (hasValue(item)) {
|
||||
return getItemPageRoute(item.id);
|
||||
return getItemPageRoute(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,198 @@
|
||||
{
|
||||
"id": "0136fe00-43ca-439e-ae6c-b2b08c2b8f5e",
|
||||
"uuid": "0136fe00-43ca-439e-ae6c-b2b08c2b8f5e",
|
||||
"name": "The pathogenesis of dengue",
|
||||
"handle": "123456789/156",
|
||||
"metadata": {
|
||||
"dc.contributor.author": [
|
||||
{
|
||||
"value": "Simmons, Cameron",
|
||||
"language": null,
|
||||
"authority": "virtual::1586",
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.date.accessioned": [
|
||||
{
|
||||
"value": "2018-09-14T11:15:00Z",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.date.available": [
|
||||
{
|
||||
"value": "2017-07-12T04:44:34Z",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 1
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 2
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 3
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 4
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 5
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 6
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 7
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 8
|
||||
},
|
||||
{
|
||||
"value": "2018-09-14T11:15:00Z",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 9
|
||||
}
|
||||
],
|
||||
"dc.date.issued": [
|
||||
{
|
||||
"value": "2011-09-23",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.description.abstract": [
|
||||
{
|
||||
"value": "Dengue is an important cause of childhood and adult morbidity in Asian and Latin American countries and its geographic footprint is growing. The clinical manifestations of dengue are the expression of a constellation of host and viral factors, some acquired, others intrinsic to the individual. The virulence of the virus plus the flavivirus infection history, age, gender and genotype of the host all appear to help shape the severity of infection. Similarly, the characteristics of the innate and acquired host immune response subsequent to infection are also likely determinants of outcome. This review summarises recent developments in the understanding of dengue pathogenesis and their relevance to dengue vaccine development.",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.identifier.uri": [
|
||||
{
|
||||
"value": "http://localhost:8080/dspace7/handle/123456789/156",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.language": [
|
||||
{
|
||||
"value": "English",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.title": [
|
||||
{
|
||||
"value": "The pathogenesis of dengue",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.type": [
|
||||
{
|
||||
"value": "Journal Article",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"relation.isAuthorOfPublication": [
|
||||
{
|
||||
"value": "b1b2c768-bda1-448a-a073-fc541e8b24d9",
|
||||
"language": null,
|
||||
"authority": "virtual::1586",
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"relationship.type": [
|
||||
{
|
||||
"value": "Publication",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"inArchive": true,
|
||||
"discoverable": true,
|
||||
"withdrawn": false,
|
||||
"lastModified": "2019-05-06T15:24:25.037+0000",
|
||||
"type": "item",
|
||||
"_links": {
|
||||
"bundles": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/bundles"
|
||||
},
|
||||
"mappedCollections": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/mappedCollections"
|
||||
},
|
||||
"owningCollection": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/owningCollection"
|
||||
},
|
||||
"relationships": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/relationships"
|
||||
},
|
||||
"version": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/version"
|
||||
},
|
||||
"templateItemOf": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/templateItemOf"
|
||||
},
|
||||
"self": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,180 @@
|
||||
{
|
||||
"id": "0136fe00-43ca-439e-ae6c-b2b08c2b8f5e",
|
||||
"uuid": "0136fe00-43ca-439e-ae6c-b2b08c2b8f5e",
|
||||
"name": "The pathogenesis of dengue",
|
||||
"handle": "123456789/156",
|
||||
"metadata": {
|
||||
"dc.contributor.author": [
|
||||
{
|
||||
"value": "Simmons, Cameron",
|
||||
"language": null,
|
||||
"authority": "null",
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.date.accessioned": [
|
||||
{
|
||||
"value": "2018-09-14T11:15:00Z",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.date.available": [
|
||||
{
|
||||
"value": "2017-07-12T04:44:34Z",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 1
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 2
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 3
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 4
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 5
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 6
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 7
|
||||
},
|
||||
{
|
||||
"value": "2011-07-06",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 8
|
||||
},
|
||||
{
|
||||
"value": "2018-09-14T11:15:00Z",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 9
|
||||
}
|
||||
],
|
||||
"dc.date.issued": [
|
||||
{
|
||||
"value": "2011-09-23",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.description.abstract": [
|
||||
{
|
||||
"value": "Dengue is an important cause of childhood and adult morbidity in Asian and Latin American countries and its geographic footprint is growing. The clinical manifestations of dengue are the expression of a constellation of host and viral factors, some acquired, others intrinsic to the individual. The virulence of the virus plus the flavivirus infection history, age, gender and genotype of the host all appear to help shape the severity of infection. Similarly, the characteristics of the innate and acquired host immune response subsequent to infection are also likely determinants of outcome. This review summarises recent developments in the understanding of dengue pathogenesis and their relevance to dengue vaccine development.",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.identifier.uri": [
|
||||
{
|
||||
"value": "http://localhost:8080/dspace7/handle/123456789/156",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.language": [
|
||||
{
|
||||
"value": "English",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.title": [
|
||||
{
|
||||
"value": "The pathogenesis of dengue",
|
||||
"language": "en_US",
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
],
|
||||
"dc.type": [
|
||||
{
|
||||
"value": "Journal Article",
|
||||
"language": null,
|
||||
"authority": null,
|
||||
"confidence": -1,
|
||||
"place": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"inArchive": true,
|
||||
"discoverable": true,
|
||||
"withdrawn": false,
|
||||
"lastModified": "2019-05-06T15:24:25.037+0000",
|
||||
"type": "item",
|
||||
"_links": {
|
||||
"bundles": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/bundles"
|
||||
},
|
||||
"mappedCollections": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/mappedCollections"
|
||||
},
|
||||
"owningCollection": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/owningCollection"
|
||||
},
|
||||
"relationships": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/relationships"
|
||||
},
|
||||
"version": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/version"
|
||||
},
|
||||
"templateItemOf": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e/templateItemOf"
|
||||
},
|
||||
"self": {
|
||||
"href": "https://dspace7.4science.cloud/server/api/core/items/0136fe00-43ca-439e-ae6c-b2b08c2b8f5e"
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
// import mockSubmissionResponse from './mock-submission-response.json';
|
||||
// import mockPublicationResponse from './mock-publication-response.json';
|
||||
// import mockUntypedItemResponse from './mock-untyped-item-response.json';
|
||||
|
||||
export class ResponseMapMock extends Map<string, any> {}
|
||||
|
||||
@@ -12,4 +14,6 @@ export const MOCK_RESPONSE_MAP: InjectionToken<ResponseMapMock> = new InjectionT
|
||||
*/
|
||||
export const mockResponseMap: ResponseMapMock = new Map([
|
||||
// [ '/config/submissionforms/traditionalpageone', mockSubmissionResponse ]
|
||||
// [ '/api/pid/find', mockPublicationResponse ],
|
||||
// [ '/api/pid/find', mockUntypedItemResponse ],
|
||||
]);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<button class="btn btn-primary mt-1 mb-3"
|
||||
ngbTooltip="{{'submission.workflow.generic.view-help' | translate}}"
|
||||
[routerLink]="['/items/' + object.id]">
|
||||
[routerLink]="[itemPageRoute]">
|
||||
<i class="fa fa-info-circle"></i> {{"submission.workflow.generic.view" | translate}}
|
||||
</button>
|
||||
|
@@ -1,14 +1,13 @@
|
||||
import { Component, Injector, Input } from '@angular/core';
|
||||
import { Component, Injector, Input, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
import { NotificationsService } from '../../notifications/notifications.service';
|
||||
import { RequestService } from '../../../core/data/request.service';
|
||||
import { SearchService } from '../../../core/shared/search/search.service';
|
||||
import { getItemPageRoute } from '../../../+item-page/item-page-routing-paths';
|
||||
|
||||
/**
|
||||
* This component represents mydspace actions related to Item object.
|
||||
@@ -19,13 +18,18 @@ import { SearchService } from '../../../core/shared/search/search.service';
|
||||
templateUrl: './item-actions.component.html',
|
||||
})
|
||||
|
||||
export class ItemActionsComponent extends MyDSpaceActionsComponent<Item, ItemDataService> {
|
||||
export class ItemActionsComponent extends MyDSpaceActionsComponent<Item, ItemDataService> implements OnInit {
|
||||
|
||||
/**
|
||||
* The Item object
|
||||
*/
|
||||
@Input() object: Item;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
/**
|
||||
* Initialize instance variables
|
||||
*
|
||||
@@ -45,6 +49,10 @@ export class ItemActionsComponent extends MyDSpaceActionsComponent<Item, ItemDat
|
||||
super(Item.type, injector, router, notificationsService, translate, searchService, requestService);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initPageRoute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the target object
|
||||
*
|
||||
@@ -52,6 +60,14 @@ export class ItemActionsComponent extends MyDSpaceActionsComponent<Item, ItemDat
|
||||
*/
|
||||
initObjects(object: Item) {
|
||||
this.object = object;
|
||||
this.initPageRoute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the route to the item's page
|
||||
*/
|
||||
initPageRoute() {
|
||||
this.itemPageRoute = getItemPageRoute(this.object);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,7 +12,10 @@ import { RouterStub } from '../testing/router.stub';
|
||||
import { getMockSearchService } from '../mocks/search-service.mock';
|
||||
import { getMockRequestService } from '../mocks/request.service.mock';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject } from '../remote-data.utils';
|
||||
import {
|
||||
createFailedRemoteDataObject,
|
||||
createSuccessfulRemoteDataObject
|
||||
} from '../remote-data.utils';
|
||||
import { WorkflowItem } from '../../core/submission/models/workflowitem.model';
|
||||
import { TranslateLoaderMock } from '../mocks/translate-loader.mock';
|
||||
import { NotificationsService } from '../notifications/notifications.service';
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<div class="position-absolute ml-1">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="card-img-top full-width">
|
||||
<div>
|
||||
<ds-grid-thumbnail [thumbnail]="getThumbnail() | async">
|
||||
@@ -36,7 +36,7 @@
|
||||
</ds-truncatable-part>
|
||||
</p>
|
||||
<div *ngIf="linkType != linkTypes.None" class="text-center">
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="['/items/' + dso.id]"
|
||||
<a [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="[itemPageRoute]"
|
||||
class="lead btn btn-primary viewButton">View</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -5,6 +5,7 @@ import { listableObjectComponent } from '../../../../object-collection/shared/li
|
||||
import { SearchResultGridElementComponent } from '../../search-result-grid-element.component';
|
||||
import { Item } from '../../../../../core/shared/item.model';
|
||||
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
|
||||
import { getItemPageRoute } from '../../../../../+item-page/item-page-routing-paths';
|
||||
|
||||
@listableObjectComponent('PublicationSearchResult', ViewMode.GridElement)
|
||||
@listableObjectComponent(ItemSearchResult, ViewMode.GridElement)
|
||||
@@ -18,4 +19,13 @@ import { ItemSearchResult } from '../../../../object-collection/shared/item-sear
|
||||
* The component for displaying a grid element for an item search result of the type Publication
|
||||
*/
|
||||
export class ItemSearchResultGridElementComponent extends SearchResultGridElementComponent<ItemSearchResult, Item> {
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.itemPageRoute = getItemPageRoute(this.dso);
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { MetadataRepresentationListElementComponent } from '../metadata-representation-list-element.component';
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
|
||||
import { getItemPageRoute } from '../../../../+item-page/item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-metadata-representation-list-element',
|
||||
@@ -9,6 +10,15 @@ import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-rep
|
||||
/**
|
||||
* An abstract class for displaying a single ItemMetadataRepresentation
|
||||
*/
|
||||
export class ItemMetadataRepresentationListElementComponent extends MetadataRepresentationListElementComponent {
|
||||
export class ItemMetadataRepresentationListElementComponent extends MetadataRepresentationListElementComponent implements OnInit {
|
||||
metadataRepresentation: ItemMetadataRepresentation;
|
||||
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.itemPageRoute = getItemPageRoute(this.metadataRepresentation);
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
<ds-truncatable [id]="dso.id" *ngIf="object !== undefined && object !== null">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer"
|
||||
[routerLink]="['/items/' + dso.id]" class="lead"
|
||||
[routerLink]="[itemPageRoute]" class="lead"
|
||||
[innerHTML]="firstMetadataValue('dc.title')"></a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="lead"
|
||||
[innerHTML]="firstMetadataValue('dc.title')"></span>
|
||||
|
@@ -4,6 +4,7 @@ import { ViewMode } from '../../../../../../core/shared/view-mode.model';
|
||||
import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model';
|
||||
import { SearchResultListElementComponent } from '../../../search-result-list-element.component';
|
||||
import { Item } from '../../../../../../core/shared/item.model';
|
||||
import { getItemPageRoute } from '../../../../../../+item-page/item-page-routing-paths';
|
||||
|
||||
@listableObjectComponent('PublicationSearchResult', ViewMode.ListElement)
|
||||
@listableObjectComponent(ItemSearchResult, ViewMode.ListElement)
|
||||
@@ -16,4 +17,13 @@ import { Item } from '../../../../../../core/shared/item.model';
|
||||
* The component for displaying a list element for an item search result of the type Publication
|
||||
*/
|
||||
export class ItemSearchResultListElementComponent extends SearchResultListElementComponent<ItemSearchResult, Item> {
|
||||
/**
|
||||
* Route to the item's page
|
||||
*/
|
||||
itemPageRoute: string;
|
||||
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.itemPageRoute = getItemPageRoute(this.dso);
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@
|
||||
</span>
|
||||
</td>
|
||||
<td><span *ngIf="item.hasMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])">{{item.firstMetadataValue(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])}}</span></td>
|
||||
<td><a [routerLink]="['/items', item.id]">{{item.firstMetadataValue("dc.title")}}</a></td>
|
||||
<td><a [routerLink]="[(itemPageRoutes$ | async)[item.id]]">{{item.firstMetadataValue("dc.title")}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@@ -2,7 +2,11 @@ import { Component, Input } from '@angular/core';
|
||||
import { Item } from '../../../core/shared/item.model';
|
||||
import { ObjectSelectService } from '../object-select.service';
|
||||
import { ObjectSelectComponent } from '../object-select/object-select.component';
|
||||
import { isNotEmpty } from '../../empty.util';
|
||||
import { hasValueOperator, isNotEmpty } from '../../empty.util';
|
||||
import { Observable } from 'rxjs';
|
||||
import { getAllSucceededRemoteDataPayload } from '../../../core/shared/operators';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { getItemPageRoute } from '../../../+item-page/item-page-routing-paths';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-item-select',
|
||||
@@ -20,6 +24,15 @@ export class ItemSelectComponent extends ObjectSelectComponent<Item> {
|
||||
@Input()
|
||||
hideCollection = false;
|
||||
|
||||
/**
|
||||
* The routes to the items their pages
|
||||
* Key: Item ID
|
||||
* Value: Route to item page
|
||||
*/
|
||||
itemPageRoutes$: Observable<{
|
||||
[itemId: string]: string
|
||||
}>;
|
||||
|
||||
constructor(protected objectSelectService: ObjectSelectService) {
|
||||
super(objectSelectService);
|
||||
}
|
||||
@@ -29,6 +42,15 @@ export class ItemSelectComponent extends ObjectSelectComponent<Item> {
|
||||
if (!isNotEmpty(this.confirmButton)) {
|
||||
this.confirmButton = 'item.select.confirm';
|
||||
}
|
||||
this.itemPageRoutes$ = this.dsoRD$.pipe(
|
||||
hasValueOperator(),
|
||||
getAllSucceededRemoteDataPayload(),
|
||||
map((items) => {
|
||||
const itemPageRoutes = {};
|
||||
items.page.forEach((item) => itemPageRoutes[item.uuid] = getItemPageRoute(item));
|
||||
return itemPageRoutes;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,11 @@ import { hasValue, isNotEmpty, isUndefined } from '../empty.util';
|
||||
import { UploaderService } from './uploader.service';
|
||||
import { UploaderProperties } from './uploader-properties.model';
|
||||
import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
||||
import { XSRF_REQUEST_HEADER, XSRF_RESPONSE_HEADER, XSRF_COOKIE } from '../../core/xsrf/xsrf.interceptor';
|
||||
import {
|
||||
XSRF_REQUEST_HEADER,
|
||||
XSRF_RESPONSE_HEADER,
|
||||
XSRF_COOKIE
|
||||
} from '../../core/xsrf/xsrf.interceptor';
|
||||
import { CookieService } from '../../core/services/cookie.service';
|
||||
|
||||
@Component({
|
||||
|
@@ -1,7 +1,10 @@
|
||||
import { GoogleAnalyticsService } from './google-analytics.service';
|
||||
import { Angulartics2GoogleAnalytics } from 'angulartics2/ga';
|
||||
import { ConfigurationDataService } from '../core/data/configuration-data.service';
|
||||
import {createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$} from '../shared/remote-data.utils';
|
||||
import {
|
||||
createFailedRemoteDataObject$,
|
||||
createSuccessfulRemoteDataObject$
|
||||
} from '../shared/remote-data.utils';
|
||||
import { ConfigurationProperty } from '../core/shared/configuration-property.model';
|
||||
|
||||
describe('GoogleAnalyticsService', () => {
|
||||
|
@@ -1,6 +1,11 @@
|
||||
import { ChangeDetectorRef, Component, Inject } from '@angular/core';
|
||||
|
||||
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, Subscription } from 'rxjs';
|
||||
import {
|
||||
BehaviorSubject,
|
||||
combineLatest as observableCombineLatest,
|
||||
Observable,
|
||||
Subscription
|
||||
} from 'rxjs';
|
||||
import { distinctUntilChanged, filter, map, mergeMap, switchMap, tap } from 'rxjs/operators';
|
||||
|
||||
import { SectionModelComponent } from '../models/section.model';
|
||||
|
@@ -35,4 +35,3 @@ if (hasValue(environment.universal) && environment.universal.preboot === false)
|
||||
document.addEventListener('DOMContentLoaded', () => bootloader(main));
|
||||
}
|
||||
|
||||
import 'zone.js/dist/zone';
|
||||
|
@@ -8,7 +8,7 @@ a<div class="top-item-page">
|
||||
</ds-metadata-field-wrapper>
|
||||
<div>
|
||||
<a class="btn btn-secondary"
|
||||
[routerLink]="['/items/' + object.id + '/full']">
|
||||
[routerLink]="[itemPageRoute + '/full']">
|
||||
{{"item.page.link.full" | translate}}
|
||||
</a>
|
||||
</div>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user