create new component for handling SDG suggestions

This commit is contained in:
Alex Martzios 2023-02-17 19:08:44 +02:00
parent 4858e9f22d
commit 75ad00db3f
11 changed files with 188 additions and 40 deletions

View File

@ -16,8 +16,6 @@ import {FosComponent} from "./fos.component";
import {SdgComponent} from "./sdg.component";
import {IconsModule} from "../../utils/icons/icons.module";
import {AlertModalModule} from "../../utils/modal/alertModal.module";
import {SdgSelectionComponent} from '../../sdg/sdg-selection/sdg-selection.component';
import {FosSelectionComponent} from '../../fos/fos-selection/fos-selection.component';
import { SearchInputModule } from '../../sharedComponents/search-input/search-input.module';
@ -29,16 +27,14 @@ import { SearchInputModule } from '../../sharedComponents/search-input/search-in
declarations: [
ShowIdentifiersComponent,ShowSubjectsComponent,
FundedByComponent,AvailableOnComponent,TabTableComponent,
RelatedToComponent, FosComponent, SdgComponent,
SdgSelectionComponent, FosSelectionComponent
RelatedToComponent, FosComponent, SdgComponent
],
providers:[
],
exports: [
ShowIdentifiersComponent, ShowSubjectsComponent,
FundedByComponent,AvailableOnComponent, TabTableComponent, ShowPublisherComponent,
RelatedToComponent, FosComponent, SdgComponent,
SdgSelectionComponent, FosSelectionComponent
RelatedToComponent, FosComponent, SdgComponent
]
})
export class ResultLandingUtilsModule { }

View File

@ -0,0 +1,101 @@
import {HttpClient} from "@angular/common/http";
import {Component, Input, ViewChild} from "@angular/core";
import {FormBuilder, UntypedFormGroup, Validators} from "@angular/forms";
import {SdgSelectionComponent} from "../../../sdg/sdg-selection/sdg-selection.component";
import {properties} from "../../../../../environments/environment";
import {EnvProperties} from "../../../utils/properties/env-properties";
import {EmailService} from "../../../utils/email/email.service";
import {Subscription} from "rxjs";
import {Composer} from "../../../utils/email/composer";
@Component({
selector: 'sdg-fos-suggest',
template: `
<sdg-selection #sdgSelection [class.uk-hidden]="!sdgSelectionStep1" [subjects]="subjects"></sdg-selection>
<div [class.uk-hidden]="sdgSelectionStep1">
<div class="uk-flex uk-flex-column uk-flex-middle">
<div>Thank you for your feedback.</div>
<div>Before sending us your options, would you like to leave us your e-mail to notify you about the reporting status?</div>
<div input class="uk-width-1-2 uk-margin-medium-top uk-margin-medium-bottom"
[formInput]="form.get('email')" placeholder="E-mail">
</div>
<div>
<re-captcha (resolved)="handleRecaptcha($event)" [siteKey]="properties.reCaptchaSiteKey">
</re-captcha>
</div>
</div>
</div>
`
})
export class SdgFosSuggestComponent {
@Input("subjects") subjects;
@Input() title;
public properties: EnvProperties = properties;
public sdgSelectionStep1: boolean = true;
@ViewChild("sdgSelection") sdgSelection: SdgSelectionComponent;
public form: UntypedFormGroup;
subscriptions: Subscription[] = [];
constructor(
private emailService: EmailService,
private fb: FormBuilder
) {}
ngOnInit() {
let url;
if (typeof window !== "undefined") {
url = window.location.href;
}
this.form = this.fb.group({
name: this.fb.control(this.title),
url: this.fb.control(url),
email: this.fb.control('', Validators.email),
sdgs: this.fb.array([], Validators.required),
recaptcha: this.fb.control('', Validators.required),
});
}
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
if (subscription instanceof Subscription) {
subscription.unsubscribe();
}
});
}
public sdgModalOutput() {
if(this.sdgSelectionStep1) {
this.sdgSelectionStep1 = false;
} else {
console.log(this.sdgSelection.sdgs.filter(element => element.checked == true));
console.log(this.form.get('email').value);
// email functionality
this.subscriptions.push(this.emailService.contact(this.properties,
Composer.composeEmailForSdgsSuggestion(this.form.value, [this.properties.feedbackmail]), this.form.get('recaptcha').value).subscribe(sent => {
// this.error = !sent;
if (sent) {
if (this.form.get('email').value !== '') {
this.subscriptions.push(this.emailService.contact(this.properties,
Composer.composeEmailForUserAfterFeedback([this.form.get('email').value])).subscribe(sent => {
if (sent) {
//console.log('An email has been sent to user ' + this.form.get('email').value);
}
}));
}
// this.init();
// this.sent = true;
}
// this.sending = false;
}, error => {
console.log(error);
// this.error = true;
// this.sending = false;
}));
}
}
public handleRecaptcha(captchaResponse: string) {
this.form.get('recaptcha').setValue(captchaResponse);
}
}

View File

@ -0,0 +1,25 @@
import {CommonModule} from "@angular/common";
import {NgModule} from "@angular/core";
import {FormsModule} from "@angular/forms";
import {RecaptchaModule} from "ng-recaptcha";
import {SdgSelectionModule} from "src/app/openaireLibrary/sdg/sdg-selection/sdg-selection.module";
import {InputModule} from "../../../sharedComponents/input/input.module";
import {SdgFosSuggestComponent} from "./sdg-fos-suggest.component";
@NgModule({
imports: [
CommonModule, FormsModule, InputModule, SdgSelectionModule, RecaptchaModule
],
declarations: [
SdgFosSuggestComponent
],
providers: [
],
exports: [
SdgFosSuggestComponent
]
})
export class SdgFosSuggestModule {
}

View File

@ -14,13 +14,13 @@ import {StringUtils} from "../../utils/string-utils.class";
<icon class="uk-margin-small-right" name="arrow_back" flex="true" ratio="1.2"></icon>
<span uk-tooltip="Sustainable Development Goals">{{title}}</span>
</span>
<span *ngIf="!viewAll" class="uk-text-emphasis uk-text-bolder uk-text-nowrap uk-margin-small-right" uk-tooltip="Sustainable Development Goals">{{title}}</span>
<span *ngIf="!viewAll" class="uk-text-emphasis uk-text-bolder uk-text-nowrap uk-margin-small-right" uk-tooltip="Sustainable Development Goals">{{title}} ({{subjects.length}})</span>
<!-- <a *ngIf="viewAll && lessBtn" (click)="viewAll = !viewAll; lessBtn=false;">View less</a> -->
<a *ngIf="subjects && subjects.length > threshold && !viewAll"
(click)="viewAllClick();" class="view-more-less-link uk-text-truncate">
(click)="viewAllClick();" class="view-more-less-link uk-link uk-link-text uk-text-truncate">
View all & suggest</a>
<a *ngIf="(subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-text-truncate"
(click)="feedbackClick();">Feedback</a>
<a *ngIf="(subjects && subjects.length <= threshold || viewAll)" class="uk-link uk-link-text uk-text-truncate"
(click)="suggestClick();">Suggest</a>
</div>
<div class="uk-margin-small-bottom uk-flex">
<img src="assets/common-assets/common/The_Global_Goals_Icon_Color.svg"
@ -59,7 +59,7 @@ export class SdgComponent {
@Input() subjects: string[];
@Input() viewAll: boolean = false;
@Output() viewAllClicked = new EventEmitter();
@Output() feedbackClicked = new EventEmitter();
@Output() suggestClicked = new EventEmitter();
public lessBtn: boolean = false;
public threshold: number = 2;
public routerHelper: RouterHelper = new RouterHelper();
@ -71,7 +71,7 @@ export class SdgComponent {
// this.viewAll = true;
// this.lessBtn = true;
// } else {
// this.viewAll = true;
this.viewAll = true;
this.viewAllClicked.emit('sdg');
// }
}
@ -81,8 +81,8 @@ export class SdgComponent {
this.viewAllClicked.emit("");
}
public feedbackClick() {
this.feedbackClicked.emit("");
public suggestClick() {
this.suggestClicked.emit('sdg');
}
public urlEncodeAndQuote(str: string): string {

View File

@ -735,7 +735,7 @@
<ng-template #right_column>
<!-- new metrics box -->
<div *ngIf="resultLandingInfo && resultLandingInfo.measure"
<div *ngIf="resultLandingInfo && resultLandingInfo.measure && !viewAll"
class="uk-margin-medium-top uk-padding uk-padding-remove-vertical">
<div class="landing-metrics-card uk-card uk-card-secondary uk-text-small uk-flex uk-padding-small">
<div class="uk-width-expand uk-flex uk-flex-middle">
@ -791,7 +791,7 @@
</div>
<div *ngIf="resultLandingInfo.sdg && resultLandingInfo.sdg.length > 0 && (!viewAll || viewAll=='sdg')">
<sdg [subjects]="resultLandingInfo.sdg" (viewAllClicked)="openSelectionModal($event)" (feedbackClicked)="feedbackClicked('Sustainable Development Goals (SDGs)')"></sdg>
<sdg [subjects]="resultLandingInfo.sdg" (viewAllClicked)="viewAll=$event" (suggestClicked)="suggestClicked($event)"></sdg>
</div>
<div *ngIf="resultLandingInfo.fos && resultLandingInfo.fos.length > 0 && (!viewAll || viewAll=='fos')">
<fos [subjects]="resultLandingInfo.fos" (viewAllClicked)="openSelectionModal($event)" (feedbackClicked)="feedbackClicked('Fields of Science and Technology (FOS)')"></fos>
@ -986,8 +986,8 @@
</modal-alert>
<modal-alert *ngIf="resultLandingInfo && resultLandingInfo.sdg?.length > 0"
#sdgSelectionModal [large]="true">
<sdg-selection [subjects]="resultLandingInfo.sdg" [properties]="properties"></sdg-selection>
#sdgSelectionModal [large]="true" (alertOutput)="sdgModalOutput()">
<sdg-fos-suggest #sdgFosSuggest [subjects]="resultLandingInfo.sdg" [title]="resultLandingInfo.title"></sdg-fos-suggest>
</modal-alert>
<modal-alert *ngIf="resultLandingInfo && resultLandingInfo.fos?.length > 0"

View File

@ -26,6 +26,7 @@ import {UserManagementService} from "../../services/user-management.service";
import {OpenaireEntities} from "../../utils/properties/searchFields";
import {Option} from "../../sharedComponents/input/input.component";
import {NumberUtils} from '../../utils/number-utils.class';
import {SdgFosSuggestComponent} from '../landing-utils/sdg-fos-suggest/sdg-fos-suggest.component';
declare var ResizeObserver;
@ -114,7 +115,7 @@ export class ResultLandingComponent {
'Publisher information', 'Funding Information',
'Persistent identifiers', 'Sustainable Development Goals (SDGs)',
'Fields of Science and Technology (FOS)', 'Other'];
public pidsArrayString: string = "";
public identifier: Identifier;
@ -144,6 +145,7 @@ export class ResultLandingComponent {
public viewAll: string = "";
@ViewChild("sdgSelectionModal") sdgSelectionModal;
@ViewChild("fosSelectionModal") fosSelectionModal;
@ViewChild("sdgFosSuggest") sdgFosSuggest: SdgFosSuggestComponent;
public noCommunities: boolean = false;
@ -911,6 +913,14 @@ export class ResultLandingComponent {
this.viewAll = "";
}
public suggestClicked(value: string) {
if(value == 'sdg') {
this.openSdgSelectionModal();
} else if(value == 'fos') {
this.openFosSelectionModal();
}
}
public openDescriptionModal() {
this.descriptionModal.alertFooter = false;
this.descriptionModal.alertTitle = "Abstract";
@ -928,17 +938,11 @@ export class ResultLandingComponent {
return formatted.number + formatted.size;
}
public openSelectionModal(value: string) {
if(value == 'sdg') {
this.openSdgSelectionModal();
} else if(value == 'fos') {
this.openFosSelectionModal();
}
}
private openSdgSelectionModal() {
this.sdgSelectionModal.cancelButton = false;
this.sdgSelectionModal.alertTitle = "Please select SDGs that are the most relevant for this publication.";
this.sdgSelectionModal.okButtonText = "Send feedback";
this.sdgSelectionModal.stayOpen = true;
this.sdgSelectionModal.open();
}
@ -947,4 +951,8 @@ export class ResultLandingComponent {
this.fosSelectionModal.alertTitle = "Please select FOS that are the most relevant for this publication.";
this.fosSelectionModal.open();
}
public sdgModalOutput() {
this.sdgFosSuggest.sdgModalOutput();
}
}

View File

@ -36,6 +36,8 @@ import {IconsService} from "../../utils/icons/icons.service";
import {graph, link, quotes, cite, link_to, versions, rocket, fire, landmark, open_access, closed_access} from "../../utils/icons/icons";
import {InputModule} from "../../sharedComponents/input/input.module";
import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.module";
import {RecaptchaModule} from 'ng-recaptcha';
import {SdgFosSuggestModule} from '../landing-utils/sdg-fos-suggest/sdg-fos-suggest.module';
@NgModule({
imports: [
@ -44,7 +46,8 @@ import {EGIDataTransferModule} from "../../utils/dataTransfer/transferData.modul
MetricsModule, AltMetricsModule, Schema2jsonldModule, SEOServiceModule,
DeletedByInferenceModule, ShowAuthorsModule, HelperModule, ResultLandingUtilsModule, AlertModalModule,
AnnotationModule, LandingHeaderModule, NoLoadPaging, ResultPreviewModule, FeedbackModule, TabsModule, LoadingModule,
OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule
OrcidModule, MatFormFieldModule, MatSelectModule, IconsModule, InputModule, EGIDataTransferModule, RecaptchaModule,
SdgFosSuggestModule
],
declarations: [
ResultLandingComponent

View File

@ -6,8 +6,8 @@
<div>
<div *ngFor="let item of firstColumn; let i = index"
class="uk-margin-bottom">
<label>
<input [checked]="subjects.includes(item.id)"
<label [class.uk-text-bolder]="subjects.includes(item.id)">
<input [(ngModel)]="item.checked"
type="checkbox" class="uk-checkbox uk-margin-small-right">
<span class="uk-text-uppercase uk-margin-xsmall-right">Goal</span>
<span>{{item.id}}</span>
@ -17,8 +17,8 @@
<div>
<div *ngFor="let item of secondColumn; let i = index"
class="uk-margin-bottom">
<label>
<input [checked]="subjects.includes(item.id)"
<label [class.uk-text-bolder]="subjects.includes(item.id)">
<input [(ngModel)]="item.checked"
type="checkbox" class="uk-checkbox uk-margin-small-right">
<span *ngIf="i !== secondColumn.length - 1"
class="uk-text-uppercase uk-margin-xsmall-right">Goal</span>

View File

@ -1,5 +1,6 @@
import {HttpClient} from "@angular/common/http";
import {Component, Input} from "@angular/core";
import {properties} from "../../../../environments/environment";
import {EnvProperties} from "../../utils/properties/env-properties";
@Component({
@ -8,7 +9,7 @@ import {EnvProperties} from "../../utils/properties/env-properties";
styleUrls: ['sdg-selection.component.less']
})
export class SdgSelectionComponent {
@Input() properties: EnvProperties;
public properties: EnvProperties = properties;
@Input() subjects: string[];
public loading: boolean;
@ -21,9 +22,10 @@ export class SdgSelectionComponent {
ngOnInit() {
this.loading = true;
this.httpClient.get(this.properties.domain+'/assets/common-assets/vocabulary/sdg.json').subscribe(data => {
this.sdgs = data['sdg'];
console.log(this.sdgs);
this.sdgs.push({code: '18', id: 'No SDGs are relevant for this publication', label: 'No SDG relevant', html: 'No SDG relevant'})
data['sdg'].forEach(element => {
this.sdgs.push({code: element.code, id: element.id, label: element.label, html: element.html, checked: this.subjects.includes(element.id)});
});
this.sdgs.push({code: '18', id: 'No SDGs are relevant for this publication', label: 'Not relevant', html: 'Not relevant', checked: false});
});
this.loading = false;
}

View File

@ -3,21 +3,20 @@ import {NgModule} from "@angular/core";
import {FormsModule} from "@angular/forms";
import {InputModule} from "../../sharedComponents/input/input.module";
import {LoadingModule} from "../../utils/loading/loading.module";
// import {SdgSelectionComponent} from './sdg-selection.component';
import {SdgSelectionComponent} from "./sdg-selection.component";
@NgModule({
imports: [
CommonModule, FormsModule, LoadingModule, InputModule
],
declarations: [
// SdgSelectionComponent
SdgSelectionComponent
],
providers: [
],
exports: [
// SdgSelectionComponent
SdgSelectionComponent
]
})
export class SdgSelectionModule {

View File

@ -136,6 +136,20 @@ export class Composer {
email.recipients = recipients;
return email;
}
public static composeEmailForSdgsSuggestion(info: {name: string, url: string, email: string, sdgs: any[]}, recipients: string[]): Email {
let email: Email = new Email();
email.subject = 'Feedback report for ' + info.name;
email.body = "<div style='font-size:" + this.noteBodySize + "'>"
+ "<p>A user" + ((info.email)?(" with email " + info.email):"") + " has reported the following SDG(s) for "
+ "<a href=\'" + info.url + "\'>" + info.name + "</a></p><ul>";
info.sdgs.forEach((issue, index) => {
email.body += "<br><li><span><b><u>" + issue + "</u></b></span></li>";
});
email.body += "</ul></div>";
email.recipients = recipients;
return email;
}
public static composeEmailForUserAfterFeedback(recipients: string[]): Email {
let email: Email = new Email();