From 6380311b1eb2ab27cc9f813b9cf47f3bd4f41066 Mon Sep 17 00:00:00 2001 From: Alex Martzios Date: Wed, 12 Oct 2022 15:31:34 +0300 Subject: [PATCH] add fixed contact/help button --- explore/src/app/app-routing.module.ts | 20 ++--- explore/src/app/app.component.ts | 94 ++++++++++++++++++++++-- explore/src/app/app.module.ts | 7 +- explore/src/app/fos/fos.component.html | 4 +- explore/src/app/home/home.component.html | 2 +- explore/src/app/home/home.component.ts | 30 ++++++-- explore/src/app/openaireLibrary | 2 +- explore/src/assets/explore-custom.less | 7 ++ 8 files changed, 142 insertions(+), 24 deletions(-) diff --git a/explore/src/app/app-routing.module.ts b/explore/src/app/app-routing.module.ts index 10166089..dcba415f 100644 --- a/explore/src/app/app-routing.module.ts +++ b/explore/src/app/app-routing.module.ts @@ -10,24 +10,26 @@ const routes: Routes = [ {path: 'mail-preferences', loadChildren: () => import('./userEmailPreferences/mailPrefs.module').then(m => m.LibMailPrefsModule)}, {path: 'sdgs', loadChildren: () => import('./sdg/sdg.module').then(m => m.SdgModule)}, {path: 'fields-of-science', loadChildren: () => import('./fos/fos.module').then(m => m.FosModule), data: {extraOffset: 100}}, - {path: 'contact-us', loadChildren: () => import('./contact/contact.module').then(m => m.ContactModule)}, + {path: 'contact-us', loadChildren: () => import('./contact/contact.module').then(m => m.ContactModule), data: {hasQuickContact: false}}, // ORCID Pages {path: 'orcid', loadChildren: () => import('./orcid/orcid.module').then(m => m.LibOrcidModule)}, {path: 'my-orcid-links', loadChildren: () => import('./orcid/my-orcid-links/myOrcidLinks.module').then(m => m.LibMyOrcidLinksModule)}, // Landing Pages - {path: 'search/result', loadChildren: () => import('./landingPages/result/libResult.module').then(m => m.LibResultModule)}, - {path: 'search/publication', loadChildren: () => import('./landingPages/publication/libPublication.module').then(m => m.LibPublicationModule)}, - {path: 'search/dataset', loadChildren: () => import('./landingPages/dataset/libDataset.module').then(m => m.LibDatasetModule)}, - {path: 'search/software', loadChildren: () => import('./landingPages/software/libSoftware.module').then(m => m.LibSoftwareModule)}, - {path: 'search/other', loadChildren: () => import('./landingPages/orp/libOrp.module').then(m => m.LibOrpModule)}, - {path: 'search/project', loadChildren: () => import('./landingPages/project/libProject.module').then(m => m.LibProjectModule)}, + {path: 'search/result', loadChildren: () => import('./landingPages/result/libResult.module').then(m => m.LibResultModule), data: {hasQuickContact: false}}, + {path: 'search/publication', loadChildren: () => import('./landingPages/publication/libPublication.module').then(m => m.LibPublicationModule), data: {hasQuickContact: false}}, + {path: 'search/dataset', loadChildren: () => import('./landingPages/dataset/libDataset.module').then(m => m.LibDatasetModule), data: {hasQuickContact: false}}, + {path: 'search/software', loadChildren: () => import('./landingPages/software/libSoftware.module').then(m => m.LibSoftwareModule), data: {hasQuickContact: false}}, + {path: 'search/other', loadChildren: () => import('./landingPages/orp/libOrp.module').then(m => m.LibOrpModule), data: {hasQuickContact: false}}, + {path: 'search/project', loadChildren: () => import('./landingPages/project/libProject.module').then(m => m.LibProjectModule), data: {hasQuickContact: false}}, { path: 'search/dataprovider', - loadChildren: () => import('././landingPages/dataProvider/libDataProvider.module').then(m => m.LibDataProviderModule) + loadChildren: () => import('././landingPages/dataProvider/libDataProvider.module').then(m => m.LibDataProviderModule), + data: {hasQuickContact: false} }, { path: 'search/organization', - loadChildren: () => import('./landingPages/organization/libOrganization.module').then(m => m.LibOrganizationModule) + loadChildren: () => import('./landingPages/organization/libOrganization.module').then(m => m.LibOrganizationModule), + data: {hasQuickContact: false} }, { path: 'project-report', diff --git a/explore/src/app/app.component.ts b/explore/src/app/app.component.ts index a3e2cad1..538570f3 100644 --- a/explore/src/app/app.component.ts +++ b/explore/src/app/app.component.ts @@ -1,10 +1,8 @@ -import {Component} from '@angular/core'; +import {ChangeDetectorRef, Component, ViewChild} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; - import {EnvProperties} from './openaireLibrary/utils/properties/env-properties'; import {MenuItem} from './openaireLibrary/sharedComponents/menu'; import {EnvironmentSpecificService} from './openaireLibrary/utils/properties/environment-specific.service'; - import {Session, User} from './openaireLibrary/login/utils/helper.class'; import {UserManagementService} from "./openaireLibrary/services/user-management.service"; import {ConfigurationService} from "./openaireLibrary/utils/configuration/configuration.service"; @@ -15,6 +13,14 @@ import {properties} from "../environments/environment"; import {SmoothScroll} from "./openaireLibrary/utils/smooth-scroll"; import {SEOService} from "./openaireLibrary/sharedComponents/SEO/SEO.service"; import {OpenaireEntities} from "./openaireLibrary/utils/properties/searchFields"; +import {FormBuilder, FormGroup, Validators} from '@angular/forms'; +import {QuickContactComponent} from './openaireLibrary/sharedComponents/quick-contact/quick-contact.component'; +import {EmailService} from './openaireLibrary/utils/email/email.service'; +import {Composer} from "./openaireLibrary/utils/email/composer"; +import {AlertModal} from './openaireLibrary/utils/modal/alert'; +import {NotificationHandler} from "./openaireLibrary/utils/notification-handler"; +import {QuickContactService} from './openaireLibrary/sharedComponents/quick-contact/quick-contact.service'; +import {LayoutService} from './openaireLibrary/dashboard/sharedComponents/sidebar/layout.service'; @Component({ //changeDetection: ChangeDetectionStrategy.Default, @@ -46,6 +52,9 @@ import {OpenaireEntities} from "./openaireLibrary/utils/properties/searchFields" + + ` }) export class AppComponent { @@ -56,17 +65,29 @@ export class AppComponent { properties: EnvProperties = properties; user: User; header: Header; + public showQuickContact: boolean; + public contactForm: FormGroup; + public sending: boolean = false; + @ViewChild('quickContact') quickContact: QuickContactComponent; + @ViewChild('modal') modal: AlertModal; + subscriptions = []; constructor(private route: ActivatedRoute, private propertiesService: EnvironmentSpecificService, private router: Router, private userManagementService: UserManagementService, private smoothScroll: SmoothScroll, - private configurationService: ConfigurationService, private _meta: Meta, private seoService: SEOService,) { + private configurationService: ConfigurationService, private _meta: Meta, private seoService: SEOService, + private emailService: EmailService, private fb: FormBuilder, private quickContactService: QuickContactService, + private layoutService: LayoutService, private cdr: ChangeDetectorRef) { } ngOnInit() { if (typeof document !== 'undefined') { this.isClient = true; } + this.subscriptions.push(this.layoutService.hasQuickContact.subscribe(hasQuickContact => { + this.showQuickContact = hasQuickContact; + this.cdr.detectChanges(); + })); this.configurationService.initCommunityInformation(this.properties, this.properties.adminToolsCommunity); this.feedbackmail = this.properties.feedbackmail; if (this.properties.environment == "production" || this.properties.environment == "development") { @@ -88,6 +109,10 @@ export class AppComponent { position: 'left', badge: true }; + this.reset(); + })); + this.subscriptions.push(this.quickContactService.isDisplayed.subscribe(display => { + this.showQuickContact = display; })); } @@ -138,7 +163,6 @@ export class AppComponent { new MenuItem("", "Registries", "", "/search/entity-registries", false, ["datasource"], ["/search/entity-registries"], {}), new MenuItem("", "Browse all", "", "/search/find/dataproviders", false, ["datasource"], ["/search/find/dataproviders"], {})] ), - new MenuItem("contact", "Contact us", "", "/contact-us", false, [], ["/contact-us"], {}), ]; if (Session.isPortalAdministrator(this.user)) { this.userMenuItems.push(new MenuItem("", "Manage all links", "", "/claims", false, [], ["/claims"], {})); @@ -150,6 +174,66 @@ export class AppComponent { if (this.user) { this.userMenuItems.push(new MenuItem("", "User information", "", "/user-info", false, [], [], {})); } + } + + public send(event) { + if (event.valid === true) { + this.sendMail(this.properties.admins); + } + } + + private sendMail(admins: string[]) { + this.sending = true; + this.subscriptions.push(this.emailService.contact(this.properties, + Composer.composeEmailForExplore(this.contactForm.value, admins), + this.contactForm.value.recaptcha).subscribe( + res => { + if (res) { + this.sending = false; + this.reset(); + this.modalOpen(); + } else { + this.handleError('Email sent failed! Please try again.'); + } + }, + error => { + this.handleError('Email sent failed! Please try again.', error); + } + )); + } + + public reset() { + if (this.quickContact) { + this.quickContact.close(); + } + this.contactForm = this.fb.group({ + name: this.fb.control('', Validators.required), + surname: this.fb.control('', Validators.required), + email: this.fb.control('', [Validators.required, Validators.email]), + affiliation: this.fb.control(''), + message: this.fb.control('', Validators.required), + recaptcha: this.fb.control('', Validators.required), + }); + } + + public modalOpen() { + this.modal.okButton = true; + this.modal.alertTitle = 'Your request has been successfully submitted'; + this.modal.message = 'Our team will respond to your submission soon.'; + this.modal.cancelButton = false; + this.modal.okButtonLeft = false; + this.modal.okButtonText = 'OK'; + this.modal.open(); + } + + handleError(message: string, error = null) { + if (error) { + console.error(error); + } + this.sending = false; + this.quickContact.close(); + NotificationHandler.rise(message, 'danger'); + this.contactForm.get('recaptcha').setValue(''); } } diff --git a/explore/src/app/app.module.ts b/explore/src/app/app.module.ts index 30fd904d..75a1a717 100755 --- a/explore/src/app/app.module.ts +++ b/explore/src/app/app.module.ts @@ -17,6 +17,8 @@ import {Schema2jsonldModule} from "./openaireLibrary/sharedComponents/schema2jso import {CacheInterceptorService} from "./openaireLibrary/cache-interceptor.service"; import {DEFAULT_TIMEOUT, TimeoutInterceptor} from "./openaireLibrary/timeout-interceptor.service"; import {ErrorInterceptorService} from "./openaireLibrary/error-interceptor.service"; +import {QuickContactModule} from './openaireLibrary/sharedComponents/quick-contact/quick-contact.module'; +import {AlertModalModule} from './openaireLibrary/utils/modal/alertModal.module'; @NgModule({ imports: [ @@ -29,7 +31,10 @@ import {ErrorInterceptorService} from "./openaireLibrary/error-interceptor.servi BrowserModule.withServerTransition({ appId: 'explore' }), AppRoutingModule, BrowserTransferStateModule, - BrowserAnimationsModule, PageURLResolverModule, Schema2jsonldModule + BrowserAnimationsModule, PageURLResolverModule, + Schema2jsonldModule, + QuickContactModule, + AlertModalModule ], declarations: [AppComponent, OpenaireErrorPageComponent], exports: [AppComponent], diff --git a/explore/src/app/fos/fos.component.html b/explore/src/app/fos/fos.component.html index accf321d..92648243 100644 --- a/explore/src/app/fos/fos.component.html +++ b/explore/src/app/fos/fos.component.html @@ -46,7 +46,7 @@
-
+
-
+
diff --git a/explore/src/app/home/home.component.html b/explore/src/app/home/home.component.html index 45fb8e44..5395c755 100644 --- a/explore/src/app/home/home.component.html +++ b/explore/src/app/home/home.component.html @@ -324,7 +324,7 @@
-
+

Need more information? diff --git a/explore/src/app/home/home.component.ts b/explore/src/app/home/home.component.ts index d7093b5a..e7ea6bd8 100644 --- a/explore/src/app/home/home.component.ts +++ b/explore/src/app/home/home.component.ts @@ -19,7 +19,6 @@ import {SearchProjectsService} from '../openaireLibrary/services/searchProjects. import {SearchOrganizationsService} from '../openaireLibrary/services/searchOrganizations.service'; import {RefineFieldResultsService} from '../openaireLibrary/services/refineFieldResults.service'; import {OpenaireEntities, SearchFields} from '../openaireLibrary/utils/properties/searchFields'; - import {RouterHelper} from '../openaireLibrary/utils/routerHelper.class'; import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties'; import {ErrorCodes} from '../openaireLibrary/utils/properties/errorCodes'; @@ -32,6 +31,7 @@ import {properties} from "../../environments/environment"; import {Numbers, NumbersComponent} from "../openaireLibrary/sharedComponents/numbers/numbers.component"; import {StringUtils} from "../openaireLibrary/utils/string-utils.class"; import {NumberUtils} from '../openaireLibrary/utils/number-utils.class'; +import {QuickContactService} from '../openaireLibrary/sharedComponents/quick-contact/quick-contact.service'; @Component({ selector: 'home', @@ -138,7 +138,8 @@ export class HomeComponent implements OnInit, OnDestroy, AfterViewInit { properties: EnvProperties = properties; public openaireEntities = OpenaireEntities; public readMore: boolean = false; - + public showQuickContact: boolean; + @ViewChild('contact') contact: ElementRef; subscriptions: any[] = []; @ViewChildren('scrolling_element') elements: QueryList; @@ -195,7 +196,8 @@ export class HomeComponent implements OnInit, OnDestroy, AfterViewInit { private location: Location, private _piwikService: PiwikService, private config: ConfigurationService, private _meta: Meta, private _title: Title, private seoService: SEOService, private helper: HelperService, - private cdr: ChangeDetectorRef + private cdr: ChangeDetectorRef, + private quickContactService: QuickContactService ) { let description = "OpenAIRE Explore: Over 100M of research deduplicated, 170K research software, 11M research data. One of the largest open scholarly records collection worldwide."; let title = "OpenAIRE | Find and Share research"; @@ -304,11 +306,28 @@ export class HomeComponent implements OnInit, OnDestroy, AfterViewInit { ngAfterViewInit() { if (typeof window !== "undefined") { - this.createObserver(); + this.createObservers(); } } - createObserver() { + createObservers() { + let options = { + root: null, + rootMargin: '200px', + threshold: 1.0 + }; + let intersectionObserver = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (entry.isIntersecting && this.showQuickContact) { + this.showQuickContact = false; + this.quickContactService.setDisplay(this.showQuickContact); + } else if (!entry.isIntersecting && !this.showQuickContact) { + this.showQuickContact = true; + this.quickContactService.setDisplay(this.showQuickContact); + } + }); + }, options); + intersectionObserver.observe(this.contact.nativeElement); let mutationObserver = new MutationObserver(entries => { entries.forEach(entry => { if (entry.attributeName === 'style') { @@ -327,6 +346,7 @@ export class HomeComponent implements OnInit, OnDestroy, AfterViewInit { this.elements.forEach(element => { mutationObserver.observe(element.nativeElement, {attributes: true}); }); + this.subscriptions.push(intersectionObserver); this.subscriptions.push(mutationObserver); } diff --git a/explore/src/app/openaireLibrary b/explore/src/app/openaireLibrary index 09706515..427e9105 160000 --- a/explore/src/app/openaireLibrary +++ b/explore/src/app/openaireLibrary @@ -1 +1 @@ -Subproject commit 09706515ba1feb0d44c02485bee9782f63a5978f +Subproject commit 427e9105140fabb99f59693c94bc3b70db159901 diff --git a/explore/src/assets/explore-custom.less b/explore/src/assets/explore-custom.less index 60707c55..5b160e16 100644 --- a/explore/src/assets/explore-custom.less +++ b/explore/src/assets/explore-custom.less @@ -3,6 +3,13 @@ /* Button */ @button-primary-background: @explore-color; @inverse-button-primary-background: @explore-color; +@button-secondary-border: @explore-color; +@button-secondary-color: @explore-color; +@button-secondary-hover-background: @global-secondary-background; +@button-secondary-hover-background-gradient: none; +@button-secondary-active-background: @global-secondary-background; +@button-secondary-active-background-gradient: none; + /* Background */ @background-primary-background: @explore-color;