mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
[CST-5729] implemented functionality to add link tags in head html section when on item page
This commit is contained in:
12
server.ts
12
server.ts
@@ -180,14 +180,14 @@ export function app() {
|
|||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxy the linksets
|
* Proxy the linksets
|
||||||
*/
|
*/
|
||||||
router.use('/linksets**', createProxyMiddleware({
|
router.use('/linkset**', createProxyMiddleware({
|
||||||
target: `${environment.rest.baseUrl}/linksets`,
|
target: `${environment.rest.baseUrl}/signposting/linksets`,
|
||||||
pathRewrite: path => path.replace(environment.ui.nameSpace, '/'),
|
pathRewrite: path => path.replace(environment.ui.nameSpace, '/'),
|
||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
}));
|
}));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the rateLimiter property is present
|
* Checks if the rateLimiter property is present
|
||||||
|
16
src/app/core/data/signposting-data.service.spec.ts
Normal file
16
src/app/core/data/signposting-data.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SignpostingDataService } from './signposting-data.service';
|
||||||
|
|
||||||
|
describe('SignpostingDataService', () => {
|
||||||
|
let service: SignpostingDataService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(SignpostingDataService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
52
src/app/core/data/signposting-data.service.ts
Normal file
52
src/app/core/data/signposting-data.service.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DspaceRestService } from '../dspace-rest/dspace-rest.service';
|
||||||
|
// import { HttpHeaders, HttpResponse } from '@angular/common/http';
|
||||||
|
import { catchError, map } from 'rxjs/operators';
|
||||||
|
// import { throwError } from 'rxjs';
|
||||||
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
|
import { RawRestResponse } from '../dspace-rest/raw-rest-response.model';
|
||||||
|
import { HttpHeaders } from '@angular/common/http';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SignpostingDataService {
|
||||||
|
|
||||||
|
constructor(private restService: DspaceRestService, protected halService: HALEndpointService) { }
|
||||||
|
|
||||||
|
getLinks(uuid: string): Observable<any> {
|
||||||
|
const url = this.halService.getRootHref().split('/');
|
||||||
|
const baseUrl = `${url[0]}//${url[2]}/${url[3]}`;
|
||||||
|
|
||||||
|
return this.restService.get(`${baseUrl}/signposting/links/${uuid}`).pipe(
|
||||||
|
catchError((err ) => {
|
||||||
|
console.error(err);
|
||||||
|
return observableOf(false);
|
||||||
|
}),
|
||||||
|
map((res: RawRestResponse) => res)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLinksets(uuid: string): Observable<any> {
|
||||||
|
const url = this.halService.getRootHref().split('/');
|
||||||
|
const baseUrl = `${url[0]}//${url[2]}/${url[3]}`;
|
||||||
|
|
||||||
|
const requestOptions = {
|
||||||
|
observe: 'response' as any,
|
||||||
|
headers: new HttpHeaders({
|
||||||
|
'accept': 'application/linkset',
|
||||||
|
'Content-Type': 'application/linkset'
|
||||||
|
}),
|
||||||
|
responseType: 'text'
|
||||||
|
} as any;
|
||||||
|
|
||||||
|
return this.restService.getWithHeaders(`${baseUrl}/signposting/linksets/${uuid}`, requestOptions).pipe(
|
||||||
|
catchError((err ) => {
|
||||||
|
console.error(err);
|
||||||
|
return observableOf(false);
|
||||||
|
}),
|
||||||
|
map((res: RawRestResponse) => res)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
5
src/app/core/data/signposting-data.ts
Normal file
5
src/app/core/data/signposting-data.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export interface SignpostingDataLink {
|
||||||
|
href: string,
|
||||||
|
rel: string,
|
||||||
|
type: string
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { Observable, throwError as observableThrowError } from 'rxjs';
|
import { Observable, throwError as observableThrowError, throwError } from 'rxjs';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';
|
import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';
|
||||||
@@ -58,6 +58,19 @@ export class DspaceRestService {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getWithHeaders(absoluteURL: string, reqOptions: any): Observable<any> {
|
||||||
|
const requestOptions = reqOptions;
|
||||||
|
|
||||||
|
return this.http.get(absoluteURL, requestOptions).pipe(
|
||||||
|
map((res) => ({
|
||||||
|
payload: res
|
||||||
|
})),
|
||||||
|
catchError((err) => {
|
||||||
|
console.log('Error: ', err);
|
||||||
|
return throwError(() => new Error(err.error));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a request to the REST API.
|
* Performs a request to the REST API.
|
||||||
*
|
*
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { MetadataItemService } from './metadata-item.service';
|
|
||||||
|
|
||||||
describe('MetadataItemService', () => {
|
|
||||||
let service: MetadataItemService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({});
|
|
||||||
service = TestBed.inject(MetadataItemService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', () => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,70 +0,0 @@
|
|||||||
import { Inject, Injectable } from '@angular/core';
|
|
||||||
import { MetadataService } from '../metadata/metadata.service';
|
|
||||||
import { ActivatedRoute, NavigationEnd, Event as NavigationEvent, NavigationStart, Router } from '@angular/router';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
import { Meta, Title } from '@angular/platform-browser';
|
|
||||||
import { DSONameService } from '../breadcrumbs/dso-name.service';
|
|
||||||
import { BundleDataService } from '../data/bundle-data.service';
|
|
||||||
import { BitstreamDataService } from '../data/bitstream-data.service';
|
|
||||||
import { BitstreamFormatDataService } from '../data/bitstream-format-data.service';
|
|
||||||
import { RootDataService } from '../data/root-data.service';
|
|
||||||
import { CoreState } from '../core-state.model';
|
|
||||||
import { Store } from '@ngrx/store';
|
|
||||||
import { HardRedirectService } from '../services/hard-redirect.service';
|
|
||||||
import { APP_CONFIG, AppConfig } from 'src/config/app-config.interface';
|
|
||||||
import { AuthorizationDataService } from '../data/feature-authorization/authorization-data.service';
|
|
||||||
import { filter, map, switchMap, take, mergeMap } from 'rxjs/operators';
|
|
||||||
import { DOCUMENT } from '@angular/common';
|
|
||||||
|
|
||||||
@Injectable({
|
|
||||||
providedIn: 'root'
|
|
||||||
})
|
|
||||||
export class MetadataItemService extends MetadataService {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private router1: ActivatedRoute,
|
|
||||||
router: Router,
|
|
||||||
translate: TranslateService,
|
|
||||||
meta: Meta,
|
|
||||||
title: Title,
|
|
||||||
dsoNameService: DSONameService,
|
|
||||||
bundleDataService: BundleDataService,
|
|
||||||
bitstreamDataService: BitstreamDataService,
|
|
||||||
bitstreamFormatDataService: BitstreamFormatDataService,
|
|
||||||
rootService: RootDataService,
|
|
||||||
store: Store<CoreState>,
|
|
||||||
hardRedirectService: HardRedirectService,
|
|
||||||
@Inject(APP_CONFIG) appConfig: AppConfig,
|
|
||||||
authorizationService: AuthorizationDataService,
|
|
||||||
@Inject(DOCUMENT) private document: Document
|
|
||||||
) {
|
|
||||||
super(router, translate, meta, title, dsoNameService, bundleDataService, bitstreamDataService, bitstreamFormatDataService, rootService, store, hardRedirectService, appConfig, authorizationService);
|
|
||||||
}
|
|
||||||
|
|
||||||
public checkCurrentRoute(){
|
|
||||||
|
|
||||||
console.log(this.router);
|
|
||||||
|
|
||||||
this.router1.url.subscribe(url => {
|
|
||||||
console.log(url);
|
|
||||||
console.log(url[0].path);
|
|
||||||
});
|
|
||||||
|
|
||||||
// this.router.events.subscribe((event: NavigationEvent) => {
|
|
||||||
// if(event instanceof NavigationStart) {
|
|
||||||
// if(event.url.startsWith('/entities')){
|
|
||||||
// console.log('We are on ENTITIES!');
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
setLinkTag(){
|
|
||||||
this.clearMetaTags();
|
|
||||||
|
|
||||||
let link: HTMLLinkElement = this.document.createElement('link');
|
|
||||||
link.setAttribute('rel', '');
|
|
||||||
link.setAttribute('href', '');
|
|
||||||
this.document.head.appendChild(link);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -45,6 +45,7 @@ import { CoreState } from '../core-state.model';
|
|||||||
import { AuthorizationDataService } from '../data/feature-authorization/authorization-data.service';
|
import { AuthorizationDataService } from '../data/feature-authorization/authorization-data.service';
|
||||||
import { getDownloadableBitstream } from '../shared/bitstream.operators';
|
import { getDownloadableBitstream } from '../shared/bitstream.operators';
|
||||||
import { APP_CONFIG, AppConfig } from '../../../config/app-config.interface';
|
import { APP_CONFIG, AppConfig } from '../../../config/app-config.interface';
|
||||||
|
import { SignpostingDataService } from '../data/signposting-data.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base selector function to select the metaTag section in the store
|
* The base selector function to select the metaTag section in the store
|
||||||
@@ -96,7 +97,8 @@ export class MetadataService {
|
|||||||
private store: Store<CoreState>,
|
private store: Store<CoreState>,
|
||||||
private hardRedirectService: HardRedirectService,
|
private hardRedirectService: HardRedirectService,
|
||||||
@Inject(APP_CONFIG) private appConfig: AppConfig,
|
@Inject(APP_CONFIG) private appConfig: AppConfig,
|
||||||
private authorizationService: AuthorizationDataService
|
private authorizationService: AuthorizationDataService,
|
||||||
|
private signpostginDataService: SignpostingDataService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +140,7 @@ export class MetadataService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCurrentRoute(route: ActivatedRoute): ActivatedRoute {
|
public getCurrentRoute(route: ActivatedRoute): ActivatedRoute {
|
||||||
while (route.firstChild) {
|
while (route.firstChild) {
|
||||||
route = route.firstChild;
|
route = route.firstChild;
|
||||||
}
|
}
|
||||||
@@ -162,6 +164,8 @@ export class MetadataService {
|
|||||||
this.setCitationAbstractUrlTag();
|
this.setCitationAbstractUrlTag();
|
||||||
this.setCitationPdfUrlTag();
|
this.setCitationPdfUrlTag();
|
||||||
this.setCitationPublisherTag();
|
this.setCitationPublisherTag();
|
||||||
|
this.setSignpostingLinks();
|
||||||
|
this.setSignpostingLinksets();
|
||||||
|
|
||||||
if (this.isDissertation()) {
|
if (this.isDissertation()) {
|
||||||
this.setCitationDissertationNameTag();
|
this.setCitationDissertationNameTag();
|
||||||
@@ -184,6 +188,45 @@ export class MetadataService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add <link name="title" ... > to the <head>
|
||||||
|
*/
|
||||||
|
private setSignpostingLinks() {
|
||||||
|
if (this.currentObject.value instanceof Item){
|
||||||
|
const value = this.signpostginDataService.getLinks(this.currentObject.getValue().id);
|
||||||
|
value.subscribe(links => {
|
||||||
|
links.payload.forEach(link => {
|
||||||
|
this.setLinkTag(link.href, link.rel, link.type);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLinkTag(href: string, rel: string, type: string){
|
||||||
|
let link: HTMLLinkElement = document.createElement('link');
|
||||||
|
link.href = href;
|
||||||
|
link.rel = rel;
|
||||||
|
link.type = type;
|
||||||
|
document.head.appendChild(link);
|
||||||
|
console.log(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setSignpostingLinksets() {
|
||||||
|
if (this.currentObject.value instanceof Item){
|
||||||
|
const value = this.signpostginDataService.getLinksets(this.currentObject.getValue().id);
|
||||||
|
value.subscribe(linksets => {
|
||||||
|
this.setLinkAttribute(linksets);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLinkAttribute(linksets){
|
||||||
|
console.log('ANDREA', linksets);
|
||||||
|
const linkAttribute = `Link: ${linksets.payload.body}`;
|
||||||
|
const textNode = document.createTextNode(linkAttribute);
|
||||||
|
document.head.appendChild(textNode);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add <meta name="title" ... > to the <head>
|
* Add <meta name="title" ... > to the <head>
|
||||||
*/
|
*/
|
||||||
@@ -363,15 +406,6 @@ export class MetadataService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add <meta name="link" ... > to the <head>
|
|
||||||
*/
|
|
||||||
// private setLinkTag(): void {
|
|
||||||
// const value = this.getMetaTagValue('dc.link');
|
|
||||||
// this.meta.addTag({ name: 'Link', content: value });
|
|
||||||
// this.addMetaTag('Link', value);
|
|
||||||
// }
|
|
||||||
|
|
||||||
getBitLinkIfDownloadable(bitstream: Bitstream, bitstreamRd: RemoteData<PaginatedList<Bitstream>>): Observable<string> {
|
getBitLinkIfDownloadable(bitstream: Bitstream, bitstreamRd: RemoteData<PaginatedList<Bitstream>>): Observable<string> {
|
||||||
return observableOf(bitstream).pipe(
|
return observableOf(bitstream).pipe(
|
||||||
getDownloadableBitstream(this.authorizationService),
|
getDownloadableBitstream(this.authorizationService),
|
||||||
|
@@ -24,7 +24,6 @@ import { isAuthenticationBlocking } from './core/auth/selectors';
|
|||||||
import { distinctUntilChanged, find } from 'rxjs/operators';
|
import { distinctUntilChanged, find } from 'rxjs/operators';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { MenuService } from './shared/menu/menu.service';
|
import { MenuService } from './shared/menu/menu.service';
|
||||||
import { MetadataItemService } from './core/metadata-item/metadata-item.service';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the initialization of the app.
|
* Performs the initialization of the app.
|
||||||
@@ -51,7 +50,6 @@ export abstract class InitService {
|
|||||||
protected localeService: LocaleService,
|
protected localeService: LocaleService,
|
||||||
protected angulartics2DSpace: Angulartics2DSpace,
|
protected angulartics2DSpace: Angulartics2DSpace,
|
||||||
protected metadata: MetadataService,
|
protected metadata: MetadataService,
|
||||||
protected metadataItem: MetadataItemService,
|
|
||||||
protected breadcrumbsService: BreadcrumbsService,
|
protected breadcrumbsService: BreadcrumbsService,
|
||||||
protected themeService: ThemeService,
|
protected themeService: ThemeService,
|
||||||
protected menuService: MenuService,
|
protected menuService: MenuService,
|
||||||
@@ -190,7 +188,7 @@ export abstract class InitService {
|
|||||||
this.breadcrumbsService.listenForRouteChanges();
|
this.breadcrumbsService.listenForRouteChanges();
|
||||||
this.themeService.listenForRouteChanges();
|
this.themeService.listenForRouteChanges();
|
||||||
this.menuService.listenForRouteChanges();
|
this.menuService.listenForRouteChanges();
|
||||||
this.metadataItem.checkCurrentRoute();
|
// this.metadataItem.checkCurrentRoute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -32,7 +32,6 @@ import { logStartupMessage } from '../../../startup-message';
|
|||||||
import { MenuService } from '../../app/shared/menu/menu.service';
|
import { MenuService } from '../../app/shared/menu/menu.service';
|
||||||
import { RootDataService } from '../../app/core/data/root-data.service';
|
import { RootDataService } from '../../app/core/data/root-data.service';
|
||||||
import { firstValueFrom, Subscription } from 'rxjs';
|
import { firstValueFrom, Subscription } from 'rxjs';
|
||||||
import { MetadataItemService } from 'src/app/core/metadata-item/metadata-item.service';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs client-side initialization.
|
* Performs client-side initialization.
|
||||||
@@ -52,7 +51,6 @@ export class BrowserInitService extends InitService {
|
|||||||
protected angulartics2DSpace: Angulartics2DSpace,
|
protected angulartics2DSpace: Angulartics2DSpace,
|
||||||
protected googleAnalyticsService: GoogleAnalyticsService,
|
protected googleAnalyticsService: GoogleAnalyticsService,
|
||||||
protected metadata: MetadataService,
|
protected metadata: MetadataService,
|
||||||
protected metadataItem: MetadataItemService,
|
|
||||||
protected breadcrumbsService: BreadcrumbsService,
|
protected breadcrumbsService: BreadcrumbsService,
|
||||||
protected klaroService: KlaroService,
|
protected klaroService: KlaroService,
|
||||||
protected authService: AuthService,
|
protected authService: AuthService,
|
||||||
@@ -68,7 +66,6 @@ export class BrowserInitService extends InitService {
|
|||||||
localeService,
|
localeService,
|
||||||
angulartics2DSpace,
|
angulartics2DSpace,
|
||||||
metadata,
|
metadata,
|
||||||
metadataItem,
|
|
||||||
breadcrumbsService,
|
breadcrumbsService,
|
||||||
themeService,
|
themeService,
|
||||||
menuService,
|
menuService,
|
||||||
|
@@ -21,7 +21,6 @@ import { BreadcrumbsService } from '../../app/breadcrumbs/breadcrumbs.service';
|
|||||||
import { ThemeService } from '../../app/shared/theme-support/theme.service';
|
import { ThemeService } from '../../app/shared/theme-support/theme.service';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import { MenuService } from '../../app/shared/menu/menu.service';
|
import { MenuService } from '../../app/shared/menu/menu.service';
|
||||||
import { MetadataItemService } from 'src/app/core/metadata-item/metadata-item.service';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs server-side initialization.
|
* Performs server-side initialization.
|
||||||
@@ -37,7 +36,6 @@ export class ServerInitService extends InitService {
|
|||||||
protected localeService: LocaleService,
|
protected localeService: LocaleService,
|
||||||
protected angulartics2DSpace: Angulartics2DSpace,
|
protected angulartics2DSpace: Angulartics2DSpace,
|
||||||
protected metadata: MetadataService,
|
protected metadata: MetadataService,
|
||||||
protected metadataItem: MetadataItemService,
|
|
||||||
protected breadcrumbsService: BreadcrumbsService,
|
protected breadcrumbsService: BreadcrumbsService,
|
||||||
protected themeService: ThemeService,
|
protected themeService: ThemeService,
|
||||||
protected menuService: MenuService
|
protected menuService: MenuService
|
||||||
@@ -50,7 +48,6 @@ export class ServerInitService extends InitService {
|
|||||||
localeService,
|
localeService,
|
||||||
angulartics2DSpace,
|
angulartics2DSpace,
|
||||||
metadata,
|
metadata,
|
||||||
metadataItem,
|
|
||||||
breadcrumbsService,
|
breadcrumbsService,
|
||||||
themeService,
|
themeService,
|
||||||
menuService,
|
menuService,
|
||||||
|
Reference in New Issue
Block a user