mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
[CST-12235] support for the LDN inbox for root & /home & /item/:uuid pages
This commit is contained in:
@@ -10,7 +10,10 @@ import { ConfigurationProperty } from '../../shared/configuration-property.model
|
|||||||
})
|
})
|
||||||
export class NotifyInfoService {
|
export class NotifyInfoService {
|
||||||
|
|
||||||
private relationLink = 'http://www.w3.org/ns/ldp#inbox';
|
/**
|
||||||
|
* The relation link for the inbox
|
||||||
|
*/
|
||||||
|
private _inboxRelationLink = 'http://www.w3.org/ns/ldp#inbox';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private configService: ConfigurationDataService,
|
private configService: ConfigurationDataService,
|
||||||
@@ -27,7 +30,11 @@ export class NotifyInfoService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCoarLdnLocalInboxUrl(): Observable<string[]> {
|
/**
|
||||||
|
* Get the url of the local inbox from the REST configuration
|
||||||
|
* @returns the url of the local inbox
|
||||||
|
*/
|
||||||
|
getCoarLdnLocalInboxUrls(): Observable<string[]> {
|
||||||
return this.configService.findByPropertyName('ldn.notify.local-inbox-endpoint').pipe(
|
return this.configService.findByPropertyName('ldn.notify.local-inbox-endpoint').pipe(
|
||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
getRemoteDataPayload(),
|
getRemoteDataPayload(),
|
||||||
@@ -49,7 +56,11 @@ export class NotifyInfoService {
|
|||||||
return `${ssl ? 'https' : 'http'}://${host}:${port}${namespace}`;
|
return `${ssl ? 'https' : 'http'}://${host}:${port}${namespace}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRelationLink(): string{
|
/**
|
||||||
return this.relationLink;
|
* Method to get the relation link for the inbox
|
||||||
|
* @returns the relation link for the inbox
|
||||||
|
*/
|
||||||
|
getInboxRelationLink(): string {
|
||||||
|
return this._inboxRelationLink;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +1,28 @@
|
|||||||
import { Component, Inject, OnInit, PLATFORM_ID } from '@angular/core';
|
import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { Site } from '../core/shared/site.model';
|
import { Site } from '../core/shared/site.model';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
import { isPlatformServer } from '@angular/common';
|
import { isPlatformServer } from '@angular/common';
|
||||||
import { ServerResponseService } from '../core/services/server-response.service';
|
import { ServerResponseService } from '../core/services/server-response.service';
|
||||||
import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service';
|
import { NotifyInfoService } from '../core/coar-notify/notify-info/notify-info.service';
|
||||||
import { LinkDefinition, LinkHeadService } from '../core/services/link-head.service';
|
import { LinkDefinition, LinkHeadService } from '../core/services/link-head.service';
|
||||||
|
import { isNotEmpty } from '../shared/empty.util';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-home-page',
|
selector: 'ds-home-page',
|
||||||
styleUrls: ['./home-page.component.scss'],
|
styleUrls: ['./home-page.component.scss'],
|
||||||
templateUrl: './home-page.component.html'
|
templateUrl: './home-page.component.html'
|
||||||
})
|
})
|
||||||
export class HomePageComponent implements OnInit {
|
export class HomePageComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
site$: Observable<Site>;
|
site$: Observable<Site>;
|
||||||
recentSubmissionspageSize: number;
|
recentSubmissionspageSize: number;
|
||||||
|
/**
|
||||||
|
* An array of LinkDefinition objects representing inbox links for the home page.
|
||||||
|
*/
|
||||||
|
inboxLinks: LinkDefinition[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@@ -27,14 +32,18 @@ export class HomePageComponent implements OnInit {
|
|||||||
@Inject(PLATFORM_ID) private platformId: string
|
@Inject(PLATFORM_ID) private platformId: string
|
||||||
) {
|
) {
|
||||||
this.recentSubmissionspageSize = environment.homePage.recentSubmissions.pageSize;
|
this.recentSubmissionspageSize = environment.homePage.recentSubmissions.pageSize;
|
||||||
|
// Get COAR REST API URLs from REST configuration
|
||||||
|
// only if COAR configuration is enabled
|
||||||
this.notifyInfoService.isCoarConfigEnabled().pipe(
|
this.notifyInfoService.isCoarConfigEnabled().pipe(
|
||||||
switchMap((coarLdnEnabled: boolean) => {
|
switchMap((coarLdnEnabled: boolean) => {
|
||||||
if (coarLdnEnabled) {
|
if (coarLdnEnabled) {
|
||||||
return this.notifyInfoService.getCoarLdnLocalInboxUrl();
|
return this.notifyInfoService.getCoarLdnLocalInboxUrls();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
).subscribe((coarRestApiUrls: string[]) => {
|
).subscribe((coarRestApiUrls: string[]) => {
|
||||||
this.initPageLinks(coarRestApiUrls);
|
if (coarRestApiUrls.length > 0) {
|
||||||
|
this.initPageLinks(coarRestApiUrls);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,17 +53,37 @@ export class HomePageComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes page links for COAR REST API URLs.
|
||||||
|
* @param coarRestApiUrls An array of COAR REST API URLs.
|
||||||
|
*/
|
||||||
private initPageLinks(coarRestApiUrls: string[]): void {
|
private initPageLinks(coarRestApiUrls: string[]): void {
|
||||||
const rel = this.notifyInfoService.getRelationLink();
|
const rel = this.notifyInfoService.getInboxRelationLink();
|
||||||
|
let links = '';
|
||||||
coarRestApiUrls.forEach((coarRestApiUrl: string) => {
|
coarRestApiUrls.forEach((coarRestApiUrl: string) => {
|
||||||
|
// Add link to head
|
||||||
let tag: LinkDefinition = {
|
let tag: LinkDefinition = {
|
||||||
href: coarRestApiUrl,
|
href: coarRestApiUrl,
|
||||||
rel: rel
|
rel: rel
|
||||||
};
|
};
|
||||||
|
this.inboxLinks.push(tag);
|
||||||
this.linkHeadService.addTag(tag);
|
this.linkHeadService.addTag(tag);
|
||||||
if (isPlatformServer(this.platformId)) {
|
|
||||||
this.responseService.setHeader('Link', `<${coarRestApiUrl}>; rel="${rel}"`);
|
links = links + (isNotEmpty(links) ? ', ' : '') + `<${coarRestApiUrl}> ; rel="${rel}"`;
|
||||||
}
|
});
|
||||||
|
|
||||||
|
if (isPlatformServer(this.platformId)) {
|
||||||
|
// Add link to response header
|
||||||
|
this.responseService.setHeader('Link', links);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It removes the inbox links from the head of the html.
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.inboxLinks.forEach((link: LinkDefinition) => {
|
||||||
|
this.linkHeadService.removeTag(`href='${link.href}'`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import { RemoteData } from '../../core/data/remote-data';
|
|||||||
import { ServerResponseService } from '../../core/services/server-response.service';
|
import { ServerResponseService } from '../../core/services/server-response.service';
|
||||||
import { SignpostingDataService } from '../../core/data/signposting-data.service';
|
import { SignpostingDataService } from '../../core/data/signposting-data.service';
|
||||||
import { LinkHeadService } from '../../core/services/link-head.service';
|
import { LinkHeadService } from '../../core/services/link-head.service';
|
||||||
|
import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service';
|
||||||
|
|
||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
|
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
|
||||||
@@ -122,6 +123,7 @@ describe('FullItemPageComponent', () => {
|
|||||||
{ provide: ServerResponseService, useValue: serverResponseService },
|
{ provide: ServerResponseService, useValue: serverResponseService },
|
||||||
{ provide: SignpostingDataService, useValue: signpostingDataService },
|
{ provide: SignpostingDataService, useValue: signpostingDataService },
|
||||||
{ provide: LinkHeadService, useValue: linkHeadService },
|
{ provide: LinkHeadService, useValue: linkHeadService },
|
||||||
|
{ provide: NotifyInfoService, useValue: {} },
|
||||||
{ provide: PLATFORM_ID, useValue: 'server' }
|
{ provide: PLATFORM_ID, useValue: 'server' }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -19,6 +19,7 @@ import { AuthorizationDataService } from '../../core/data/feature-authorization/
|
|||||||
import { ServerResponseService } from '../../core/services/server-response.service';
|
import { ServerResponseService } from '../../core/services/server-response.service';
|
||||||
import { SignpostingDataService } from '../../core/data/signposting-data.service';
|
import { SignpostingDataService } from '../../core/data/signposting-data.service';
|
||||||
import { LinkHeadService } from '../../core/services/link-head.service';
|
import { LinkHeadService } from '../../core/services/link-head.service';
|
||||||
|
import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders a full item page.
|
* This component renders a full item page.
|
||||||
@@ -55,9 +56,10 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit,
|
|||||||
protected responseService: ServerResponseService,
|
protected responseService: ServerResponseService,
|
||||||
protected signpostingDataService: SignpostingDataService,
|
protected signpostingDataService: SignpostingDataService,
|
||||||
protected linkHeadService: LinkHeadService,
|
protected linkHeadService: LinkHeadService,
|
||||||
|
protected notifyInfoService: NotifyInfoService,
|
||||||
@Inject(PLATFORM_ID) protected platformId: string,
|
@Inject(PLATFORM_ID) protected platformId: string,
|
||||||
) {
|
) {
|
||||||
super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService, platformId);
|
super(route, router, items, authService, authorizationService, responseService, signpostingDataService, linkHeadService,notifyInfoService, platformId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** AoT inheritance fix, will hopefully be resolved in the near future **/
|
/*** AoT inheritance fix, will hopefully be resolved in the near future **/
|
||||||
|
@@ -26,6 +26,7 @@ import { ServerResponseService } from '../../core/services/server-response.servi
|
|||||||
import { SignpostingDataService } from '../../core/data/signposting-data.service';
|
import { SignpostingDataService } from '../../core/data/signposting-data.service';
|
||||||
import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service';
|
import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service';
|
||||||
import { SignpostingLink } from '../../core/data/signposting-links.model';
|
import { SignpostingLink } from '../../core/data/signposting-links.model';
|
||||||
|
import { NotifyInfoService } from '../../core/coar-notify/notify-info/notify-info.service';
|
||||||
|
|
||||||
const mockItem: Item = Object.assign(new Item(), {
|
const mockItem: Item = Object.assign(new Item(), {
|
||||||
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
|
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
|
||||||
@@ -62,6 +63,7 @@ describe('ItemPageComponent', () => {
|
|||||||
let serverResponseService: jasmine.SpyObj<ServerResponseService>;
|
let serverResponseService: jasmine.SpyObj<ServerResponseService>;
|
||||||
let signpostingDataService: jasmine.SpyObj<SignpostingDataService>;
|
let signpostingDataService: jasmine.SpyObj<SignpostingDataService>;
|
||||||
let linkHeadService: jasmine.SpyObj<LinkHeadService>;
|
let linkHeadService: jasmine.SpyObj<LinkHeadService>;
|
||||||
|
let notifyInfoService: jasmine.SpyObj<NotifyInfoService>;
|
||||||
|
|
||||||
const mockMetadataService = {
|
const mockMetadataService = {
|
||||||
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */
|
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */
|
||||||
@@ -94,6 +96,12 @@ describe('ItemPageComponent', () => {
|
|||||||
removeTag: jasmine.createSpy('removeTag'),
|
removeTag: jasmine.createSpy('removeTag'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
notifyInfoService = jasmine.createSpyObj('NotifyInfoService', {
|
||||||
|
getInboxRelationLink: 'http://www.w3.org/ns/ldp#inbox',
|
||||||
|
isCoarConfigEnabled: observableOf(true),
|
||||||
|
getCoarLdnLocalInboxUrls: observableOf(['http://test.org', 'http://test2.org']),
|
||||||
|
});
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [TranslateModule.forRoot({
|
imports: [TranslateModule.forRoot({
|
||||||
loader: {
|
loader: {
|
||||||
@@ -112,6 +120,7 @@ describe('ItemPageComponent', () => {
|
|||||||
{ provide: ServerResponseService, useValue: serverResponseService },
|
{ provide: ServerResponseService, useValue: serverResponseService },
|
||||||
{ provide: SignpostingDataService, useValue: signpostingDataService },
|
{ provide: SignpostingDataService, useValue: signpostingDataService },
|
||||||
{ provide: LinkHeadService, useValue: linkHeadService },
|
{ provide: LinkHeadService, useValue: linkHeadService },
|
||||||
|
{ provide: NotifyInfoService, useValue: notifyInfoService},
|
||||||
{ provide: PLATFORM_ID, useValue: 'server' },
|
{ provide: PLATFORM_ID, useValue: 'server' },
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@@ -2,8 +2,8 @@ import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit, PLATFORM
|
|||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { isPlatformServer } from '@angular/common';
|
import { isPlatformServer } from '@angular/common';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable, combineLatest } from 'rxjs';
|
||||||
import { map, take } from 'rxjs/operators';
|
import { map, switchMap, take } from 'rxjs/operators';
|
||||||
|
|
||||||
import { ItemDataService } from '../../core/data/item-data.service';
|
import { ItemDataService } from '../../core/data/item-data.service';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
@@ -21,6 +21,7 @@ import { SignpostingDataService } from '../../core/data/signposting-data.service
|
|||||||
import { SignpostingLink } from '../../core/data/signposting-links.model';
|
import { SignpostingLink } from '../../core/data/signposting-links.model';
|
||||||
import { isNotEmpty } from '../../shared/empty.util';
|
import { isNotEmpty } from '../../shared/empty.util';
|
||||||
import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service';
|
import { LinkDefinition, LinkHeadService } from '../../core/services/link-head.service';
|
||||||
|
import { NotifyInfoService } from 'src/app/core/coar-notify/notify-info/notify-info.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component renders a simple item page.
|
* This component renders a simple item page.
|
||||||
@@ -68,6 +69,13 @@ export class ItemPageComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
signpostingLinks: SignpostingLink[] = [];
|
signpostingLinks: SignpostingLink[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of LinkDefinition objects representing inbox links for the item page.
|
||||||
|
*/
|
||||||
|
inboxTags: LinkDefinition[] = [];
|
||||||
|
|
||||||
|
coarRestApiUrls: string[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected route: ActivatedRoute,
|
protected route: ActivatedRoute,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
@@ -77,6 +85,7 @@ export class ItemPageComponent implements OnInit, OnDestroy {
|
|||||||
protected responseService: ServerResponseService,
|
protected responseService: ServerResponseService,
|
||||||
protected signpostingDataService: SignpostingDataService,
|
protected signpostingDataService: SignpostingDataService,
|
||||||
protected linkHeadService: LinkHeadService,
|
protected linkHeadService: LinkHeadService,
|
||||||
|
protected notifyInfoService: NotifyInfoService,
|
||||||
@Inject(PLATFORM_ID) protected platformId: string
|
@Inject(PLATFORM_ID) protected platformId: string
|
||||||
) {
|
) {
|
||||||
this.initPageLinks();
|
this.initPageLinks();
|
||||||
@@ -106,7 +115,8 @@ export class ItemPageComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
private initPageLinks(): void {
|
private initPageLinks(): void {
|
||||||
this.route.params.subscribe(params => {
|
this.route.params.subscribe(params => {
|
||||||
this.signpostingDataService.getLinks(params.id).pipe(take(1)).subscribe((signpostingLinks: SignpostingLink[]) => {
|
combineLatest([this.signpostingDataService.getLinks(params.id).pipe(take(1)), this.getCoarLdnLocalInboxUrls()])
|
||||||
|
.subscribe(([signpostingLinks, coarRestApiUrls]) => {
|
||||||
let links = '';
|
let links = '';
|
||||||
this.signpostingLinks = signpostingLinks;
|
this.signpostingLinks = signpostingLinks;
|
||||||
|
|
||||||
@@ -124,6 +134,11 @@ export class ItemPageComponent implements OnInit, OnDestroy {
|
|||||||
this.linkHeadService.addTag(tag);
|
this.linkHeadService.addTag(tag);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (coarRestApiUrls.length > 0) {
|
||||||
|
let inboxLinks = this.initPageInboxLinks(coarRestApiUrls);
|
||||||
|
links = links + (isNotEmpty(links) ? ', ' : '') + inboxLinks;
|
||||||
|
}
|
||||||
|
|
||||||
if (isPlatformServer(this.platformId)) {
|
if (isPlatformServer(this.platformId)) {
|
||||||
this.responseService.setHeader('Link', links);
|
this.responseService.setHeader('Link', links);
|
||||||
}
|
}
|
||||||
@@ -131,9 +146,49 @@ export class ItemPageComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the COAR LDN local inbox URL if COAR configuration is enabled.
|
||||||
|
* If the COAR LDN local inbox URL is retrieved successfully, initializes the page inbox links.
|
||||||
|
*/
|
||||||
|
private getCoarLdnLocalInboxUrls(): Observable<string[]> {
|
||||||
|
return this.notifyInfoService.isCoarConfigEnabled().pipe(
|
||||||
|
switchMap((coarLdnEnabled: boolean) => {
|
||||||
|
if (coarLdnEnabled) {
|
||||||
|
return this.notifyInfoService.getCoarLdnLocalInboxUrls();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the page inbox links.
|
||||||
|
* @param coarRestApiUrls - An array of COAR REST API URLs.
|
||||||
|
*/
|
||||||
|
private initPageInboxLinks(coarRestApiUrls: string[]): string {
|
||||||
|
const rel = this.notifyInfoService.getInboxRelationLink();
|
||||||
|
let links = '';
|
||||||
|
|
||||||
|
coarRestApiUrls.forEach((coarRestApiUrl: string) => {
|
||||||
|
// Add link to head
|
||||||
|
let tag: LinkDefinition = {
|
||||||
|
href: coarRestApiUrl,
|
||||||
|
rel: rel
|
||||||
|
};
|
||||||
|
this.inboxTags.push(tag);
|
||||||
|
this.linkHeadService.addTag(tag);
|
||||||
|
|
||||||
|
links = links + (isNotEmpty(links) ? ', ' : '') + `<${coarRestApiUrl}> ; rel="${rel}"`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.signpostingLinks.forEach((link: SignpostingLink) => {
|
this.signpostingLinks.forEach((link: SignpostingLink) => {
|
||||||
this.linkHeadService.removeTag(`href='${link.href}'`);
|
this.linkHeadService.removeTag(`href='${link.href}'`);
|
||||||
});
|
});
|
||||||
|
this.inboxTags.forEach((link: LinkDefinition) => {
|
||||||
|
this.linkHeadService.removeTag(`href='${link.href}'`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user