[Library]: Altmetrics bug fix (from landing page with identifiers to landing page without: ERROR) | Instances model changed to merge common urls #7153 & #7156.
1. deletedByInference.service.ts: Call updated parsing method for hostedBy_collectedFrom. 2. result-preview.component.html: Updated display of hostedBy_collectedFrom (new schema). 3. availableOn.component.ts: Updated display of instances in download from section of result landing page (new schema - merged instances with common url and multiple collectedfrom & hostedby) 4. result-preview.ts: Updated class HostedByCollectedFrom (new schema). 5. resultLanding.service.ts: a. Updated parsing of hostedBy_collectedFrom (new schema). c. Updated sorting of hostedBy_collectedFrom. 6. resultLanding.component.ts: a. Use updated resultLandingInfo.hostedBy_collectedFrom to check if this result will be indexed or not. b. [Bug fix] Set hasAltmetrics to false when requesting a new id. 7. parsingFunctions.class.ts: Updated parsing of hostedBy_collectedFrom according to new schema.
This commit is contained in:
parent
dd7aeaa34f
commit
8140beb701
|
@ -1,44 +1,33 @@
|
|||
import {Component, Input} from '@angular/core';
|
||||
import {HelperFunctions} from "../../utils/HelperFunctions.class";
|
||||
import {HostedByCollectedFrom} from "../../utils/result-preview/result-preview";
|
||||
import {properties} from "../../../../environments/environment";
|
||||
|
||||
@Component({
|
||||
selector: 'availableOn',
|
||||
template: `
|
||||
<div class="download-from uk-height-max-large uk-overflow-auto uk-margin-small-bottom">
|
||||
<div *ngFor="let available of availableOn.slice(0, showNum) let i=index"
|
||||
<div *ngIf="availableOn" class="download-from uk-height-max-large uk-overflow-auto uk-margin-small-bottom">
|
||||
<div *ngFor="let instance of availableOn.slice(0, showNum) let i=index"
|
||||
class="uk-flex uk-flex-top"
|
||||
[title]="available.bestAccessMode ? available.bestAccessMode : 'Not available'">
|
||||
[title]="instance.accessRight ? instance.accessRight : 'Not available'">
|
||||
<span class="uk-margin-small-right">
|
||||
<img [src]="available.icon" loading="lazy" [alt]="available.bestAccessMode" style="width:20px; height:20px">
|
||||
<img [src]="instance.accessRightIcon" loading="lazy" [alt]="instance.accessRight" style="width:20px; height:20px">
|
||||
</span>
|
||||
<div class="uk-width-expand uk-padding-small uk-padding-remove-left uk-padding-remove-vertical">
|
||||
<span *ngIf="available.downloadUrl.length > 1" class="title">
|
||||
<span>{{available.downloadName}}</span>
|
||||
<a *ngFor="let url of available.downloadUrl; let i=index;"
|
||||
[href]="url" target="_blank">
|
||||
[{{(i + 1) | number}}]
|
||||
</a>
|
||||
</span>
|
||||
<a *ngIf="available.downloadUrl.length === 1" [href]="available.downloadUrl[0]" target="_blank"
|
||||
<a *ngIf="instance.downloadUrl" [href]="instance.downloadUrl" target="_blank"
|
||||
class="title">
|
||||
{{available.downloadName}}
|
||||
{{instance.downloadNames.join("; ")}}
|
||||
<span class="custom-external custom-icon space"></span>
|
||||
</a>
|
||||
<span *ngIf="!available.downloadUrl || available.downloadUrl.length === 0" class="title">
|
||||
{{available.downloadName}}
|
||||
</span>
|
||||
<div *ngIf="removeUnknown(available.type) || available.year">
|
||||
<span *ngIf="removeUnknown(available.type)" class="uk-text-capitalize">{{available.type}}</span>
|
||||
<span *ngIf="removeUnknown(available.type) && available.year"> . </span>
|
||||
<span *ngIf="available.year">{{available.year}}</span>
|
||||
<div *ngIf="instance.types?.length > 0 || instance.years?.length > 0">
|
||||
<span *ngIf="instance.types?.length > 0" class="uk-text-capitalize">{{instance.types.join(" . ")}}</span>
|
||||
<span *ngIf="instance.types?.length > 0 && instance.years?.length > 0"> . </span>
|
||||
<span *ngIf="instance.years?.length > 0">{{instance.years.join(" . ")}}</span>
|
||||
</div>
|
||||
<div *ngIf="available.collectedName">
|
||||
<span>Provider: </span>
|
||||
<a *ngIf="available.collectedId" [routerLink]="dataProviderUrl"
|
||||
[queryParams]="{datasourceId: available.collectedId}">
|
||||
{{available.collectedName}}
|
||||
<div *ngIf="instance.collectedNamesAndIds?.size > 0">
|
||||
<span>Providers: </span>
|
||||
<a *ngFor="let collectedName of instance.collectedNamesAndIds.keys(); let i=index" [routerLink]="dataProviderUrl"
|
||||
[queryParams]="{datasourceId: instance.collectedNamesAndIds.get(collectedName)}">
|
||||
{{collectedName}}<ng-container *ngIf="(i !== (instance.collectedNamesAndIds.size - 1))">; </ng-container>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -158,31 +158,23 @@ export class ParsingFunctions {
|
|||
hostedBy_collectedFrom = [];
|
||||
}
|
||||
let available: HostedByCollectedFrom = {
|
||||
downloadName: "",
|
||||
downloadUrl: null,
|
||||
collectedName: "",
|
||||
collectedId: "",
|
||||
accessMode: null,
|
||||
bestAccessMode: null,
|
||||
type: "",
|
||||
year: "",
|
||||
icon: ""
|
||||
downloadNames: [],
|
||||
downloadUrl: "",
|
||||
collectedNamesAndIds: null,
|
||||
accessRight: "",
|
||||
types: [],
|
||||
years: [],
|
||||
accessRightIcon: ""
|
||||
};
|
||||
|
||||
if (journal && journal.journal) {
|
||||
available.downloadName = publisher + "/ " + journal['journal'];
|
||||
available.downloadNames.push(publisher + "/ " + journal['journal']);
|
||||
} else {
|
||||
available.downloadName = publisher;
|
||||
available.downloadNames.push(publisher);
|
||||
}
|
||||
|
||||
let url = properties.doiURL + identifiers.get("doi")[0];
|
||||
|
||||
available.downloadUrl = new Array<string>();
|
||||
available.accessMode = new Array<string>();
|
||||
|
||||
available.downloadUrl.push(url);
|
||||
|
||||
available.icon = this.unknown;
|
||||
available.downloadUrl = properties.doiURL + identifiers.get("doi")[0];;
|
||||
available.accessRightIcon = this.unknown;
|
||||
/*
|
||||
if(title != undefined && title['url'] == "") {
|
||||
title['url'] = url;
|
||||
|
@ -254,117 +246,106 @@ export class ParsingFunctions {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
parseHostedBy_collectedFrom(hostedBy_collectedFrom: HostedByCollectedFrom[],
|
||||
instance: any, data: any, url: string, counter: number/*,
|
||||
title: { "name": string, "url": string, "accessMode": string}*/, accessMode: string): number {
|
||||
instance: any, url: string, globalAccessRight: string) {
|
||||
if(!url) {
|
||||
return;
|
||||
}
|
||||
|
||||
let available: HostedByCollectedFrom = {
|
||||
"downloadName": "",
|
||||
"downloadNames": [],
|
||||
"downloadUrl": null,
|
||||
"collectedName": "",
|
||||
"collectedId": "",
|
||||
"accessMode": null,
|
||||
"bestAccessMode": null,
|
||||
"type": "",
|
||||
"year": "",
|
||||
"icon": ""
|
||||
"collectedNamesAndIds": new Map(),
|
||||
"accessRight": null,
|
||||
"accessRightIcon": "",
|
||||
"types": [],
|
||||
"years": []
|
||||
};
|
||||
|
||||
if (instance['hostedby'].name && instance['hostedby'].name != "other resources" && instance['hostedby'].name != "Unknown Repository") {
|
||||
available.downloadName = instance['hostedby'].name;
|
||||
} else {
|
||||
// if (data != null && data.hasOwnProperty("source")) {
|
||||
// let downloadName: string;
|
||||
// if (Array.isArray(data.source)) {
|
||||
//
|
||||
// if (counter == data.source.length) {
|
||||
// counter--;
|
||||
// }
|
||||
// downloadName = data['source'][counter];
|
||||
// } else {
|
||||
// downloadName = data['source'];
|
||||
// }
|
||||
// if (downloadName) {
|
||||
// counter++;
|
||||
// available.downloadName = downloadName;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// if(!available.downloadName) {
|
||||
available.downloadName = url.substring(0, 30) + '...'; // substring(from, to);
|
||||
if (instance.hasOwnProperty("hostedby")) {
|
||||
let downloadNames: Set<string> = new Set();
|
||||
let length = Array.isArray(instance['hostedby']) ? instance['hostedby'].length : 1;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let hostedBy = Array.isArray(instance['hostedby']) ? instance['hostedby'][i] : instance['hostedby'];
|
||||
if (hostedBy.name && hostedBy.name != "other resources" && hostedBy.name != "Unknown Repository") {
|
||||
downloadNames.add(hostedBy.name);
|
||||
}
|
||||
}
|
||||
available.downloadNames = Array.from(downloadNames);
|
||||
|
||||
if (available.downloadNames.length == 0) {
|
||||
available.downloadNames.push(url.substring(0, 30) + '...'); // substring(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
if (available.downloadName) {
|
||||
if (instance.hasOwnProperty("collectedfrom")) {
|
||||
available.collectedId = instance['collectedfrom'].id;
|
||||
available.collectedName = instance['collectedfrom'].name;
|
||||
let length = Array.isArray(instance['collectedfrom']) ? instance['collectedfrom'].length : 1;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let collectedFrom = Array.isArray(instance['collectedfrom']) ? instance['collectedfrom'][i] : instance['collectedfrom'];
|
||||
if(collectedFrom.name && collectedFrom.id) {
|
||||
available.collectedNamesAndIds.set(collectedFrom.name, collectedFrom.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (instance.hasOwnProperty("instancetype") && instance['instancetype'].classname) {
|
||||
available.type = instance['instancetype'].classname;
|
||||
if (instance.hasOwnProperty("instancetype")) {
|
||||
let types: Set<string> = new Set();
|
||||
let length = Array.isArray(instance['instancetype']) ? instance['instancetype'].length : 1;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let instanceType = Array.isArray(instance['instancetype']) ? instance['instancetype'][i] : instance['instancetype'];
|
||||
if(instanceType.classname && instanceType.classname.toLowerCase() !== "unknown") {
|
||||
types.add(instanceType.classname);
|
||||
}
|
||||
}
|
||||
available.types = Array.from(types);
|
||||
}
|
||||
|
||||
if (instance.hasOwnProperty("dateofacceptance")) {
|
||||
var date: string = (instance.dateofacceptance) + ""; // transform to string in case it is an integer
|
||||
available.year = (date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date;
|
||||
let years: Set<string> = new Set();
|
||||
let length = Array.isArray(instance['dateofacceptance']) ? instance['dateofacceptance'].length : 1;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let dateOfAcceptance = Array.isArray(instance['dateofacceptance']) ? instance['dateofacceptance'][i] : instance['dateofacceptance'];
|
||||
let date: string = (dateOfAcceptance) + ""; // transform to string in case it is an integer
|
||||
years.add((date && (date).indexOf('-') !== -1) ? date.split('-')[0] : date);
|
||||
}
|
||||
available.years = Array.from(years);
|
||||
}
|
||||
|
||||
available.accessMode = new Array<string>();
|
||||
available.downloadUrl = new Array<string>();
|
||||
available['downloadUrl'].push(url);
|
||||
available['downloadUrl'] = url;
|
||||
if(url.includes("doi.org/")) {
|
||||
this.instanceWithDoiExists = true;
|
||||
}
|
||||
|
||||
if (instance.hasOwnProperty("accessright")) {
|
||||
if (url) {
|
||||
available['accessMode'].push(instance['accessright'].classname);
|
||||
let length = Array.isArray(instance['accessright']) ? instance['accessright'].length : 1;
|
||||
for (let i = 0; i < length; i++) {
|
||||
let accessRight = Array.isArray(instance['accessright']) ? instance['accessright'][i] : instance['accessright'];
|
||||
|
||||
if (this.changeBestAccessMode(available.accessRight, accessRight)) {
|
||||
available.accessRight = accessRight.classname;
|
||||
if (this.changeBestAccessMode(globalAccessRight, accessRight)) {
|
||||
globalAccessRight = accessRight.classname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.changeBestAccessMode(available.bestAccessMode, instance['accessright'])) {
|
||||
available.bestAccessMode = instance['accessright'].classname;
|
||||
/*
|
||||
if(title != undefined) {
|
||||
if(this.changeBestAccessMode(title['accessMode'], instance['accessright'])) {
|
||||
title['accessMode'] = instance['accessright'].classid;
|
||||
title['url'] = url;
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (this.changeBestAccessMode(accessMode, instance['accessright'])) {
|
||||
accessMode = instance['accessright'].classname;
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(title != undefined) {
|
||||
if(!title['url']) {
|
||||
title['url'] = url;
|
||||
}
|
||||
}
|
||||
*/
|
||||
} else if (url) {
|
||||
available['accessMode'].push("");
|
||||
}
|
||||
|
||||
if (available.bestAccessMode) {
|
||||
if (available.bestAccessMode.toLowerCase().indexOf('open') !== -1) {
|
||||
available.icon = this.open;
|
||||
} else if (available.bestAccessMode.toLowerCase().indexOf('not available') !== -1) {
|
||||
available.icon = this.unknown;
|
||||
if (available.accessRight) {
|
||||
if (available.accessRight.toLowerCase().indexOf('open') !== -1) {
|
||||
available.accessRightIcon = this.open;
|
||||
} else if (available.accessRight.toLowerCase().indexOf('not available') !== -1) {
|
||||
available.accessRightIcon = this.unknown;
|
||||
} else {
|
||||
available.icon = this.closed;
|
||||
available.accessRightIcon = this.closed;
|
||||
}
|
||||
} else {
|
||||
available.icon = this.unknown;
|
||||
available.accessRightIcon = this.unknown;
|
||||
}
|
||||
|
||||
hostedBy_collectedFrom.push(available);
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
// publication & dataset landing : for downloadFrom and publishedIn
|
||||
changeBestAccessMode(currentAccessMode: string, accessMode: any): boolean {
|
||||
if (!accessMode) {
|
||||
|
|
|
@ -121,7 +121,7 @@ export class DeletedByInferenceService {
|
|||
}
|
||||
|
||||
if(instance.hasOwnProperty("hostedby")) {
|
||||
counter = this.parsingFunctions.parseHostedBy_collectedFrom(result.hostedBy_collectedFrom, instance, _result['oaf:result'], url, counter, result.accessMode);
|
||||
this.parsingFunctions.parseHostedBy_collectedFrom(result.hostedBy_collectedFrom, instance, url, result.accessMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -358,6 +358,7 @@ export class ResultLandingComponent {
|
|||
return;
|
||||
}
|
||||
this.resultLandingInfo = null;
|
||||
this.hasAltMetrics = false;
|
||||
this.subscriptions.push(this._resultLandingService.getResultLandingInfo(this.id, this.identifier, this.type, provenanceActionVocabulary, this.properties).subscribe(
|
||||
data => {
|
||||
this.resultLandingInfo = data;
|
||||
|
@ -689,7 +690,9 @@ export class ResultLandingComponent {
|
|||
|| (resultLandingInfo.description && this.hasKeyword(resultLandingInfo.description,abstract_words))
|
||||
) &&
|
||||
((resultLandingInfo.publisher && resultLandingInfo.publisher.toLowerCase() == "zenodo") ||
|
||||
resultLandingInfo.hostedBy_collectedFrom.filter( value => {return value.downloadName && value.downloadName.toLowerCase().indexOf("zenodo")!=-1}).length > 0));
|
||||
resultLandingInfo.hostedBy_collectedFrom.filter(value => {
|
||||
return value.downloadNames && value.downloadNames.filter(name => {return name && name.toLowerCase().indexOf("zenodo") != 1}).length > 0
|
||||
}).length > 0));
|
||||
// console.log("spam content " + allow)
|
||||
//common titles/ description / authors
|
||||
let common_titles = ["introduction", "editorial", "book reviews", "preface", "reviews", "none", "book review", "foreword", "conclusion", "review", "reply","einleitung","short notices","erratum","discussion", "letters to the editor","letter to the editor","reviews of books",":{unav)","editorial board"];
|
||||
|
|
|
@ -241,40 +241,58 @@ export class ResultLandingService {
|
|||
let url;
|
||||
if(!Array.isArray(instance['webresource'])) {
|
||||
url = instance['webresource'].url;
|
||||
if(url.includes('&')) {
|
||||
let regExp = /&/gmu;
|
||||
let newUrl = url.replace(regExp, '&');
|
||||
url = newUrl;
|
||||
}
|
||||
} else {
|
||||
url = instance['webresource'][0].url;
|
||||
}
|
||||
if(url.includes('&')) {
|
||||
let regExp = /&/gmu;
|
||||
let newUrl = url.replace(regExp, '&');
|
||||
url = newUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
if(instance.hasOwnProperty("hostedby")) {
|
||||
counter = this.parsingFunctions.parseHostedBy_collectedFrom(this.resultLandingInfo.hostedBy_collectedFrom, instance, data[0], url, counter/*, this.resultLandingInfo.title*/, this.resultLandingInfo.accessMode);
|
||||
this.parsingFunctions.parseHostedBy_collectedFrom(this.resultLandingInfo.hostedBy_collectedFrom, instance, url, this.resultLandingInfo.accessMode);
|
||||
}
|
||||
/**********************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
/* Order Download from via openness*/
|
||||
this.resultLandingInfo.hostedBy_collectedFrom.sort((a, b) => {
|
||||
if(a.bestAccessMode && a.bestAccessMode.toLowerCase() === 'open access') {
|
||||
return -1;
|
||||
} else if(b.bestAccessMode && b.bestAccessMode.toLowerCase() === 'open access') {
|
||||
return 1;
|
||||
} else if(!a.bestAccessMode || a.bestAccessMode.toLowerCase() !== 'not available') {
|
||||
return 1;
|
||||
} else if(!b.bestAccessMode || b.bestAccessMode.toLowerCase() !== 'not available') {
|
||||
return -1;
|
||||
} else {
|
||||
let firstAccessRight: string = (a.accessRight ? a.accessRight.toLowerCase() : null);
|
||||
let secondAccessRight: string = (b.accessRight ? b.accessRight.toLowerCase() : null);
|
||||
|
||||
if (firstAccessRight === secondAccessRight) {
|
||||
return 0;
|
||||
} else {
|
||||
if (firstAccessRight === 'open access') {
|
||||
return -1;
|
||||
} else if (secondAccessRight === 'open access') {
|
||||
return 1;
|
||||
} else if (firstAccessRight === "open source") {
|
||||
return -1;
|
||||
} else if (secondAccessRight === "open source") {
|
||||
return 1;
|
||||
} else if (firstAccessRight === "embargo") {
|
||||
return -1;
|
||||
} else if (secondAccessRight === "embargo") {
|
||||
return 1;
|
||||
} else if (firstAccessRight === "restricted") {
|
||||
return -1;
|
||||
} else if (secondAccessRight === "restricted") {
|
||||
return 1;
|
||||
} else if (firstAccessRight === "closed access") {
|
||||
return -1;
|
||||
} else if (secondAccessRight === "closed access") {
|
||||
return 1;
|
||||
} else if (firstAccessRight === "not available") {
|
||||
return -1;
|
||||
} else if (secondAccessRight === "not available") {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -254,41 +254,29 @@
|
|||
<div *ngIf="result.hostedBy_collectedFrom && result.hostedBy_collectedFrom.length > 0"
|
||||
class="uk-margin-small-bottom download-from">
|
||||
<div *ngFor="let from of result.hostedBy_collectedFrom"
|
||||
[title]="from.bestAccessMode ? from.bestAccessMode : 'Not available'"
|
||||
[title]="from.accessRight ? from.accessRight : 'Not available'"
|
||||
class="uk-flex">
|
||||
<span class="uk-margin-small-right">
|
||||
<img [src]="from.icon" loading="lazy">
|
||||
<img [src]="from.accessRightIcon" loading="lazy">
|
||||
</span>
|
||||
<span class="uk-width-expand">
|
||||
<span class="uk-margin-right uk-display-inline-block">
|
||||
<span class="uk-text-muted">Download from: </span>
|
||||
<span *ngIf="from.downloadUrl.length > 1" class="title">
|
||||
<span>{{from.downloadName}}</span>
|
||||
<a *ngFor="let url of from.downloadUrl; let i=index;"
|
||||
[href]="url" target="_blank">
|
||||
[{{(i + 1) | number}}]
|
||||
</a>
|
||||
</span>
|
||||
<a *ngIf="from.downloadUrl && from.downloadUrl.length === 1"
|
||||
[href]="from.downloadUrl[0]" target="_blank" class="title">
|
||||
{{from.downloadName}}
|
||||
<a *ngIf="from.downloadUrl"
|
||||
[href]="from.downloadUrl" target="_blank" class="title">
|
||||
<span>{{from.downloadNames.join("; ")}}</span>
|
||||
<span class="custom-external space"></span>
|
||||
</a>
|
||||
<span *ngIf="!from.downloadUrl || from.downloadUrl.length === 0" class="title">
|
||||
{{from.downloadName}}
|
||||
<span>{{from.downloadNames.join(", ")}}</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="provider uk-display-inline-block">
|
||||
<span class="uk-text-muted">Provider: </span>
|
||||
<!-- target="_blank"-->
|
||||
<a *ngIf="from.collectedId" [routerLink]="dataProviderUrl" [queryParams]="{datasourceId: from.collectedId}"
|
||||
[href]="from.downloadUrl[0]" (click)="onClick();">
|
||||
{{from.collectedName}}
|
||||
<!-- <span class="custom-external space"></span>-->
|
||||
<a *ngFor="let collectedName of from.collectedNamesAndIds.keys(); let i=index" [routerLink]="dataProviderUrl"
|
||||
[queryParams]="{datasourceId: from.collectedNamesAndIds.get(collectedName)}" (click)="onClick();">
|
||||
{{collectedName}}<ng-container *ngIf="(i !== (from.collectedNamesAndIds.size - 1))">; </ng-container>
|
||||
</a>
|
||||
<span *ngIf="!from.collectedId">
|
||||
{{from.collectedName}}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -3,15 +3,13 @@ import {ResultLandingInfo} from "../entities/resultLandingInfo";
|
|||
import {OrganizationInfo} from "../entities/organizationInfo";
|
||||
|
||||
export interface HostedByCollectedFrom {
|
||||
downloadName: string;
|
||||
downloadUrl: string[];
|
||||
collectedName: string;
|
||||
collectedId: string;
|
||||
accessMode: string[];
|
||||
bestAccessMode: string;
|
||||
type: string;
|
||||
year: string;
|
||||
icon: string
|
||||
downloadNames: string[];
|
||||
downloadUrl: string;
|
||||
collectedNamesAndIds: Map<string, string>;
|
||||
accessRight: string;
|
||||
types: string[];
|
||||
years: string[];
|
||||
accessRightIcon: string;
|
||||
}
|
||||
|
||||
export interface Journal {
|
||||
|
|
Loading…
Reference in New Issue