[Explore & Library & openaire-theme | new-theme]: Updated parsing of classified subjects by using a vocabulary | Added parsing of instance.license in Download from | Added feedback functionality for fos and sdgs in landing | #7509 Parsing both citations and references fields | In "view all/less" links added chervon-right icon with class "view-more-less-link".

1. fos.component.ts & sdg.component.ts: Added method "urlEncodeAndQuote()" to encode and then quote a string.
2. fos.component.html & sdg.component.html:
   a. "Beta" badge was updated to yellow uk-text-large.
   b. Link to the simple search page instead of the advanced and urlEncodeAndQuote the parameter used in url.
3. link.css: Added class "view-more-less-link" to set on ::after "chevron_right" icon (not underlined on hover) - used in "view all/more/less" links.
4. dataProvider.component.html & project.component.html & fundedBy.component.ts & relatedTo.component.ts & showIdentifiers.component.ts & showAuthors.component.ts: In "view all/less" links added class "view-more-less-link" | Renamed "view more" to "view all".
5. feedback.component.html: Rename wording to be more positive: issues -> feedback, issue -> comment, report -> feedback.
6. feedback.component.ts: Added @Input() preSelectedField: string = ""; and set with it "field" on "addIssue()" (fos/sdg preselected for feedback).
7. availableOn.component.ts:
   a. In "view all/less" links added class "view-more-less-link".
   b. #7833 - Show instance.license information (as link when recognized as url, string otherwise).
8. landing-utils/fos.component.ts & landing-utils/sdg.component.ts:
   a. "Beta" word was updated to yellow uk-text-xsmall.
   b. In "view all/less" links added class "view-more-less-link".
   c. Added feedback functionality: link to feedback form.
9. showSubjects.component.ts:
   a. In "view all/less" links added class "view-more-less-link".
   b. Added "view all" functionality for classified subjects too.
10. resultLanding.component.html:
    a. In "view all/less" links added class "view-more-less-link" | Renamed "view more" to "view all"
    b. Added feedback functionality: link to feedback form - preselect in feedback form fos/sdg.
11. resultLanding.component.ts:
    a. Added public feedbackPreSelectedField: string = ""; field.
    b. Added method "feedbackClicked()".
    c. [Bug fix] In hasPrimaryInfo() added check for classifiedSubjects.
    d. Renamed getProvenanceVocabularyAndResultLandingInfo() to getVocabulariesAndResultLandingInfo() and call also this._vocabulariesService.getSubjectsVocabulary().
12. parsingFunctions.class.ts:
    a. #7196 - Updated parsing of subjects in method "parseAllSubjects()".
    b. #7833 - In method "parseHostedBy_collectedFrom()", added parsing for "license" field.
13. orcid-work.component.ts: On calling method "this.resultLandingService.getResultLandingInfo()", added null parameter for subject vocabulary.
14. searchFilter.module.ts: Import IconsModule.
15. searchFilter.component.html: Removed +/- form "view all/less" links and added class "view-more-less-link".
16. result-preview.ts: Added "licence?: string" in HostedByCollectedFrom.
17. ISVocabularies.service.ts:
    a. Added "private subjectsVocabulary: BehaviorSubject<any> = new BehaviorSubject<any>(null);" field and methods "getSubjectsVocabulary()", "getSubjectsVocabularyFromService()".
    b. Commented this.clearSubscriptions() from "getProvenanceActionVocabularyFromServiceAsync()".
18. resultLanding.service.ts:
    a. On subjects parsing, use subjectsVocabulary.
    b. #7509- Added if/then/else case for parsing citations (new name: references).
This commit is contained in:
Konstantina Galouni 2022-06-09 16:45:39 +03:00
parent 5e11488c8f
commit f974e91c25
21 changed files with 286 additions and 132 deletions

View File

@ -270,12 +270,12 @@
</div>
<div *ngIf="dataProviderInfo.subjects.length > thresholdSubjects && !lessBtnSubjects"
class="uk-width-1-1 uk-text-right">
<a (click)="viewAllSubjectsClick();">
<a (click)="viewAllSubjectsClick();" class="view-more-less-link">
View all {{dataProviderInfo.subjects.length | number}} subjects
</a>
</div>
<div *ngIf="viewAllSubjects && lessBtnSubjects" class="uk-width-1-1 uk-text-right">
<a (click)="viewAllSubjects = !viewAllSubjects; lessBtnSubjects=false;">View less subjects</a>
<a (click)="viewAllSubjects = !viewAllSubjects; lessBtnSubjects=false;" class="view-more-less-link">View less subjects</a>
</div>
</div>
@ -315,12 +315,12 @@
<div *ngIf="dataProviderInfo.organizations.length > thresholdOrganizations && !lessBtnOrganizations"
class="uk-width-1-1 uk-text-right">
<a (click)="viewAllOrganizationsClick();">
<a (click)="viewAllOrganizationsClick();" class="view-more-less-link">
View all {{dataProviderInfo.organizations.length | number}} organizations
</a>
</div>
<div *ngIf="viewAllOrganizations && lessBtnOrganizations" class="uk-width-1-1 uk-text-right">
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;">View less organizations</a>
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;" class="view-more-less-link">View less organizations</a>
</div>
</div>
</div>

View File

@ -5,7 +5,7 @@
<icon name="west" [flex]="true"></icon>
<span class="uk-margin-small-left">Back</span>
</button>
<h3>Report issues in...</h3>
<h3>Give us feedback in...</h3>
<landing-header *ngIf="resultLandingInfo" [properties]="properties" [title]="title"
[subTitle]="resultLandingInfo.subtitle" [underCuration]="resultLandingInfo.underCurationMessage"
[entityType]="entityType" [types]="resultLandingInfo.types"
@ -34,7 +34,7 @@
<div formArrayName="issues">
<div *ngFor="let control of issues.controls; let i = index" [formGroupName]="i" class="uk-margin-medium-bottom">
<div class="uk-flex uk-flex-between">
<h6 class="uk-margin-remove">Issue #{{i + 1}}</h6>
<h6 class="uk-margin-remove">Comment #{{i + 1}}</h6>
<button class="uk-button uk-button-link uk-flex uk-flex-middle" (click)="removeIssue(i)">
<icon name="delete" [flex]="true"></icon>
<span class="uk-margin-small-left">Remove</span>
@ -42,12 +42,12 @@
</div>
<div class="uk-margin-top">
<div input class="uk-width-medium" [formInput]="control.get('field')" placeholder="Select a field" [options]="fields" type="select"></div>
<div input class="uk-width-1-1 uk-margin-top" [formInput]="control.get('report')" placeholder="Write your report here" type="textarea"></div>
<div input class="uk-width-1-1 uk-margin-top" [formInput]="control.get('report')" placeholder="Write your comment here" type="textarea"></div>
</div>
</div>
<button class="uk-button uk-button-link uk-flex uk-flex-middle uk-margin-top uk-margin-bottom" (click)="addIssue()">
<icon name="add" [flex]="true"></icon>
<span class="uk-margin-small-left">Add Issue</span>
<span class="uk-margin-small-left">Add Comment</span>
</button>
</div>
<div>
@ -61,7 +61,7 @@
</div>
<div class="uk-width-1-1 uk-flex uk-flex-center uk-flex-right@m">
<button [class.uk-disabled]="form.invalid || sending" [class.uk-button-primary]="form.valid"
(click)="sendReport()" class="uk-button">Send report
(click)="sendReport()" class="uk-button">Send feedback
</button>
</div>
</div>
@ -82,4 +82,4 @@
</div>
</div>
</div>
<modal-alert #backModal (alertOutput)="changeShowForm(false)"></modal-alert>
<modal-alert #backModal (alertOutput)="changeShowForm(false)" [overflowBody]="false"></modal-alert>

View File

@ -38,6 +38,7 @@ export class FeedbackComponent implements OnInit, OnChanges {
@Input() properties: EnvProperties = null;
@Input() entityType: string = null;
@Input() fields: string[] = [];
@Input() preSelectedField: string = "";
public sending: boolean = false;
public sent: boolean = false;
@ -94,7 +95,7 @@ export class FeedbackComponent implements OnInit, OnChanges {
public addIssue() {
let issue: FormGroup = this.fb.group({
field: this.fb.control('', Validators.required),
field: this.fb.control(this.preSelectedField, Validators.required),
report: this.fb.control('', Validators.required)
});
this.issues.push(issue);

View File

@ -13,8 +13,8 @@ import {properties} from "../../../../environments/environment";
<span *ngIf="!viewAll || lessBtn" class="uk-margin-small-bottom uk-flex uk-flex-middle">
<span class="uk-text-light-grey uk-margin-small-right">Download from</span>
</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>
<a *ngIf="availableOn && availableOn.length > threshold && !viewAll"
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a>
<a *ngIf="availableOn && availableOn.length > threshold && !viewAll" class="view-more-less-link"
(click)="viewAllClick();">View all {{availableOn.length}} sources</a>
</div>
@ -37,6 +37,14 @@ import {properties} from "../../../../environments/environment";
<span *ngIf="instance.types?.length > 0 && instance.years?.length > 0"> . </span>
<span *ngIf="instance.years?.length > 0">{{instance.years.join(" . ")}}</span>
</div>
<div *ngIf="instance.license" class="uk-text-meta uk-text-truncate">
License:
<a *ngIf="isUrl(instance.license); else elseBlock"
[href]="instance.license" target="_blank" class="custom-external">
{{instance.license}}
</a>
<ng-template #elseBlock> {{instance.license}}</ng-template>
</div>
<div *ngIf="instance.collectedNamesAndIds?.size > 0" class="uk-text-meta">
<span>Providers: </span>
<a *ngFor="let collectedName of getKeys(instance.collectedNamesAndIds); let i=index" [routerLink]="dataProviderUrl"
@ -109,4 +117,8 @@ export class AvailableOnComponent {
this.viewAll = false;
this.viewAllClicked.emit("");
}
public isUrl(str: string): boolean {
return str.startsWith('http://') || str.startsWith('https://') || str.startsWith('//') || str.startsWith('www.');
}
}

View File

@ -1,24 +1,30 @@
import {Component, EventEmitter, Input, Output} from "@angular/core";
import {RouterHelper} from "../../utils/routerHelper.class";
import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class";
@Component({
selector: 'fos',
template: `
<div class="uk-margin-small-bottom uk-flex uk-flex-between">
<span *ngIf="viewAll && !lessBtn" class="clickable uk-h6 uk-flex uk-flex-middle" (click)="viewLessClick()">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom" (click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
{{title}}
<span class="uk-text-nowrap">{{title}}</span>
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>
<span *ngIf="!viewAll" class="uk-text-light-grey uk-text-nowrap uk-margin-small-right">{{title}}</span>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>-->
<a *ngIf="subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();">View more</a>
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all & feedback">
<span class="">View all & feedback</span>
</a>
<a *ngIf="(subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate"
(click)="feedbackClick();">Feedback</a>
</div>
<div class="uk-margin-small-top">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a [routerLink]="properties.searchLinkToAdvancedResults"
[queryParams]="routerHelper.createQueryParams(['f0', 'fv0', 'size'], ['fos', subject, '50'])">
<a [routerLink]="properties.searchLinkToResults"
[queryParams]="{'fos': urlEncodeAndQuote(subject)}">
{{subject}}
</a>
</div>
@ -30,24 +36,33 @@ export class FosComponent {
@Input() subjects: string[];
@Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter();
@Output() feedbackClicked = new EventEmitter();
public lessBtn: boolean = false;
public threshold: number = 2;
public routerHelper: RouterHelper = new RouterHelper();
public properties = properties;
public title: string = "Fields of Science (FOS) [Beta]";
public title: string = "Fields of Science";
public viewAllClick() {
if(this.subjects.length <= this.threshold*2) {
this.viewAll = true;
this.lessBtn = true;
} else {
// if(this.subjects.length <= this.threshold*2) {
// this.viewAll = true;
// this.lessBtn = true;
// } else {
this.viewAll = true;
this.viewAllClicked.emit('fos');
}
// }
}
public viewLessClick() {
this.viewAll = false;
this.viewAllClicked.emit("");
}
public feedbackClick() {
this.feedbackClicked.emit("");
}
public urlEncodeAndQuote(str: string): string {
return StringUtils.quote(StringUtils.URIEncode(str));
}
}

View File

@ -11,14 +11,14 @@ import {properties} from "../../../../environments/environment";
{{title}}
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a>
<a *ngIf="fundedByProjects && fundedByProjects.length > threshold && !viewAll"
(click)="viewAllClick();">View more</a>
(click)="viewAllClick();" class="view-more-less-link">View all</a>
</div>
<div>
<span *ngFor="let item of fundedByProjects.slice(0, viewAll?fundedByProjects.length:threshold) let i=index">
<span class="uk-text-emphasis">
<a class="uk-link-text">
<a class="uk-link uk-link-text">
<span
*ngIf="item['funderShortname'] || item['funderName']">{{item['funderShortname'] ? item['funderShortname'] : item['funderName']}}</span>
<span *ngIf="!item['funderShortname'] && !item['funderName']">[no funder available]</span>

View File

@ -271,7 +271,8 @@ export class ParsingFunctions {
"accessRight": null,
"accessRightIcon": "",
"types": [],
"years": []
"years": [],
"license": ""
};
if (instance.hasOwnProperty("hostedby")) {
@ -355,6 +356,10 @@ export class ParsingFunctions {
available.accessRightIcon = this.unknown;
}
if(instance.hasOwnProperty("license")) {
available.license = Array.isArray(instance['license']) ? instance['license'][0] : instance['license'];
}
hostedBy_collectedFrom.push(available);
}
@ -570,7 +575,7 @@ export class ParsingFunctions {
}
// publication & dataset landing : for subjects and otherSubjects and classifiedSubjects
parseAllSubjects(_subjects: any): [string[], Map<string, string[]>, Map<string, string[]>, string[], string[], any[]] {
parseAllSubjects(_subjects: any, vocabulary: any): [string[], Map<string, string[]>, Map<string, string[]>, string[], string[], any[]] {
let eoscSubjectsFound = [];
let subjects: string[];
let otherSubjects: Map<string, string[]>;
@ -586,7 +591,22 @@ export class ParsingFunctions {
for (let i = 0; i < length; i++) {
subject = Array.isArray(_subjects) ? _subjects[i] : _subjects;
if (subject.classid != "") {
if (subject.inferred && subject.inferred == true) {
if (subject.classid == "keyword") {
let content: string = subject.content+"";
let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, classifiedSubjects, eoscSubjectsFound, subject, content);
let found: boolean = checkAndAddEoscSubjectResp["found"];
if(found) {
setOfEoscSubjects = checkAndAddEoscSubjectResp["setOfEoscSubject"];
classifiedSubjects = checkAndAddEoscSubjectResp["classifiedSubjects"];
eoscSubjectsFound = checkAndAddEoscSubjectResp["eoscSubjectsFound"];
} else {
if (subjects == undefined) {
subjects = new Array<string>();
}
subjects.push(content);
}
} else if (!vocabulary || vocabulary[subject.classid] || subject.classid === "SDG" || subject.classid === "FOS") {
// if (subject.inferred && subject.inferred == true) {
if(subject.classid === "SDG") {
if (sdg == undefined) {
sdg = new Array<string>();
@ -616,21 +636,6 @@ export class ParsingFunctions {
classifiedSubjects.get(subject.classname).push(content);
}
}
} else {
if (subject.classid == "keyword") {
let content: string = subject.content+"";
let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, classifiedSubjects, eoscSubjectsFound, subject, content);
let found: boolean = checkAndAddEoscSubjectResp["found"];
if(found) {
setOfEoscSubjects = checkAndAddEoscSubjectResp["setOfEoscSubject"];
classifiedSubjects = checkAndAddEoscSubjectResp["classifiedSubjects"];
eoscSubjectsFound = checkAndAddEoscSubjectResp["eoscSubjectsFound"];
} else {
if (subjects == undefined) {
subjects = new Array<string>();
}
subjects.push(content);
}
} else {
let content: string = subject.content+"";
let checkAndAddEoscSubjectResp = this.checkAndAddEoscSubject(setOfEoscSubjects, classifiedSubjects, eoscSubjectsFound, subject, content);
@ -649,7 +654,6 @@ export class ParsingFunctions {
}
}
}
}
return [subjects, otherSubjects, classifiedSubjects, fos, sdg, eoscSubjectsFound];
}

View File

@ -19,9 +19,9 @@ import {OpenaireEntities} from "../../utils/properties/searchFields";
{{title}}
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less</a>
<a *ngIf="communities && communities.length > threshold && !viewAll"
(click)="viewAllClick();">View more</a>
(click)="viewAllClick();" class="view-more-less-link">View all</a>
</div>
<div *ngFor="let community of communities.slice(0, viewAll?communities.length:threshold)" class="uk-text-truncate">
<!-- If there are any communities with dashboard -->

View File

@ -1,19 +1,25 @@
import {Component, EventEmitter, Input, Output} from "@angular/core";
import {RouterHelper} from "../../utils/routerHelper.class";
import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class";
@Component({
selector: 'sdg',
template: `
<div class="uk-margin-small-bottom uk-flex uk-flex-between">
<span *ngIf="viewAll && !lessBtn" class="clickable uk-h6 uk-flex uk-flex-middle" (click)="viewLessClick()">
<div class="uk-text-xsmall" style="color: #EEB204">Beta</div>
<div [class]="'uk-flex uk-flex-between uk-flex-middle uk-margin-'+(viewAll?'':'small-')+'bottom'">
<span *ngIf="viewAll" class="clickable uk-h6 uk-flex uk-flex-middle uk-margin-small-right uk-margin-remove-bottom"
(click)="viewLessClick()">
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
{{title}}
<span uk-tooltip="Sustainable Development Goals">{{title}}</span>
</span>
<span *ngIf="!viewAll || lessBtn" class="uk-text-light-grey">{{title}}</span>
<a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>
<span *ngIf="!viewAll" class="uk-text-light-grey uk-text-nowrap uk-margin-small-right" uk-tooltip="Sustainable Development Goals">{{title}}</span>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a>-->
<a *ngIf="subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();">View more</a>
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate" uk-tooltip="View all & feedback">
View all & feedback</a>
<a *ngIf="(subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate"
(click)="feedbackClick();">Feedback</a>
</div>
<div class="uk-margin-small-bottom uk-flex">
@ -21,8 +27,8 @@ import {properties} from "../../../../environments/environment";
loading="lazy" alt="sdg_colors" style="width:27px; height:27px">
<div class="uk-margin-small-left">
<div *ngFor="let subject of subjects.slice(0, viewAll?subjects.length:threshold); let i=index" class="uk-text-truncate">
<a [routerLink]=" properties.searchLinkToAdvancedResults"
[queryParams]="routerHelper.createQueryParams(['f0', 'fv0', 'size'], ['sdg', subject, '50'])">
<a [routerLink]=" properties.searchLinkToResults"
[queryParams]="{'sdg': urlEncodeAndQuote(subject)}">
{{subject}}
</a>
</div>
@ -35,24 +41,33 @@ export class SdgComponent {
@Input() subjects: string[];
@Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter();
@Output() feedbackClicked = new EventEmitter();
public lessBtn: boolean = false;
public threshold: number = 4;
public routerHelper: RouterHelper = new RouterHelper();
public properties = properties;
public title: string = "Sustainable Development Goals (SDG) [Beta]";
public title: string = "SDGs";
public viewAllClick() {
if(this.subjects.length <= this.threshold*2) {
this.viewAll = true;
this.lessBtn = true;
} else {
// if(this.subjects.length <= this.threshold*2) {
// this.viewAll = true;
// this.lessBtn = true;
// } else {
this.viewAll = true;
this.viewAllClicked.emit('sdg');
}
// }
}
public viewLessClick() {
this.viewAll = false;
this.viewAllClicked.emit("");
}
public feedbackClick() {
this.feedbackClicked.emit("");
}
public urlEncodeAndQuote(str: string): string {
return StringUtils.quote(StringUtils.URIEncode(str));
}
}

View File

@ -44,7 +44,7 @@ import {properties} from "../../../../environments/environment";
<ng-container *ngTemplateOutlet="identifiers_template; context: { modal: false}"></ng-container>
</div>
<div *ngIf="isLarge && showViewAll" class="uk-text-right uk-margin-small-top">
<a (click)="openIdentifiersModal()">View all</a>
<a (click)="openIdentifiersModal()" class="view-more-less-link">View all</a>
</div>
<modal-alert #identifiersModal>

View File

@ -17,23 +17,11 @@ import {properties} from "../../../../environments/environment";
<div class="uk-text-meta uk-margin-small-bottom">
Subjects by Vocabulary
</div>
<div *ngFor="let key of getKeys(classifiedSubjects)" class="uk-grid uk-grid-small uk-flex-middle" uk-grid>
<span>
<span uk-icon="tag"></span>
<span class="uk-text-bold uk-margin-small-right"> {{key}}: </span>
</span>
<span *ngFor="let subject of classifiedSubjects.get(key)" class="uk-width-auto uk-flex">
<span class="uk-border-rounded uk-label uk-label-small uk-label-primary uk-text-truncate">
<span>{{subject}}</span>
<!-- <span *ngIf="specialSubjects.indexOf(subject) == -1 ">{{subject}}</span>-->
<!-- <a class="uk-link-reset" *ngIf="specialSubjects.indexOf(subject) != -1"-->
<!-- [routerLink]=" properties.searchLinkToAdvancedResults"-->
<!-- [queryParams]="getSubjectParameter(subject)">-->
<!-- {{subject}}-->
<!-- </a>-->
</span>
</span>
<ng-container *ngTemplateOutlet="subjects_by_vocabulary_template; context: {customClasses: 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container>
<div *ngIf="isClassifiedLarge" class="uk-text-right">
<a (click)="openSubjectsByVocabularyModal()" class="view-more-less-link">View all</a>
</div>
</ng-container>
<ng-container *ngIf="(subjects && subjects.length > 0) || (otherSubjects && otherSubjects.size > 0)">
<div class="uk-text-meta uk-margin-small-bottom" [class.uk-margin-medium-top]="classifiedSubjects && classifiedSubjects.size > 0">
@ -41,7 +29,7 @@ import {properties} from "../../../../environments/environment";
</div>
<ng-container *ngTemplateOutlet="subjects_template; context: {customClasses: 'multi-line-ellipsis lines-2', id: 'content'}"></ng-container>
<div *ngIf="isLarge" class="uk-text-right uk-margin-small-top">
<a (click)="openSubjectsModal()">View all</a>
<a (click)="openSubjectsModal()" class="view-more-less-link">View all</a>
</div>
</ng-container>
@ -65,6 +53,30 @@ import {properties} from "../../../../environments/environment";
<ng-container *ngTemplateOutlet="subjects_template"></ng-container>
</div>
</modal-alert>
<ng-template #subjects_by_vocabulary_template let-customClasses="customClasses" let-id="id">
<div *ngFor="let key of getKeys(classifiedSubjects) let i=index"
class="uk-flex-inline uk-flex-wrap uk-margin-medium-right"
[ngClass]="customClasses">
<p #classifiedContent [id]="id+'_'+key" class="uk-grid uk-grid-small uk-flex-middle uk-margin-bottom uk-margin-remove-left" uk-grid>
<span class="uk-padding-remove">
<span uk-icon="tag"></span>
<span class="uk-text-bold uk-margin-small-right"> {{key}}: </span>
</span>
<span *ngFor="let subject of classifiedSubjects.get(key); let j=index" class="uk-width-auto uk-padding-remove uk-display-inline-block">
<span class="uk-border-rounded uk-label uk-label-small uk-label-primary uk-text-truncate uk-margin-small-right">
{{subject}}
</span>
</span>
</p>
</div>
</ng-template>
<modal-alert #subjectsByVocabularyModal large="true">
<div class="uk-text-small">
<ng-container *ngTemplateOutlet="subjects_by_vocabulary_template"></ng-container>
</div>
</modal-alert>
`
})
@ -73,14 +85,18 @@ export class ShowSubjectsComponent {
@Input() otherSubjects: Map<string, string[]>;
@Input() classifiedSubjects: Map<string, string[]>;
isLarge: boolean = false;
isClassifiedLarge: boolean = false;
properties = properties;
specialSubjects = [];
@ViewChildren("content", { read: ElementRef }) content: QueryList<ElementRef>;
@ViewChildren("classifiedContent", { read: ElementRef }) classifiedContent: QueryList<ElementRef>;
@ViewChild('subjectsModal') subjectsModal;
@ViewChild('subjectsByVocabularyModal') subjectsByVocabularyModal;
@HostListener('window:resize', ['$event'])
onResize(event) {
this.checkLarge();
this.checkLargeClassified();
}
constructor(private cdr: ChangeDetectorRef) {
@ -113,6 +129,7 @@ export class ShowSubjectsComponent {
ngAfterViewInit() {
this.checkLarge();
this.checkLargeClassified();
}
checkLarge() {
@ -124,6 +141,19 @@ export class ShowSubjectsComponent {
}
}
checkLargeClassified() {
let overflow = 42;
if(typeof document !== "undefined") {
this.getKeys(this.classifiedSubjects).forEach(key => {
let tag = this.classifiedContent.find(tag => tag.nativeElement.id === "content_"+key);
if(tag && tag.nativeElement.offsetHeight > overflow) {
this.isClassifiedLarge = true;
}
});
this.cdr.detectChanges();
}
}
public getKeys(map) {
return Array.from(map.keys());
}
@ -137,4 +167,11 @@ export class ShowSubjectsComponent {
this.subjectsModal.alertTitle = "Subjects";
this.subjectsModal.open();
}
public openSubjectsByVocabularyModal() {
this.subjectsByVocabularyModal.cancelButton = false;
this.subjectsByVocabularyModal.okButton = false;
this.subjectsByVocabularyModal.alertTitle = "Subjects by Vocabulary";
this.subjectsByVocabularyModal.open();
}
}

View File

@ -352,12 +352,12 @@
<ng-container *ngTemplateOutlet="organizations_template; context: { threshold: lessBtnOrganizations ? projectInfo.organizations.length : thresholdOrganizations }"></ng-container>
<div *ngIf="projectInfo.organizations.length > thresholdOrganizations && !lessBtnOrganizations"
class="uk-text-center">
<a (click)="viewAllOrganizationsClick();">
View more
<a (click)="viewAllOrganizationsClick();" class="view-more-less-link">
View all
</a>
</div>
<div *ngIf="viewAllOrganizations && lessBtnOrganizations" class="uk-text-center">
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;">View less</a>
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;" class="view-more-less-link">View less</a>
</div>
</div>
</div>

View File

@ -95,7 +95,7 @@
<!--Feedback-->
<div *ngIf="properties.reCaptchaSiteKey" class="uk-width-expand uk-text-right">
<span class="uk-text-meta uk-text-xsmall">See an issue? </span>
<a (click)="showFeedback = true; scroll()" class="uk-text-xsmall"> Report it here</a>
<a (click)="feedbackClicked()" class="uk-text-xsmall">Give us feedback</a>
</div>
</div>
</ng-template>
@ -287,12 +287,12 @@
<ng-container *ngTemplateOutlet="organizations_template; context: { threshold: lessBtnOrganizations ? resultLandingInfo.organizations.length : thresholdOrganizations }"></ng-container>
<div *ngIf="resultLandingInfo.organizations.length > thresholdOrganizations && !lessBtnOrganizations"
class="uk-text-center">
<a (click)="viewAllOrganizationsClick();">
View more
<a (click)="viewAllOrganizationsClick();" class="view-more-less-link">
View all
</a>
</div>
<div *ngIf="viewAllOrganizations && lessBtnOrganizations" class="uk-text-center">
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;">View less</a>
<a (click)="viewAllOrganizations = !viewAllOrganizations; lessBtnOrganizations=false;" class="view-more-less-link">View less</a>
</div>
</div>
</div>
@ -458,10 +458,10 @@
</div>
</div>
<div *ngIf="resultLandingInfo.sdg && resultLandingInfo.sdg.length > 0 && (!viewAll || viewAll=='sdg')">
<sdg [subjects]="resultLandingInfo.sdg" (viewAllClicked)="viewAll=$event"></sdg>
<sdg [subjects]="resultLandingInfo.sdg" (viewAllClicked)="viewAll=$event" (feedbackClicked)="feedbackClicked('Sustainable Development Goals (SDGs)')"></sdg>
</div>
<div *ngIf="resultLandingInfo.fos && resultLandingInfo.fos.length > 0 && (!viewAll || viewAll=='fos')">
<fos [subjects]="resultLandingInfo.fos" (viewAllClicked)="viewAll=$event"></fos>
<fos [subjects]="resultLandingInfo.fos" (viewAllClicked)="viewAll=$event" (feedbackClicked)="feedbackClicked('Fields of Science and Technology (FOS)')"></fos>
</div>
<!-- Funded By -->
<div *ngIf="resultLandingInfo.fundedByProjects && resultLandingInfo.fundedByProjects.length > 0 && (!viewAll || viewAll=='fundedBy')">
@ -485,7 +485,7 @@
<feedback *ngIf="resultLandingInfo && properties.reCaptchaSiteKey" [resultLandingInfo]="resultLandingInfo"
[properties]="properties" [entityType]="getTypeName()" [fields]="feedbackFields"
[(showForm)]="showFeedback"></feedback>
[(showForm)]="showFeedback" [preSelectedField]="feedbackPreSelectedField"></feedback>
</div>
<!-- Other versions -->
<modal-alert *ngIf="resultLandingInfo && resultLandingInfo.deletedByInferenceIds"

View File

@ -18,7 +18,7 @@ import {IndexInfoService} from "../../utils/indexInfo.service";
import {Identifier, StringUtils} from "../../utils/string-utils.class";
import {properties} from "../../../../environments/environment";
import {ISVocabulariesService} from "../../utils/staticAutoComplete/ISVocabularies.service";
import {Subscription} from "rxjs";
import {forkJoin, Observable, Subscription, zip} from "rxjs";
import {AnnotationComponent} from "../annotation/annotation.component";
import {ParsingFunctions} from "../landing-utils/parsingFunctions.class";
import {ConnectHelper} from "../../connect/connectHelper";
@ -106,10 +106,11 @@ export class ResultLandingComponent {
public pageContents = null;
public divContents = null;
public showFeedback: boolean = false;
public feedbackPreSelectedField: string = "";
public feedbackFields: string [] = [
'Title', 'Authors', 'Access rights',
'Publisher information', 'Funding Information',
'Persistent identifiers', 'Sustainable Development Goals (SDG)',
'Persistent identifiers', 'Sustainable Development Goals (SDGs)',
'Fields of Science and Technology (FOS)', 'Other'];
public pidsArrayString: string = "";
@ -205,7 +206,7 @@ export class ResultLandingComponent {
this.type="publication";
}
if ((this.id && StringUtils.isOpenAIREID(this.id)) || (this.identifier)) {
this.getProvenanceVocabularyAndResultLandingInfo();
this.getVocabulariesAndResultLandingInfo();
} else {
this.showLoading = false;
@ -363,21 +364,30 @@ export class ResultLandingComponent {
));
}
private getProvenanceVocabularyAndResultLandingInfo() {
private getVocabulariesAndResultLandingInfo() {
this.errorMessage = '';
this.showLoading = true;
if (typeof document !== 'undefined') {
this.subscriptions.push(this._vocabulariesService.getProvenanceActionVocabulary(this.properties).subscribe(
provenanceActionVocabulary => {
this.getResultLandingInfo(provenanceActionVocabulary);
let observables: Array<Observable<any>> = [];
observables.push(this._vocabulariesService.getProvenanceActionVocabulary(this.properties));
observables.push(this._vocabulariesService.getSubjectsVocabulary(this.properties));
// observables.push(this.indexInfoService.getLastIndexDate(properties));
// observables.push(this.indexInfoService.getLastOrcidUpdateDate(properties));
this.subscriptions.push(forkJoin(observables)
.subscribe(
// this.subscriptions.push(forkJoin(observables).subscribe(
// this.subscriptions.push(this._vocabulariesService.getProvenanceActionVocabulary(this.properties).subscribe(
vocabularies => {
this.getResultLandingInfo(vocabularies[0], vocabularies[1]);
}, err => {
this.getResultLandingInfo(null);
this.getResultLandingInfo(null, null);
this.handleError("Error getting provenance action vocabulary for " + this.type, err);
}
));
} else {
this.getResultLandingInfo(null);
this.getResultLandingInfo(null, null);
}
}
@ -424,14 +434,14 @@ export class ResultLandingComponent {
// return numberOfTabs;
// }
private getResultLandingInfo(provenanceActionVocabulary: any) {
private getResultLandingInfo(provenanceActionVocabulary: any, subjectsVocabulary?: string) {
if(this.resultFromInput && this.resultLandingInfo){
this.showLoading = false;
return;
}
this.resultLandingInfo = null;
this.hasAltMetrics = false;
this.subscriptions.push(this._resultLandingService.getResultLandingInfo(this.id, this.identifier, this.type, provenanceActionVocabulary, this.properties).subscribe(
this.subscriptions.push(this._resultLandingService.getResultLandingInfo(this.id, this.identifier, this.type, provenanceActionVocabulary, subjectsVocabulary, this.properties).subscribe(
data => {
this.resultLandingInfo = data;
this.id = this.resultLandingInfo.objIdentifier;
@ -531,6 +541,7 @@ export class ResultLandingComponent {
return !!this.resultLandingInfo && (
(!!this.resultLandingInfo.description && this.resultLandingInfo.description.length > 0)
|| !!this.resultLandingInfo.subjects
|| (this.resultLandingInfo.classifiedSubjects && this.resultLandingInfo.classifiedSubjects.size > 0)
|| (!!this.resultLandingInfo.organizations && this.resultLandingInfo.organizations.length > 0));
}
@ -873,4 +884,11 @@ export class ResultLandingComponent {
this.organizationsModal.alertTitle = "Related "+this.openaireEntities.ORGANIZATIONS;
this.organizationsModal.open();
}
public feedbackClicked(preSelectedField: string = "") {
this.feedbackPreSelectedField=preSelectedField;
this.showFeedback = true;
this.scroll();
this.viewAll = "";
}
}

View File

@ -56,7 +56,7 @@ export class ResultLandingService {
}
}
getResultLandingInfo (id: string, identifier: Identifier, type: string, provenanceActionVocabulary: any, properties: EnvProperties): any {
getResultLandingInfo (id: string, identifier: Identifier, type: string, provenanceActionVocabulary: any, subjectsVocabulary: any, properties: EnvProperties): any {
let url: string = this.buildResultLandingInfoUrl(id, identifier, type);
let finalUrl: string = (properties.useCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url;
@ -94,9 +94,11 @@ export class ResultLandingService {
(res[1]['extraInfo'] !== undefined && res[1]['extraInfo']['references'] !== undefined)
? res[1]['extraInfo']['references']['reference'] : null, // 12
res[0], // 13
res[2] // 14
res[2], // 14
(res[1]['extraInfo'] !== undefined && res[1]['extraInfo']['citations'] !== undefined)
? res[1]['extraInfo']['citations']['citation'] : null, // 15
]))
.pipe(map(res => this.parseResultLandingInfo(res, provenanceActionVocabulary, properties)));
.pipe(map(res => this.parseResultLandingInfo(res, provenanceActionVocabulary, subjectsVocabulary, properties)));
}
// getProvenanceActionVocabulary (properties: EnvProperties): any {
@ -122,7 +124,7 @@ export class ResultLandingService {
return throwError(error || 'Server error');
}
parseResultLandingInfo (data: any, provenanceActionVocabulary: any, properties: EnvProperties): any {
parseResultLandingInfo (data: any, provenanceActionVocabulary: any, subjectsVocabulary: any, properties: EnvProperties): any {
this.resultLandingInfo = new ResultLandingInfo();
// res
@ -331,7 +333,7 @@ export class ResultLandingService {
// res['result']['metadata']['oaf:entity']['oaf:result']['subject']
if(data[7] != null) {
let subjectResults: [string[], Map<string, string[]>, Map<string, string[]>, string[], string[], any[]] = this.parsingFunctions.parseAllSubjects(data[7]);
let subjectResults: [string[], Map<string, string[]>, Map<string, string[]>, string[], string[], any[]] = this.parsingFunctions.parseAllSubjects(data[7], subjectsVocabulary);
this.resultLandingInfo.subjects = subjectResults[0];
this.resultLandingInfo.otherSubjects = subjectResults[1];
this.resultLandingInfo.classifiedSubjects = subjectResults[2];
@ -358,11 +360,16 @@ export class ResultLandingService {
this.resultLandingInfo.programmingLanguages = this.parsingFunctions.parseProgrammingLanguages(data[11]);
}
// res['result']['metadata']['oaf:entity']['extraInfo']['citations']['citation']
// res['result']['metadata']['oaf:entity']['extraInfo']['references']['reference']
if(data[12] != null) {
this.resultLandingInfo.references = this.parsingFunctions.parseReferences(data[12]);
}
// #7509 - OLD: res['result']['metadata']['oaf:entity']['extraInfo']['citations']['citation']
if(data[12] == null && data[15] != null) {
this.resultLandingInfo.references = this.parsingFunctions.parseReferences(data[15]);
}
// res['result']['metadata']['oaf:entity']['oaf:result']['context']
if(data[8] != null) {
this.resultLandingInfo.contexts = this.parsingFunctions.parseContexts(data[8]);

View File

@ -441,7 +441,7 @@ export class OrcidWorkComponent {
}
private getResultLandingInfo(action: string) {
this.subscriptions.push(this.resultLandingService.getResultLandingInfo(this.resultId, null, this.type, null, properties).subscribe(
this.subscriptions.push(this.resultLandingService.getResultLandingInfo(this.resultId, null, this.type, null, null, properties).subscribe(
resultLandingInfo => {
this.resultLandingInfo = resultLandingInfo;
if (this.resultLandingInfo && this.resultLandingInfo.identifiers) {

View File

@ -12,10 +12,11 @@
</div>
</div>
<div *ngIf="addShowMore && (filter.values.length) > filterValuesNum">
<a *ngIf="filterValuesNum > 0 " [class]="((isDisabled)?'uk-disabled uk-link-muted ':'uk-link') + ' uk-margin-small-top'" (click)="toggle($event)">
<span *ngIf="!isOpen">+ View all</span>
<a *ngIf="filterValuesNum > 0 " class="uk-text-small view-more-less-link uk-margin-small-top" [ngClass]="((isDisabled)?'uk-disabled uk-link-muted ':'')" (click)="toggle($event)">
<span *ngIf="!isOpen">View all</span>
<span *ngIf="isOpen">View less </span>
</a>
<div *ngIf="isOpen" class="uk-text-small uk-margin-small-bottom">
<div *ngIf="isOpen" class="uk-text-small uk-margin-small-top uk-margin-small-bottom">
<div class="uk-margin-small-left">
<div class="uk-text-meta">Top 100 values are shown in the filters</div>
<div class="uk-flex uk-flex-bottom uk-margin-top">
@ -34,9 +35,6 @@
</ng-container>
</div>
</div>
<a *ngIf="filterValuesNum > 0 && filterValuesNum !=0" [class]="(isDisabled)?'uk-disabled uk-link-muted ':'uk-link'" (click)="toggle($event)">
<span *ngIf="isOpen">- View less</span>
</a>
</div>
</div>
</div>

View File

@ -8,11 +8,12 @@ import {ModalModule} from '../../utils/modal/modal.module';
import { MatSelectModule } from "@angular/material/select";
import {RouterModule} from "@angular/router";
import {InputModule} from '../../sharedComponents/input/input.module';
import {IconsModule} from "../../utils/icons/icons.module";
@NgModule({
imports: [
CommonModule, FormsModule, ModalModule, MatSelectModule, RouterModule,
InputModule
InputModule, IconsModule
],
declarations: [
SearchFilterComponent, SearchFilterModalComponent

View File

@ -83,7 +83,7 @@ import {properties} from "../../../../environments/environment";
</span>
</div>
<div *ngIf="viewAll && lessBtn" class="uk-width-1-1 uk-text-right uk-text-small">
<a (click)="viewAll = !viewAll; lessBtn=false;">View less authors</a>
<a (click)="viewAll = !viewAll; lessBtn=false;" class="view-more-less-link">View less authors</a>
</div>
<modal-alert #authorsModal>

View File

@ -10,6 +10,7 @@ export interface HostedByCollectedFrom {
types: string[];
years: string[];
accessRightIcon: string;
license?: string;
}
export interface Journal {

View File

@ -10,6 +10,7 @@ import {catchError, map} from 'rxjs/operators';
export class ISVocabulariesService {
private vocabularies: Map<string, BehaviorSubject<AutoCompleteValue[]>> = new Map<string, BehaviorSubject<AutoCompleteValue[]>>();
private provenanceActionVocabulary: BehaviorSubject<{}> = new BehaviorSubject(null);
private subjectsVocabulary: BehaviorSubject<any> = new BehaviorSubject<any>(null);
private subscriptions = [];
constructor(private http: HttpClient) {}
@ -213,7 +214,7 @@ export class ISVocabulariesService {
}
));
});
this.clearSubscriptions();
// this.clearSubscriptions();
}
return this.provenanceActionVocabulary.getValue();
}
@ -234,6 +235,50 @@ export class ISVocabulariesService {
return provenanceActionVocabulary;
}
getSubjectsVocabulary(properties: EnvProperties): Observable<any> {
let vocabulary = "dnet:subject_classification_typologies.json";
return from(this.getSubjectsVocabularyFromServiceAsync(vocabulary, properties));
}
async getSubjectsVocabularyFromServiceAsync (vocabularyName: string, properties: EnvProperties): Promise<{}> {
if(!this.subjectsVocabulary || !this.subjectsVocabulary.getValue()) {
await new Promise<any>(resolve => {
this.subscriptions.push(this.getSubjectsVocabularyFromService(vocabularyName, properties).subscribe(
vocabularyRes => {
// console.log(vocabularyRes);
this.subjectsVocabulary.next(vocabularyRes);
resolve();
},
error => {
this.subjectsVocabulary.next(null);
resolve();
}
));
});
// this.clearSubscriptions();
}
return this.subjectsVocabulary.getValue();
}
getSubjectsVocabularyFromService (vocabularyName: string, properties: EnvProperties): any {
let url = properties.vocabulariesAPI+vocabularyName;
return this.http.get((properties.useLongCache) ? (properties.cacheUrl + encodeURIComponent(url)) : url)
.pipe(map(res => res['terms']))
// .pipe(map(res => res.code))
.pipe(map(res => this.parseSubjectsVocabulary(res)));
}
parseSubjectsVocabulary(terms: any) {
var subjectsVocabulary: {} = {};
for(let term of terms) {
if(term.code != "keyword") {
subjectsVocabulary[term.code] = term.englishName;
}
}
return subjectsVocabulary;
}
private handleError(error: HttpErrorResponse) {
// in a real world app, we may send the error to some remote logging infrastructure