Add notification handler. Add contact-us to quick contact and make some changes in contact-us

This commit is contained in:
Konstantinos Triantafyllou 2022-02-24 18:42:05 +02:00
parent 31e5658827
commit ada419f8e8
11 changed files with 167 additions and 101 deletions

View File

@ -1,62 +1,69 @@
<h1 *ngIf="formTitle" class="uk-margin-auto">{{formTitle}}</h1>
<ng-content select="[page-title]"></ng-content>
<ng-content select="[page-description]"></ng-content>
<div *ngIf="errorMessage" class="uk-width-1-1 uk-alert uk-alert-danger uk-text-center"
role="alert">{{errorMessage}}</div>
<div class="uk-margin-top" uk-grid [formGroup]="contactForm">
<div *ngIf="contactForm.get('name')" class="uk-width-1-2@s uk-margin-medium-top">
<input class="uk-input" type="text" placeholder="Name *" formControlName="name"
<div class="uk-child-width-1-1 uk-grid" [class.uk-grid-medium]="smallForm"
[class.uk-grid-margin-large]="!smallForm" [class.uk-child-width-1-2@s]="!smallForm"
[formGroup]="contactForm" uk-grid>
<div *ngIf="contactForm.get('name')">
<input class="uk-input" type="text" placeholder="Name *" formControlName="name"
[class.uk-form-danger]="contactForm.get('name').invalid && contactForm.get('name').touched">
</div>
<div *ngIf="contactForm.get('surname')" class="uk-width-1-2@s uk-margin-medium-top">
<input class="uk-input" type="text" placeholder="Surname *" formControlName="surname"
[class.uk-form-danger]="contactForm.get('surname').invalid && contactForm.get('surname').touched">
</div>
<div *ngIf="contactForm.get('email')" class="uk-width-1-2@s uk-margin-medium-top">
<input class="uk-input" type="text" placeholder="Email *" formControlName="email"
[class.uk-form-danger]="contactForm.get('email').invalid && contactForm.get('email').touched">
</div>
<div *ngIf="contactForm.get('job')" class="uk-width-1-2@s uk-margin-medium-top">
<input class="uk-input" type="text" placeholder="Job Title *" formControlName="job"
[class.uk-form-danger]="contactForm.get('job').invalid && contactForm.get('job').touched">
</div>
<div *ngIf="contactForm.get('affiliation')" class="uk-width-1-2@s uk-margin-medium-top">
<input class="uk-input" type="text" placeholder="Affiliation *" formControlName="affiliation"
[class.uk-form-danger]="contactForm.get('affiliation').invalid && contactForm.get('affiliation').touched">
</div>
<div *ngIf="contactForm.get('community')" class="uk-width-1-2@s uk-margin-medium-top">
<input class="uk-input uk-width-1" type="text" placeholder="Research Community or Infrastructure *" formControlName="community"
[class.uk-form-danger]="contactForm.get('community').invalid && contactForm.get('community').touched">
</div>
<div *ngIf="contactForm.get('organization')" class="uk-width-1-2@s uk-margin-medium-top">
<input class="uk-input uk-width-1-1" type="text" placeholder="Organization *" formControlName="organization"
[class.uk-form-danger]="contactForm.get('organization').invalid && contactForm.get('organization').touched">
</div>
<div *ngIf="contactForm.get('organizationType')" class="uk-width-1-2@s uk-margin-medium-top">
<select class="uk-select uk-width-1-1" formControlName="organizationType">
<option [value]="''" hidden selected>Organization Type *</option>
<option *ngFor="let option of organizationTypes" [value]="option">{{option}}</option>
</select>
</div>
<div *ngIf="contactForm.get('subject')" class="uk-width-1-1@s uk-margin-medium-top">
<input class="uk-input uk-width-1-1" type="text" placeholder="Subject *" formControlName="subject"
[class.uk-form-danger]="contactForm.get('subject').invalid && contactForm.get('subject').touched">
</div>
<div *ngIf="contactForm.get('message')" class="uk-width-1-1 uk-margin-medium-top">
</div>
<div *ngIf="contactForm.get('surname')">
<input class="uk-input" type="text" placeholder="Surname *" formControlName="surname"
[class.uk-form-danger]="contactForm.get('surname').invalid && contactForm.get('surname').touched">
</div>
<div *ngIf="contactForm.get('email')">
<input class="uk-input" type="text" placeholder="Email *" formControlName="email"
[class.uk-form-danger]="contactForm.get('email').invalid && contactForm.get('email').touched">
</div>
<div *ngIf="contactForm.get('job')">
<input class="uk-input" type="text" placeholder="Job Title *" formControlName="job"
[class.uk-form-danger]="contactForm.get('job').invalid && contactForm.get('job').touched">
</div>
<div *ngIf="contactForm.get('affiliation')">
<input class="uk-input" type="text" placeholder="Affiliation *" formControlName="affiliation"
[class.uk-form-danger]="contactForm.get('affiliation').invalid && contactForm.get('affiliation').touched">
</div>
<div *ngIf="contactForm.get('community')">
<input class="uk-input uk-width-1" type="text" placeholder="Research Community or Infrastructure *"
formControlName="community"
[class.uk-form-danger]="contactForm.get('community').invalid && contactForm.get('community').touched">
</div>
<div *ngIf="contactForm.get('organization')">
<input class="uk-input uk-width-1-1" type="text" placeholder="Organization *" formControlName="organization"
[class.uk-form-danger]="contactForm.get('organization').invalid && contactForm.get('organization').touched">
</div>
<div *ngIf="contactForm.get('organizationType')">
<select class="uk-select uk-width-1-1" formControlName="organizationType">
<option [value]="''" hidden selected>Organization Type *</option>
<option *ngFor="let option of organizationTypes" [value]="option">{{option}}</option>
</select>
</div>
<div *ngIf="contactForm.get('subject')" class="uk-width-1-1">
<input class="uk-input uk-width-1-1" type="text" placeholder="Subject *" formControlName="subject"
[class.uk-form-danger]="contactForm.get('subject').invalid && contactForm.get('subject').touched">
</div>
<div *ngIf="contactForm.get('message')" class="uk-width-1-1">
<textarea rows="4" class="uk-textarea" placeholder="Comments *" formControlName="message"
[class.uk-form-danger]="contactForm.get('message').invalid && contactForm.get('message').touched">
</textarea>
</div>
<div *ngIf="contactForm.get('description')" class="uk-width-1-1 uk-margin-medium-top">
</div>
<div *ngIf="contactForm.get('description')" class="uk-width-1-1">
<textarea rows="4" class="uk-textarea" placeholder="Description *" formControlName="description"
[class.uk-form-danger]="contactForm.get('description').invalid && contactForm.get('description').touched">
</textarea>
</div>
<div *ngIf="contactForm.get('recaptcha')" class="uk-width-1-2@s uk-margin-top">
<re-captcha (resolved)="handleRecaptcha($event)" [(siteKey)]="properties.reCaptchaSiteKey">
</re-captcha>
</div>
<div class="uk-margin-medium-top uk-width-1-1">
<button class="uk-button uk-text-uppercase" [class.uk-button-primary]="!buttonClass" [ngClass]="buttonClass" (click)="send()">Send</button>
</div>
</div>
<div *ngIf="contactForm.get('recaptcha')" class="uk-width-1-1">
<re-captcha class="uk-flex " [ngClass]="'uk-flex-' + alignButton" (resolved)="handleRecaptcha($event)" [(siteKey)]="properties.reCaptchaSiteKey">
</re-captcha>
</div>
<div class="uk-width-1-1 uk-flex" [ngClass]="'uk-flex-' + alignButton">
<button class="uk-button uk-text-uppercase uk-flex uk-flex-middle"
[class.uk-disabled]="contactForm.invalid || sending"
[class.uk-button-primary]="!buttonClass && contactForm.valid" [ngClass]="(contactForm.valid?buttonClass:'')"
(click)="send()">
{{sendButton}}
<span *ngIf="sending" class="uk-icon uk-margin-small-left"><loading [top_margin]="false" [size]="'small'" [color]="null"></loading></span>
</button>
</div>
</div>

View File

@ -1,8 +1,7 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Component, EventEmitter, Input, Output} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {EnvProperties} from "../utils/properties/env-properties";
import {Observable} from "rxjs";
import {map, startWith} from "rxjs/operators";
import {properties} from "../../../environments/environment";
@Component({
selector: 'contact-us',
@ -10,18 +9,16 @@ import {map, startWith} from "rxjs/operators";
})
export class ContactUsComponent {
@Input()
public contactForm: FormGroup;
@Input() formTitle: string;
@Input() properties: EnvProperties;
@Input() public contactForm: FormGroup;
@Input() public formTitle: string;
@Input() public organizationTypes: string[];
@Input() public buttonClass: string;
@Input() public alignButton: "left" | "right" | "center" = "left";
@Input() public sendButton: string = "Send";
@Input() public smallForm: boolean = false;
@Input() public sending: boolean = false;
@Output() sendEmitter: EventEmitter<any> = new EventEmitter<any>();
@Input() errorMessage;
@Input()
public organizationTypes: string[];
@Input()
public right: boolean = true;
@Input()
public buttonClass: string;
public properties: EnvProperties = properties;
public send() {
this.sendEmitter.emit({

View File

@ -7,11 +7,12 @@ import {ReactiveFormsModule} from "@angular/forms";
import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {RecaptchaModule} from "ng-recaptcha";
import {SafeHtmlPipeModule} from "../utils/pipes/safeHTMLPipe.module";
import {LoadingModule} from "../utils/loading/loading.module";
@NgModule({
imports: [
CommonModule, RouterModule,
ReactiveFormsModule, MatAutocompleteModule, RecaptchaModule, SafeHtmlPipeModule],
ReactiveFormsModule, MatAutocompleteModule, RecaptchaModule, SafeHtmlPipeModule, LoadingModule],
declarations: [
ContactUsComponent
],

View File

@ -8,6 +8,10 @@
border-radius: 4px 4px 0 0;
}
.uk-drop {
width: 380px;
}
.avatars > img {
width: 50px;
height: 50px;

View File

@ -1,10 +1,10 @@
<div class="quick-contact">
<a class="uk-button uk-button-secondary uk-text-uppercase uk-flex uk-flex-middle" (click)="toggleModal()">
<icon *ngIf="!showModal" name="mail" [flex]="true"></icon>
<icon *ngIf="showModal" name="close" [flex]="true"></icon>
<icon *ngIf="!showForm" name="mail" [flex]="true"></icon>
<icon *ngIf="showForm" name="close" [flex]="true"></icon>
<span class="uk-margin-small-left">Contact</span>
</a>
<div class="uk-card uk-card-default uk-drop" uk-drop="mode: click; pos: top-right">
<div #drop id="quick-contact" class="uk-card uk-card-default uk-drop" uk-drop="mode: click; pos: top-right; animation: uk-animation-fade">
<div class="uk-background-secondary uk-padding-small uk-text-center">
<div class="uk-text-small">
Send a message
@ -23,24 +23,9 @@
</div>
</div>
<div class="uk-height-medium uk-card-body uk-overflow-auto">
TODO: Contact form <br>
Name <br>
Email <br>
Organization <br>
Type <br>
Comments <br>
Send button <br>
TODO: Contact form <br>
Name <br>
Email <br>
Organization <br>
Type <br>
Comments <br>
Send button <br>
Organization <br>
Type <br>
Comments <br>
Send button <br>
<loading *ngIf="sending" class="uk-margin-xlarge-top"></loading>
<contact-us *ngIf="contactForm && !sending" [organizationTypes]="organizationTypes" (sendEmitter)="send($event)"
[smallForm]="true" alignButton="center" sendButton="Send Message" [contactForm]="contactForm"></contact-us>
</div>
</div>
</div>

View File

@ -1,14 +1,55 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {Component, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild} from '@angular/core';
import {FormGroup} from "@angular/forms";
import {Subscriber} from "rxjs";
declare var UIkit;
@Component({
selector: 'quick-contact',
templateUrl: 'quick-contact.component.html',
styleUrls: ['quick-contact.component.css']
selector: 'quick-contact',
templateUrl: 'quick-contact.component.html',
styleUrls: ['quick-contact.component.css']
})
export class QuickContactComponent {
public showModal: boolean = false;
public toggleModal() {
this.showModal = !this.showModal;
}
}
export class QuickContactComponent implements OnInit, OnDestroy {
public showForm: boolean = false;
@Input()
public contactForm: FormGroup;
@Input()
public sending = false;
@Input()
public organizationTypes: string[] = [];
@Output() sendEmitter: EventEmitter<any> = new EventEmitter<any>();
private subscriptions: any[] = [];
@ViewChild('drop') drop: ElementRef;
ngOnInit() {
if (document !== undefined) {
this.subscriptions.push(UIkit.util.on(document, 'beforehide', '#quick-contact', (event) => {
if(this.sending) {
event.preventDefault();
}
}));
}
}
ngOnDestroy() {
this.subscriptions.forEach(value => {
if (value instanceof Subscriber) {
value.unsubscribe();
} else if (value instanceof Function) {
value();
}
});
}
public close() {
UIkit.drop(this.drop.nativeElement).hide();
}
public send(event) {
this.sendEmitter.emit(event);
}
public toggleModal() {
this.showForm = !this.showForm;
}
}

View File

@ -4,10 +4,12 @@ import {FormsModule} from '@angular/forms';
import {QuickContactComponent} from './quick-contact.component';
import {IconsModule} from '../../utils/icons/icons.module';
import {ContactUsModule} from "../../contact-us/contact-us.module";
import {LoadingModule} from "../../utils/loading/loading.module";
@NgModule({
imports: [
CommonModule, FormsModule, IconsModule
CommonModule, FormsModule, IconsModule, ContactUsModule, LoadingModule
],
declarations: [
QuickContactComponent

View File

@ -62,7 +62,7 @@ export class Composer {
return email;
}
public static composeEmailForMonitor(contactForm: any, admins: any): Email {
public static composeEmailForMonitor(contactForm: any, admins: string[]): Email {
let email: Email = new Email();
email.subject = "OpenAIRE - Monitor";

View File

@ -7,7 +7,9 @@ import {Observable} from "rxjs";
import {EnvProperties} from "../properties/env-properties";
import {properties} from "../../../../environments/environment";
@Injectable()
@Injectable({
providedIn: 'root'
})
export class EmailService {
constructor(private http:HttpClient) {

View File

@ -0,0 +1,18 @@
declare var UIkit;
export type Status = 'danger' | 'success' | 'warning';
export type Position = 'bottom-right' | 'bottom-left' | 'bottom-center';
export class NotificationHandler {
private static DEFAULT_TIMEOUT: number = 60000;
private static DEFAULT_STATUS: Status = 'success';
private static DEFAULT_POSITION: Position = 'bottom-right';
public static rise(message: string, status: Status = this.DEFAULT_STATUS, position: Position = this.DEFAULT_POSITION) {
UIkit.notification(message, {
status: status,
timeout: this.DEFAULT_TIMEOUT,
pos: position
});
}
}

View File

@ -315,6 +315,15 @@ export class StringUtils {
return Validators.pattern(StringUtils.urlRegex);
}
public static validatorType(options: string[]): ValidatorFn {
return (control: AbstractControl): { [key: string]: boolean } | null => {
if (options.filter(type => type === control.value).length === 0) {
return {'type': false};
}
return null;
}
}
public static validRoute(pages: any[], field: string, initial: string = null): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if(control.value) {