From f2da1fa59e907be9638fdad422e62624e4452df9 Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Mon, 11 Jan 2021 11:45:01 +0100 Subject: [PATCH 1/7] 75894: Angular - Routing --- src/app/app-routing.module.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index e14672f1f51..5e5c5f54131 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -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') From 1942e0e2bab386391e70661a9e6672876d97e4de Mon Sep 17 00:00:00 2001 From: Yana De Pauw Date: Tue, 12 Jan 2021 11:25:37 +0100 Subject: [PATCH 2/7] 75895: Angular - Handle redirects --- .../data/dso-redirect-data.service.spec.ts | 17 ++ .../core/data/dso-redirect-data.service.ts | 13 +- .../mocks/mock-publication-response.json | 198 ++++++++++++++++++ .../mocks/mock-untyped-item-response.json | 180 ++++++++++++++++ .../dspace-rest/mocks/response-map.mock.ts | 4 + 5 files changed, 410 insertions(+), 2 deletions(-) create mode 100644 src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json create mode 100644 src/app/shared/mocks/dspace-rest/mocks/mock-untyped-item-response.json diff --git a/src/app/core/data/dso-redirect-data.service.spec.ts b/src/app/core/data/dso-redirect-data.service.spec.ts index 602a447d52e..714774d808d 100644 --- a/src/app/core/data/dso-redirect-data.service.spec.ts +++ b/src/app/core/data/dso-redirect-data.service.spec.ts @@ -116,6 +116,23 @@ describe('DsoRedirectDataService', () => { scheduler.flush(); expect(router.navigate).toHaveBeenCalledWith([remoteData.payload.type + 's/' + 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', () => { remoteData.payload.type = 'collection'; diff --git a/src/app/core/data/dso-redirect-data.service.ts b/src/app/core/data/dso-redirect-data.service.ts index 9fb5135d340..688c3e19636 100644 --- a/src/app/core/data/dso-redirect-data.service.ts +++ b/src/app/core/data/dso-redirect-data.service.ts @@ -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 { Metadata } from '../shared/metadata.utils'; @Injectable() export class DsoRedirectDataService extends DataService { @@ -60,8 +62,15 @@ export class DsoRedirectDataService extends DataService { getFirstCompletedRemoteData(), tap((response) => { if (response.hasSucceeded) { - const uuid = response.payload.uuid; - const newRoute = this.getEndpointFromDSOType(response.payload.type); + const dso = response.payload; + const uuid = dso.uuid; + let newRoute = this.getEndpointFromDSOType(response.payload.type); + if (dso.type.startsWith('item')) { + const relation = Metadata.firstValue(dso.metadata, 'relationship.type'); + if (hasValue(relation)) { + newRoute = `entities/${relation.toLowerCase()}`; + } + } if (hasValue(uuid) && hasValue(newRoute)) { this.router.navigate([newRoute + '/' + uuid]); } diff --git a/src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json b/src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json new file mode 100644 index 00000000000..d298812e5da --- /dev/null +++ b/src/app/shared/mocks/dspace-rest/mocks/mock-publication-response.json @@ -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" + } + } +} \ No newline at end of file diff --git a/src/app/shared/mocks/dspace-rest/mocks/mock-untyped-item-response.json b/src/app/shared/mocks/dspace-rest/mocks/mock-untyped-item-response.json new file mode 100644 index 00000000000..0501e18b9e9 --- /dev/null +++ b/src/app/shared/mocks/dspace-rest/mocks/mock-untyped-item-response.json @@ -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" + } + } +} \ No newline at end of file diff --git a/src/app/shared/mocks/dspace-rest/mocks/response-map.mock.ts b/src/app/shared/mocks/dspace-rest/mocks/response-map.mock.ts index c1fb68853df..92f04a7bc5a 100644 --- a/src/app/shared/mocks/dspace-rest/mocks/response-map.mock.ts +++ b/src/app/shared/mocks/dspace-rest/mocks/response-map.mock.ts @@ -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 {} @@ -12,4 +14,6 @@ export const MOCK_RESPONSE_MAP: InjectionToken = new InjectionT */ export const mockResponseMap: ResponseMapMock = new Map([ // [ '/config/submissionforms/traditionalpageone', mockSubmissionResponse ] + // [ '/api/pid/find', mockPublicationResponse ], + // [ '/api/pid/find', mockUntypedItemResponse ], ]); From 8e7513208618ef701d8f92e6110203ae4c7a6af7 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 15 Jan 2021 16:33:27 +0100 Subject: [PATCH 3/7] 75939: (edit) item links refactored to contain entity types --- ...in-search-result-actions.component.spec.ts | 14 +++++----- ...m-admin-search-result-actions.component.ts | 2 +- .../edit-bitstream-page.component.spec.ts | 16 +++++++---- .../edit-bitstream-page.component.ts | 16 ++++++++--- .../collection-page.component.html | 2 +- .../collection-page.component.ts | 18 +++++++++++- .../community-page.component.html | 2 +- .../community-page.component.ts | 13 ++++++++- .../upload/upload-bitstream.component.ts | 13 +++++++-- .../abstract-item-update.component.ts | 7 +++++ .../edit-item-page.component.ts | 2 +- .../item-bitstreams.component.html | 2 +- .../item-edit-bitstream-bundle.component.html | 2 +- .../item-edit-bitstream-bundle.component.ts | 7 +++++ .../item-collection-mapper.component.spec.ts | 3 +- .../item-collection-mapper.component.ts | 3 +- .../item-delete/item-delete.component.html | 2 +- .../item-delete/item-delete.component.spec.ts | 2 +- .../item-delete/item-delete.component.ts | 2 +- .../item-move/item-move.component.html | 4 +-- .../item-move/item-move.component.spec.ts | 9 ++++-- .../item-move/item-move.component.ts | 21 ++++++++++---- .../item-reinstate.component.spec.ts | 4 +-- .../item-status/item-status.component.html | 2 +- .../item-status/item-status.component.spec.ts | 3 +- .../item-status/item-status.component.ts | 21 +++++++------- ...abstract-simple-item-action.component.html | 4 +-- ...tract-simple-item-action.component.spec.ts | 8 +++--- .../abstract-simple-item-action.component.ts | 12 ++++++-- .../full/full-item-page.component.html | 4 +-- src/app/+item-page/item-page-routing-paths.ts | 28 ++++++++++++++++--- .../+item-page/simple/item-page.component.ts | 12 +++++++- .../publication/publication.component.html | 4 +-- .../item-types/shared/item.component.ts | 14 ++++++++-- .../untyped-item/untyped-item.component.html | 4 +-- src/app/app-routing-paths.ts | 2 +- .../data/dso-redirect-data.service.spec.ts | 9 +++--- .../core/data/dso-redirect-data.service.ts | 18 ++++++------ ...-search-result-grid-element.component.html | 4 +-- ...ue-search-result-grid-element.component.ts | 6 ++-- ...-search-result-grid-element.component.html | 4 +-- ...me-search-result-grid-element.component.ts | 6 ++-- ...-search-result-grid-element.component.html | 4 +-- ...al-search-result-grid-element.component.ts | 6 ++-- ...-search-result-list-element.component.html | 2 +- ...ue-search-result-list-element.component.ts | 6 ++-- ...-search-result-list-element.component.html | 2 +- ...me-search-result-list-element.component.ts | 6 ++-- ...-search-result-list-element.component.html | 2 +- ...al-search-result-list-element.component.ts | 6 ++-- .../journal-issue.component.html | 4 +-- .../journal-volume.component.html | 4 +-- .../item-pages/journal/journal.component.html | 4 +-- ...-search-result-grid-element.component.html | 4 +-- ...it-search-result-grid-element.component.ts | 6 ++-- ...-search-result-grid-element.component.html | 4 +-- ...on-search-result-grid-element.component.ts | 6 ++-- ...-search-result-grid-element.component.html | 4 +-- ...ct-search-result-grid-element.component.ts | 6 ++-- ...-search-result-list-element.component.html | 2 +- ...it-search-result-list-element.component.ts | 6 ++-- ...-search-result-list-element.component.html | 2 +- ...on-search-result-list-element.component.ts | 6 ++-- ...-search-result-list-element.component.html | 2 +- ...ct-search-result-list-element.component.ts | 6 ++-- .../org-unit/org-unit.component.html | 4 +-- .../item-pages/person/person.component.html | 4 +-- .../item-pages/project/project.component.html | 4 +-- ...-item-metadata-list-element.component.html | 2 +- ...-item-metadata-list-element.component.html | 2 +- .../dso-page-edit-button.component.html | 2 +- .../dso-page-edit-button.component.spec.ts | 2 +- .../dso-page-edit-button.component.ts | 2 +- .../edit-item-selector.component.ts | 3 +- .../item-versions.component.html | 2 +- .../item-versions/item-versions.component.ts | 25 ++++++++++++++++- .../notice/item-versions-notice.component.ts | 2 +- .../item/item-actions.component.html | 2 +- .../item/item-actions.component.ts | 24 +++++++++++++--- ...-search-result-grid-element.component.html | 4 +-- ...em-search-result-grid-element.component.ts | 10 +++++++ ...a-representation-list-element.component.ts | 14 ++++++++-- ...-search-result-list-element.component.html | 2 +- ...em-search-result-list-element.component.ts | 10 +++++++ .../item-select/item-select.component.html | 2 +- .../item-select/item-select.component.ts | 24 +++++++++++++++- .../publication/publication.component.html | 2 +- .../journal-issue.component.html | 2 +- .../journal-volume.component.html | 2 +- .../item-pages/journal/journal.component.html | 2 +- .../org-unit/org-unit.component.html | 2 +- .../item-pages/person/person.component.html | 2 +- .../item-pages/project/project.component.html | 2 +- 93 files changed, 392 insertions(+), 199 deletions(-) diff --git a/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.spec.ts b/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.spec.ts index 52a9366ecc9..2696e621de1 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.spec.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.spec.ts @@ -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()); }); }); }); diff --git a/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.ts b/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.ts index 3142f5b11a8..cded519796c 100644 --- a/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.ts +++ b/src/app/+admin/admin-search-page/admin-search-results/item-admin-search-result-actions.component.ts @@ -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); } /** diff --git a/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts b/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts index 49fdfc6115c..2e7eb4e1d1d 100644 --- a/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts +++ b/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts @@ -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']); }); }); }); diff --git a/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 8db4e28f507..8a4d5846477 100644 --- a/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/+bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -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'])); }); diff --git a/src/app/+collection-page/collection-page.component.html b/src/app/+collection-page/collection-page.component.html index beb74134151..bbe2cb5e668 100644 --- a/src/app/+collection-page/collection-page.component.html +++ b/src/app/+collection-page/collection-page.component.html @@ -35,7 +35,7 @@
- +
diff --git a/src/app/+collection-page/collection-page.component.ts b/src/app/+collection-page/collection-page.component.ts index b3c10b12df4..734d84e6b74 100644 --- a/src/app/+collection-page/collection-page.component.ts +++ b/src/app/+collection-page/collection-page.component.ts @@ -15,12 +15,18 @@ 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 { getCollectionPageRoute } from './collection-page-routing-paths'; @Component({ selector: 'ds-collection-page', @@ -43,6 +49,11 @@ export class CollectionPageComponent implements OnInit { sortConfig: SortOptions }>; + /** + * Route to the community page + */ + collectionPageRoute$: Observable; + constructor( private collectionDataService: CollectionDataService, private searchService: SearchService, @@ -93,6 +104,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$); this.onPaginationChange(params); diff --git a/src/app/+community-page/community-page.component.html b/src/app/+community-page/community-page.component.html index 418e69ed107..1b4f90a52b9 100644 --- a/src/app/+community-page/community-page.component.html +++ b/src/app/+community-page/community-page.component.html @@ -21,7 +21,7 @@
- +
diff --git a/src/app/+community-page/community-page.component.ts b/src/app/+community-page/community-page.component.ts index e4812e65141..7ba8dfc6c09 100644 --- a/src/app/+community-page/community-page.component.ts +++ b/src/app/+community-page/community-page.component.ts @@ -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>; + + /** + * Route to the community page + */ + communityPageRoute$: Observable; + constructor( private communityDataService: CommunityDataService, private metadata: MetadataService, @@ -55,6 +62,10 @@ export class CommunityPageComponent implements OnInit { map((rd: RemoteData) => rd.payload), filter((community: Community) => hasValue(community)), mergeMap((community: Community) => community.logo)); + this.communityPageRoute$ = this.communityRD$.pipe( + getAllSucceededRemoteDataPayload(), + map((community) => getCommunityPageRoute(community.id)) + ); } } diff --git a/src/app/+item-page/bitstreams/upload/upload-bitstream.component.ts b/src/app/+item-page/bitstreams/upload/upload-bitstream.component.ts index f1b5fadf129..76357584631 100644 --- a/src/app/+item-page/bitstreams/upload/upload-bitstream.component.ts +++ b/src/app/+item-page/bitstreams/upload/upload-bitstream.component.ts @@ -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) => 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']); } /** diff --git a/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts b/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts index 7c20de42e33..38abbecb66f 100644 --- a/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts +++ b/src/app/+item-page/edit-item-page/abstract-item-update/abstract-item-update.component.ts @@ -11,6 +11,7 @@ import { first, map } 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'; @Component({ selector: 'ds-abstract-item-update', @@ -30,6 +31,11 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl */ updates$: Observable; + /** + * Route to the item's page + */ + itemPageRoute: string; + constructor( public itemService: ItemDataService, public objectUpdatesService: ObjectUpdatesService, @@ -52,6 +58,7 @@ export class AbstractItemUpdateComponent extends AbstractTrackableComponent impl map((data: RemoteData) => data.payload) ).subscribe((item: Item) => { this.item = item; + this.itemPageRoute = getItemPageRoute(this.item); this.postItemInit(); }); diff --git a/src/app/+item-page/edit-item-page/edit-item-page.component.ts b/src/app/+item-page/edit-item-page/edit-item-page.component.ts index 218a60a2de7..ec7cdb022df 100644 --- a/src/app/+item-page/edit-item-page/edit-item-page.component.ts +++ b/src/app/+item-page/edit-item-page/edit-item-page.component.ts @@ -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); } } diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html b/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html index 82ca1f58d9d..9ab20298969 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html @@ -1,7 +1,7 @@
diff --git a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html index c28ef9b5257..b732e6a9505 100644 --- a/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html +++ b/src/app/+item-page/edit-item-page/item-bitstreams/item-edit-bitstream-bundle/item-edit-bitstream-bundle.component.html @@ -8,7 +8,7 @@
- - diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts index ef78d11de5b..116a0feb213 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.spec.ts @@ -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)]); }); }); }); diff --git a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts index ff8e8540d50..366b22bec73 100644 --- a/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts +++ b/src/app/+item-page/edit-item-page/item-delete/item-delete.component.ts @@ -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)]); } } } diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.html b/src/app/+item-page/edit-item-page/item-move/item-move.component.html index cf5ada77cff..74ca9aae4ea 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.html +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.html @@ -19,7 +19,7 @@

{{'item.edit.move.head' | translate: {id: (itemRD$ | async)?.payload?.handle

-
+

@@ -39,7 +39,7 @@

{{'item.edit.move.head' | translate: {id: (itemRD$ | async)?.payload?.handle {{'item.edit.move.processing' | translate}} - diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts index 7f9b53f7bac..dd91c65e1e1 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.spec.ts @@ -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(); diff --git a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts index c63caef3ea9..b1ed121b40f 100644 --- a/src/app/+item-page/edit-item-page/item-move/item-move.component.ts +++ b/src/app/+item-page/edit-item-page/item-move/item-move.component.ts @@ -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; + 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>; + 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) => { - 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 { diff --git a/src/app/+item-page/edit-item-page/item-reinstate/item-reinstate.component.spec.ts b/src/app/+item-page/edit-item-page/item-reinstate/item-reinstate.component.spec.ts index 8e08b333ce0..594e7b806a7 100644 --- a/src/app/+item-page/edit-item-page/item-reinstate/item-reinstate.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-reinstate/item-reinstate.component.spec.ts @@ -47,9 +47,9 @@ describe('ItemReinstateComponent', () => { routeStub = { data: observableOf({ - dso: createSuccessfulRemoteDataObject({ + dso: createSuccessfulRemoteDataObject(Object.assign(new Item(), { id: 'fake-id' - }) + })) }) }; diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.html b/src/app/+item-page/edit-item-page/item-status/item-status.component.html index 3fcf10a2f52..d4f61c99c1b 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.html +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.html @@ -12,7 +12,7 @@ {{'item.edit.tabs.status.labels.itemPage' | translate}}:

diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts index 63d15d62d8f..0829480670d 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.spec.ts @@ -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: { diff --git a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts index 498a39d1607..2745fc8df78 100644 --- a/src/app/+item-page/edit-item-page/item-status/item-status.component.ts +++ b/src/app/+item-page/edit-item-page/item-status/item-status.component.ts @@ -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; + 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) { diff --git a/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.html b/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.html index fef76231c6a..73793ede057 100644 --- a/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.html +++ b/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.html @@ -6,11 +6,11 @@

{{headerMessage | translate: {id: item.handle} }}

-
- \ No newline at end of file + diff --git a/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.spec.ts b/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.spec.ts index 78ef2def9ed..9a19837665c 100644 --- a/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.spec.ts +++ b/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.spec.ts @@ -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)]); }); }); diff --git a/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.ts b/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.ts index 7d374e85e07..f4028354de6 100644 --- a/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.ts +++ b/src/app/+item-page/edit-item-page/simple-item-action/abstract-simple-item-action.component.ts @@ -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>; 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)]); } } diff --git a/src/app/+item-page/full/full-item-page.component.html b/src/app/+item-page/full/full-item-page.component.html index 762390c7d44..349dd1c9287 100644 --- a/src/app/+item-page/full/full-item-page.component.html +++ b/src/app/+item-page/full/full-item-page.component.html @@ -7,11 +7,11 @@
- +
diff --git a/src/app/+item-page/item-page-routing-paths.ts b/src/app/+item-page/item-page-routing-paths.ts index 1a7c23c430e..0cf6907ac23 100644 --- a/src/app/+item-page/item-page-routing-paths.ts +++ b/src/app/+item-page/item-page-routing-paths.ts @@ -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', entityType, 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'; diff --git a/src/app/+item-page/simple/item-page.component.ts b/src/app/+item-page/simple/item-page.component.ts index 3267cf743af..67e278c2fb9 100644 --- a/src/app/+item-page/simple/item-page.component.ts +++ b/src/app/+item-page/simple/item-page.component.ts @@ -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; + 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)) + ); } } diff --git a/src/app/+item-page/simple/item-types/publication/publication.component.html b/src/app/+item-page/simple/item-types/publication/publication.component.html index ae3d62a1089..fc8d06ac106 100644 --- a/src/app/+item-page/simple/item-types/publication/publication.component.html +++ b/src/app/+item-page/simple/item-types/publication/publication.component.html @@ -3,7 +3,7 @@

{{'publication.page.titleprefix' | translate}}

- +
@@ -74,7 +74,7 @@

diff --git a/src/app/+item-page/simple/item-types/shared/item.component.ts b/src/app/+item-page/simple/item-types/shared/item.component.ts index a3dfbee814b..a8119c8565d 100644 --- a/src/app/+item-page/simple/item-types/shared/item.component.ts +++ b/src/app/+item-page/simple/item-types/shared/item.component.ts @@ -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 { return this.bitstreamDataService.getThumbnailFor(this.object).pipe( diff --git a/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html b/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html index dcb73fad106..241696f688a 100644 --- a/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html +++ b/src/app/+item-page/simple/item-types/untyped-item/untyped-item.component.html @@ -3,7 +3,7 @@

- +

@@ -59,7 +59,7 @@

diff --git a/src/app/app-routing-paths.ts b/src/app/app-routing-paths.ts index 8db4ba5aa7d..949990ba437 100644 --- a/src/app/app-routing-paths.ts +++ b/src/app/app-routing-paths.ts @@ -51,7 +51,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); } } diff --git a/src/app/core/data/dso-redirect-data.service.spec.ts b/src/app/core/data/dso-redirect-data.service.spec.ts index 714774d808d..574920746ff 100644 --- a/src/app/core/data/dso-redirect-data.service.spec.ts +++ b/src/app/core/data/dso-redirect-data.service.spec.ts @@ -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,7 @@ 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'; @@ -131,7 +132,7 @@ describe('DsoRedirectDataService', () => { redir.subscribe(); scheduler.schedule(() => redir); scheduler.flush(); - expect(router.navigate).toHaveBeenCalledWith(['entities/publication/' + remoteData.payload.uuid]); + expect(router.navigate).toHaveBeenCalledWith(['/entities/Publication/' + remoteData.payload.uuid]); }); it('should navigate to collections route', () => { diff --git a/src/app/core/data/dso-redirect-data.service.ts b/src/app/core/data/dso-redirect-data.service.ts index 688c3e19636..ffe260fd8e5 100644 --- a/src/app/core/data/dso-redirect-data.service.ts +++ b/src/app/core/data/dso-redirect-data.service.ts @@ -20,6 +20,7 @@ import { getFirstCompletedRemoteData } from '../shared/operators'; import { DSpaceObject } from '../shared/dspace-object.model'; import { Item } from '../shared/item.model'; import { Metadata } from '../shared/metadata.utils'; +import { getItemPageRoute } from '../../+item-page/item-page-routing-paths'; @Injectable() export class DsoRedirectDataService extends DataService { @@ -64,15 +65,16 @@ export class DsoRedirectDataService extends DataService { if (response.hasSucceeded) { const dso = response.payload; const uuid = dso.uuid; - let newRoute = this.getEndpointFromDSOType(response.payload.type); - if (dso.type.startsWith('item')) { - const relation = Metadata.firstValue(dso.metadata, 'relationship.type'); - if (hasValue(relation)) { - newRoute = `entities/${relation.toLowerCase()}`; + 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]); } - } - if (hasValue(uuid) && hasValue(newRoute)) { - this.router.navigate([newRoute + '/' + uuid]); } } }) diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html index 8d1ed60733f..df6c9e60c03 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html @@ -5,7 +5,7 @@

diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts index 9d27842c165..a2a6c91d2d5 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.ts @@ -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 { +export class JournalIssueSearchResultGridElementComponent extends ItemSearchResultGridElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html index 82f483e3cff..cdc19b7f14d 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html @@ -5,7 +5,7 @@ diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts index 802a6d8692a..17c8575a0e9 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.ts @@ -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 { +export class JournalVolumeSearchResultGridElementComponent extends ItemSearchResultGridElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html index 2da30076d42..bacd657663d 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html @@ -5,7 +5,7 @@ diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts index 97d43356c69..4fa554ff3b1 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.ts @@ -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 { +export class JournalSearchResultGridElementComponent extends ItemSearchResultGridElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html index 3ddf3611d14..0e783a48437 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html @@ -1,7 +1,7 @@ { +export class JournalIssueSearchResultListElementComponent extends ItemSearchResultListElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html index 778877fbe26..9bdb9a30cd2 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-volume/journal-volume-search-result-list-element.component.html @@ -1,7 +1,7 @@ { +export class JournalVolumeSearchResultListElementComponent extends ItemSearchResultListElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html index a18d75275b8..9692d30192e 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal/journal-search-result-list-element.component.html @@ -1,7 +1,7 @@ { +export class JournalSearchResultListElementComponent extends ItemSearchResultListElementComponent { } diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html index c5eb3ba59ec..5749c5797d6 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html @@ -3,7 +3,7 @@

{{'journalissue.page.titleprefix' | translate}}

- +
@@ -53,7 +53,7 @@

[label]="'journalissue.page.keyword'"> diff --git a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html index 38a201df167..2c2a4995c2e 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html @@ -3,7 +3,7 @@

{{'journalvolume.page.titleprefix' | translate}}

- +
@@ -36,7 +36,7 @@

[label]="'journalvolume.page.description'"> diff --git a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html index 874f748049c..49fdc935c5b 100644 --- a/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html +++ b/src/app/entity-groups/journal-entities/item-pages/journal/journal.component.html @@ -3,7 +3,7 @@

{{'journal.page.titleprefix' | translate}}

- +
@@ -35,7 +35,7 @@

[label]="'journal.page.description'"> diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html index c2e1efc7c9e..2c3087d701c 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html @@ -5,7 +5,7 @@

diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts index 64b4be4a115..872b4b27e38 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.ts @@ -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 { +export class OrgUnitSearchResultGridElementComponent extends ItemSearchResultGridElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html index ff0afcbdb20..005fa9cc831 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html @@ -5,7 +5,7 @@ diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts index 55bc4f5a0de..851d9007554 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.ts @@ -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 { +export class PersonSearchResultGridElementComponent extends ItemSearchResultGridElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html index 61f9b44a442..e84e8c49d06 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html @@ -5,7 +5,7 @@ diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts index a352d2dcb08..6dfbe93e3e1 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.ts @@ -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 { +export class ProjectSearchResultGridElementComponent extends ItemSearchResultGridElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html index c0d98ccf43a..fb0ad21b6e1 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html @@ -1,7 +1,7 @@ { +export class OrgUnitSearchResultListElementComponent extends ItemSearchResultListElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html index 634acf10246..c8a9ea9e289 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/person/person-search-result-list-element.component.html @@ -1,7 +1,7 @@ { +export class PersonSearchResultListElementComponent extends ItemSearchResultListElementComponent { get name() { return this.value ? diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html index b881c706003..4f82e78739d 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/project/project-search-result-list-element.component.html @@ -1,7 +1,7 @@ { +export class ProjectSearchResultListElementComponent extends ItemSearchResultListElementComponent { } diff --git a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index 4d90b85133e..822d4858ce6 100644 --- a/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/src/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -3,7 +3,7 @@

{{'orgunit.page.titleprefix' | translate}}

- +
@@ -39,7 +39,7 @@

[label]="'orgunit.page.description'"> diff --git a/src/app/entity-groups/research-entities/item-pages/person/person.component.html b/src/app/entity-groups/research-entities/item-pages/person/person.component.html index 2d751eeabb2..e1c776f3662 100644 --- a/src/app/entity-groups/research-entities/item-pages/person/person.component.html +++ b/src/app/entity-groups/research-entities/item-pages/person/person.component.html @@ -3,7 +3,7 @@

{{'person.page.titleprefix' | translate}}

- +
@@ -52,7 +52,7 @@

[label]="'person.page.firstname'"> diff --git a/src/app/entity-groups/research-entities/item-pages/project/project.component.html b/src/app/entity-groups/research-entities/item-pages/project/project.component.html index 4d681bb172a..9967b940ac8 100644 --- a/src/app/entity-groups/research-entities/item-pages/project/project.component.html +++ b/src/app/entity-groups/research-entities/item-pages/project/project.component.html @@ -3,7 +3,7 @@

{{'project.page.titleprefix' | translate}}

- +
@@ -59,7 +59,7 @@

[label]="'project.page.keyword'"> diff --git a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.html index c862507bc43..1771f3d2bc6 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.html +++ b/src/app/entity-groups/research-entities/metadata-representations/org-unit/org-unit-item-metadata-list-element.component.html @@ -6,7 +6,7 @@ - diff --git a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html index 7a7509cb399..97632117f40 100644 --- a/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html +++ b/src/app/entity-groups/research-entities/metadata-representations/person/person-item-metadata-list-element.component.html @@ -9,7 +9,7 @@ - diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html index b0bb013c1b2..36661c895ae 100644 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html +++ b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.html @@ -1,5 +1,5 @@ diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts index d3f9ec98ae2..5949a98f711 100644 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts +++ b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.spec.ts @@ -40,7 +40,7 @@ describe('DsoPageEditButtonComponent', () => { fixture = TestBed.createComponent(DsoPageEditButtonComponent); component = fixture.componentInstance; component.dso = dso; - component.pageRoutePrefix = 'test'; + component.pageRoute = 'test'; fixture.detectChanges(); }); diff --git a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts index 230855a5a2f..ebdb5e5181d 100644 --- a/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts +++ b/src/app/shared/dso-page/dso-page-edit-button/dso-page-edit-button.component.ts @@ -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 diff --git a/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts index 5288c1a1979..f79a067ea73 100644 --- a/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts +++ b/src/app/shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component.ts @@ -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)]); } } diff --git a/src/app/shared/item/item-versions/item-versions.component.html b/src/app/shared/item/item-versions/item-versions.component.html index 6e93f4c7ca3..44fc2a10230 100644 --- a/src/app/shared/item/item-versions/item-versions.component.html +++ b/src/app/shared/item/item-versions/item-versions.component.html @@ -25,7 +25,7 @@

{{"item.version.history.head" | translate}}

{{version?.version}} -
{{item?.handle}} + {{item?.handle}} * diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/shared/item/item-versions/item-versions.component.ts index 9c4682642a3..b7ba823b9a0 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/shared/item/item-versions/item-versions.component.ts @@ -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(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) => 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; + }) + ); } /** diff --git a/src/app/shared/item/item-versions/notice/item-versions-notice.component.ts b/src/app/shared/item/item-versions/notice/item-versions-notice.component.ts index d631cc35da9..e4dbe0b8387 100644 --- a/src/app/shared/item/item-versions/notice/item-versions-notice.component.ts +++ b/src/app/shared/item/item-versions/notice/item-versions-notice.component.ts @@ -109,7 +109,7 @@ export class ItemVersionsNoticeComponent implements OnInit { */ getItemPage(item: Item): string { if (hasValue(item)) { - return getItemPageRoute(item.id); + return getItemPageRoute(item); } } } diff --git a/src/app/shared/mydspace-actions/item/item-actions.component.html b/src/app/shared/mydspace-actions/item/item-actions.component.html index 91993466b61..0f085c453e1 100644 --- a/src/app/shared/mydspace-actions/item/item-actions.component.html +++ b/src/app/shared/mydspace-actions/item/item-actions.component.html @@ -1,5 +1,5 @@ diff --git a/src/app/shared/mydspace-actions/item/item-actions.component.ts b/src/app/shared/mydspace-actions/item/item-actions.component.ts index 8026303c618..c4ae0544fc1 100644 --- a/src/app/shared/mydspace-actions/item/item-actions.component.ts +++ b/src/app/shared/mydspace-actions/item/item-actions.component.ts @@ -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 { +export class ItemActionsComponent extends MyDSpaceActionsComponent 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

- diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts index e7297564523..619a980e9b1 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item/item-search-result-grid-element.component.ts @@ -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 { + /** + * Route to the item's page + */ + itemPageRoute: string; + + ngOnInit(): void { + super.ngOnInit(); + this.itemPageRoute = getItemPageRoute(this.dso); + } } diff --git a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts index 6c4d300e994..51fd6f8d36c 100644 --- a/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts +++ b/src/app/shared/object-list/metadata-representation-list-element/item/item-metadata-representation-list-element.component.ts @@ -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); + } } diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html index 880f4393cd0..01a026eec9b 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.html @@ -2,7 +2,7 @@ diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts index b4b658cb963..a955be558ff 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component.ts @@ -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 { + /** + * Route to the item's page + */ + itemPageRoute: string; + + ngOnInit(): void { + super.ngOnInit(); + this.itemPageRoute = getItemPageRoute(this.dso); + } } diff --git a/src/app/shared/object-select/item-select/item-select.component.html b/src/app/shared/object-select/item-select/item-select.component.html index da31dbac657..dab5b2f7155 100644 --- a/src/app/shared/object-select/item-select/item-select.component.html +++ b/src/app/shared/object-select/item-select/item-select.component.html @@ -26,7 +26,7 @@
{{item.firstMetadataValue(['dc.contributor.author', 'dc.creator', 'dc.contributor.*'])}} - {{item.firstMetadataValue("dc.title")}} + {{item.firstMetadataValue("dc.title")}} diff --git a/src/app/shared/object-select/item-select/item-select.component.ts b/src/app/shared/object-select/item-select/item-select.component.ts index 7dd82399603..f4e07dc1f8a 100644 --- a/src/app/shared/object-select/item-select/item-select.component.ts +++ b/src/app/shared/object-select/item-select/item-select.component.ts @@ -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 { @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 { 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; + }) + ); } } diff --git a/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html index adecd9e1afa..705d40a7c75 100644 --- a/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html +++ b/themes/mantis/app/+item-page/simple/item-types/publication/publication.component.html @@ -8,7 +8,7 @@ diff --git a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html index 78a0eba13e6..eb872ca1758 100644 --- a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html +++ b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html @@ -8,7 +8,7 @@ diff --git a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html index 3dca7dfbbad..bc11d4ba748 100644 --- a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html +++ b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal-volume/journal-volume.component.html @@ -8,7 +8,7 @@ diff --git a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html index ed542c7840b..cf4cef27dee 100644 --- a/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html +++ b/themes/mantis/app/entity-groups/journal-entities/item-pages/journal/journal.component.html @@ -7,7 +7,7 @@ diff --git a/themes/mantis/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html b/themes/mantis/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html index ae003e31a8d..114443468a3 100644 --- a/themes/mantis/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html +++ b/themes/mantis/app/entity-groups/research-entities/item-pages/org-unit/org-unit.component.html @@ -9,7 +9,7 @@ diff --git a/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html b/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html index dbcb76a2929..077ac1b9f1a 100644 --- a/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html +++ b/themes/mantis/app/entity-groups/research-entities/item-pages/person/person.component.html @@ -9,7 +9,7 @@ diff --git a/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html b/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html index b31353ef76f..e5b0884f14e 100644 --- a/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html +++ b/themes/mantis/app/entity-groups/research-entities/item-pages/project/project.component.html @@ -9,7 +9,7 @@ From 1d9d174f872af6d4255745945f90f925edab87b2 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Tue, 19 Jan 2021 11:38:11 +0100 Subject: [PATCH 4/7] 75940: Item page redirects --- src/app/+item-page/item-page.resolver.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/app/+item-page/item-page.resolver.ts b/src/app/+item-page/item-page.resolver.ts index 44c86f3b9cd..2f5af075a89 100644 --- a/src/app/+item-page/item-page.resolver.ts +++ b/src/app/+item-page/item-page.resolver.ts @@ -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'; @@ -7,13 +7,17 @@ import { Item } from '../core/shared/item.model'; import { followLink } from '../shared/utils/follow-link-config.model'; import { FindListOptions } from '../core/data/request.models'; import { getFirstCompletedRemoteData } from '../core/shared/operators'; +import { map } from 'rxjs/operators'; +import { hasValue } from '../shared/empty.util'; +import { getItemPageRoute } from './item-page-routing-paths'; /** * This class represents a resolver that requests a specific item before the route is activated */ @Injectable() export class ItemPageResolver implements Resolve> { - constructor(private itemService: ItemDataService) { + constructor(private itemService: ItemDataService, + private router: Router) { } /** @@ -33,6 +37,18 @@ export class ItemPageResolver implements Resolve> { followLink('version', undefined, true, true, true, followLink('versionhistory')), ).pipe( getFirstCompletedRemoteData(), + map((rd: RemoteData) => { + 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; + }) ); } } From 694d45fd2c9b8982217d5d2c124864eb42702685 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Fri, 22 Jan 2021 17:07:15 +0100 Subject: [PATCH 5/7] 75939: Encode and lowercase entity type url --- src/app/+item-page/item-page-routing-paths.ts | 2 +- src/app/core/data/dso-redirect-data.service.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/+item-page/item-page-routing-paths.ts b/src/app/+item-page/item-page-routing-paths.ts index 0cf6907ac23..b153f53c261 100644 --- a/src/app/+item-page/item-page-routing-paths.ts +++ b/src/app/+item-page/item-page-routing-paths.ts @@ -24,7 +24,7 @@ export function getItemEditRoute(item: Item) { export function getEntityPageRoute(entityType: string, itemId: string) { if (isNotEmpty(entityType)) { - return new URLCombiner('/entities', entityType, itemId).toString(); + return new URLCombiner('/entities', encodeURIComponent(entityType.toLowerCase()), itemId).toString(); } else { return new URLCombiner(getItemModuleRoute(), itemId).toString(); } diff --git a/src/app/core/data/dso-redirect-data.service.spec.ts b/src/app/core/data/dso-redirect-data.service.spec.ts index 574920746ff..43489fbf6d4 100644 --- a/src/app/core/data/dso-redirect-data.service.spec.ts +++ b/src/app/core/data/dso-redirect-data.service.spec.ts @@ -132,7 +132,7 @@ describe('DsoRedirectDataService', () => { redir.subscribe(); scheduler.schedule(() => redir); scheduler.flush(); - expect(router.navigate).toHaveBeenCalledWith(['/entities/Publication/' + remoteData.payload.uuid]); + expect(router.navigate).toHaveBeenCalledWith(['/entities/publication/' + remoteData.payload.uuid]); }); it('should navigate to collections route', () => { From 7ce8b3d460d826aec7d2021d794a4afb76e416a1 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Wed, 27 Jan 2021 12:58:38 +0100 Subject: [PATCH 6/7] 75940: missing semicolons --- src/app/+item-page/item-page-routing-paths.ts | 2 +- src/app/shared/item/item-versions/item-versions.component.ts | 2 +- .../shared/object-select/item-select/item-select.component.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/+item-page/item-page-routing-paths.ts b/src/app/+item-page/item-page-routing-paths.ts index b153f53c261..8ad5583269f 100644 --- a/src/app/+item-page/item-page-routing-paths.ts +++ b/src/app/+item-page/item-page-routing-paths.ts @@ -19,7 +19,7 @@ export function getItemPageRoute(item: Item) { } export function getItemEditRoute(item: Item) { - return new URLCombiner(getItemPageRoute(item), ITEM_EDIT_PATH).toString() + return new URLCombiner(getItemPageRoute(item), ITEM_EDIT_PATH).toString(); } export function getEntityPageRoute(entityType: string, itemId: string) { diff --git a/src/app/shared/item/item-versions/item-versions.component.ts b/src/app/shared/item/item-versions/item-versions.component.ts index b7ba823b9a0..d25fdaa4f15 100644 --- a/src/app/shared/item/item-versions/item-versions.component.ts +++ b/src/app/shared/item/item-versions/item-versions.component.ts @@ -98,7 +98,7 @@ export class ItemVersionsComponent implements OnInit { */ itemPageRoutes$: Observable<{ [itemId: string]: string - }> + }>; constructor(private versionHistoryService: VersionHistoryDataService) { } diff --git a/src/app/shared/object-select/item-select/item-select.component.ts b/src/app/shared/object-select/item-select/item-select.component.ts index f4e07dc1f8a..b4918ada99e 100644 --- a/src/app/shared/object-select/item-select/item-select.component.ts +++ b/src/app/shared/object-select/item-select/item-select.component.ts @@ -31,7 +31,7 @@ export class ItemSelectComponent extends ObjectSelectComponent { */ itemPageRoutes$: Observable<{ [itemId: string]: string - }> + }>; constructor(protected objectSelectService: ObjectSelectService) { super(objectSelectService); From 91b647e6e5f703cc1a826c66b20ef4fa0250e993 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Thu, 11 Feb 2021 17:42:53 +0100 Subject: [PATCH 7/7] 75940: Unused import fix --- src/app/core/data/dso-redirect-data.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app/core/data/dso-redirect-data.service.ts b/src/app/core/data/dso-redirect-data.service.ts index ffe260fd8e5..693ae0b41ab 100644 --- a/src/app/core/data/dso-redirect-data.service.ts +++ b/src/app/core/data/dso-redirect-data.service.ts @@ -19,7 +19,6 @@ import { RequestService } from './request.service'; import { getFirstCompletedRemoteData } from '../shared/operators'; import { DSpaceObject } from '../shared/dspace-object.model'; import { Item } from '../shared/item.model'; -import { Metadata } from '../shared/metadata.utils'; import { getItemPageRoute } from '../../+item-page/item-page-routing-paths'; @Injectable()