Adds a Support section to side menu that opens a dialog where the user will provide a "Subject" and a "Description" to be sent (Issue #128)
This commit is contained in:
parent
5cd5b96fb3
commit
d635032224
|
@ -36,6 +36,7 @@ import { QuickWizardService } from './services/quick-wizard/quick-wizard.service
|
|||
import { OrganisationService } from './services/organisation/organisation.service';
|
||||
import { EmailConfirmationService } from './services/email-confirmation/email-confirmation.service';
|
||||
import { FunderService } from './services/funder/funder.service';
|
||||
import { ContactSupportService } from './services/contact-support/contact-support.service';
|
||||
//
|
||||
//
|
||||
// This is shared module that provides all the services. Its imported only once on the AppModule.
|
||||
|
@ -91,7 +92,8 @@ export class CoreServiceModule {
|
|||
DatasetExternalAutocompleteService,
|
||||
QuickWizardService,
|
||||
OrganisationService,
|
||||
EmailConfirmationService
|
||||
EmailConfirmationService,
|
||||
ContactSupportService
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import { ValidationErrorModel } from "../../../common/forms/validation/error-model/validation-error-model";
|
||||
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
|
||||
|
||||
export interface ContactEmail {
|
||||
subject: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export class ContactEmailFormModel {
|
||||
subject: string;
|
||||
description: string;
|
||||
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
|
||||
|
||||
fromModel(item: ContactEmail): ContactEmailFormModel {
|
||||
this.subject = item.subject;
|
||||
this.description = item.description;
|
||||
return this;
|
||||
}
|
||||
|
||||
buildForm(): FormGroup {
|
||||
const formGroup = new FormBuilder().group({
|
||||
subject: [ this.subject, [Validators.required] ],
|
||||
description: [ this.description, [Validators.required] ]
|
||||
});
|
||||
return formGroup;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { BaseHttpService } from "../../../core/services/http/base-http.service";
|
||||
import { HttpHeaders } from "@angular/common/http";
|
||||
import { environment } from "../../../../environments/environment";
|
||||
import { Injectable } from "@angular/core";
|
||||
import { ContactEmail } from "../../model/contact/contact-email-form-model";
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
@Injectable()
|
||||
export class ContactSupportService {
|
||||
|
||||
private actionUrl: string;
|
||||
|
||||
constructor(private http: BaseHttpService) {
|
||||
this.actionUrl = environment.Server + 'contactEmail/';
|
||||
}
|
||||
|
||||
postEmail(contentEmail: ContactEmail): Observable<ContactEmail> {
|
||||
return this.http.post<ContactEmail>(this.actionUrl, contentEmail);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<div class="row d-flex flex-row">
|
||||
<div mat-dialog-title class="col-auto">
|
||||
{{'CONTACT.SUPPORT.SUBTITLE' | translate}}
|
||||
</div>
|
||||
<div class="col-auto ml-auto close-btn" (click)="close()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div mat-dialog-content class="row">
|
||||
<form class="form" [formGroup]="data">
|
||||
<mat-form-field class="full-width">
|
||||
<!-- <input matInput placeholder="{{'CONTACT.SUPPORT.SUBJECT' | translate}}" [(ngModel)]="data.subject" name="contactSupportSubject" required> -->
|
||||
<input matInput placeholder="{{'CONTACT.SUPPORT.SUBJECT' | translate}}" type="text" name="subject" formControlName="subject" required>
|
||||
<mat-error *ngIf="data.get('subject').hasError('backendError')">
|
||||
{{data.get('subject').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="data.get('subject').hasError('required')">
|
||||
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field class="full-width">
|
||||
<textarea matInput placeholder="{{'CONTACT.SUPPORT.DESCRIPTION' | translate}}" type="text" name="description" formControlName="description" required></textarea>
|
||||
<mat-error *ngIf="data.get('description').hasError('backendError')">
|
||||
{{data.get('description').getError('backendError').message}}</mat-error>
|
||||
<mat-error *ngIf="data.get('description').hasError('required')">
|
||||
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
</div>
|
||||
<div mat-dialog-actions class="row">
|
||||
<div class="ml-auto col-auto"><button mat-button mat-dialog-close mat-raised-button color="primary" (click)="cancel()">{{'CONTACT.SUPPORT.CANCEL' | translate}}</button></div>
|
||||
<div class="col-auto"><button mat-raised-button color="primary" type="button" [disabled]="!data.valid" (click)="send()"><i class="fa fa-paper-plane pr-2"></i>{{'CONTACT.SUPPORT.SEND' | translate}}</button></div>
|
||||
</div>
|
|
@ -0,0 +1,13 @@
|
|||
.form {
|
||||
min-width: 150px;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
cursor: pointer;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
import { Component, Inject } from '@angular/core';
|
||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact-dialog',
|
||||
templateUrl: './contact-dialog.component.html',
|
||||
styleUrls: ['./contact-dialog.component.scss']
|
||||
})
|
||||
export class ContactDialogComponent {
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<ContactDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: FormGroup
|
||||
) { }
|
||||
|
||||
cancel() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
send() {
|
||||
this.dialogRef.close(this.data);
|
||||
}
|
||||
|
||||
close() {
|
||||
this.dialogRef.close(false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonUiModule } from '../../common/ui/common-ui.module';
|
||||
import { ContactDialogComponent } from './contact-dialog.component';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonUiModule, FormsModule, ReactiveFormsModule],
|
||||
declarations: [ContactDialogComponent],
|
||||
exports: [ContactDialogComponent],
|
||||
entryComponents: [ContactDialogComponent]
|
||||
})
|
||||
export class ContactDialogModule {
|
||||
constructor() { }
|
||||
}
|
|
@ -34,7 +34,7 @@ import { DatasetProfileEditorDmpsAutoCompleteFieldComponent } from './editor/com
|
|||
CommonFormsModule,
|
||||
FormattingModule,
|
||||
DatasetProfileRoutingModule,
|
||||
ConfirmationDialogModule,
|
||||
ConfirmationDialogModule
|
||||
],
|
||||
declarations: [
|
||||
DatasetProfileListingComponent,
|
||||
|
|
|
@ -47,8 +47,6 @@ export class DatasetProfileCriteriaComponent extends BaseCriteriaComponent imple
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
openDialog(): void {
|
||||
const dialogRef = this.dialog.open(DialodConfirmationUploadDatasetProfiles, {
|
||||
data: {
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
padding-right: 10px;
|
||||
border-radius: 0px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebar-footer :hover {
|
||||
color: #4687e6;
|
||||
}
|
||||
|
||||
.sidebar-footer .vl {
|
||||
|
@ -19,10 +24,3 @@
|
|||
color: white;
|
||||
}
|
||||
|
||||
.option .style-icon {
|
||||
font-size: 15px;
|
||||
margin: 0px;
|
||||
width: 20px;
|
||||
padding-top: 2px;
|
||||
color: white;
|
||||
}
|
||||
|
|
|
@ -5,4 +5,5 @@
|
|||
</a>
|
||||
<a class="option vl" href="#"><i class="fa fa-book style-icon"></i>Guide</a>
|
||||
<a class="option" href="#"><i class="fa fa-life-ring style-icon"></i>Help</a> -->
|
||||
<p class="option" (click)="openContactDialog()"><i class="fa fa-question-circle pr-2"></i>{{'CONTACT.SUPPORT.TITLE' | translate}}</p>
|
||||
</div>
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SidebarFooterComponent } from './sidebar-footer.component';
|
||||
|
||||
describe('SidebarFooterComponent', () => {
|
||||
let component: SidebarFooterComponent;
|
||||
let fixture: ComponentFixture<SidebarFooterComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SidebarFooterComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SidebarFooterComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,15 +1,94 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { BaseComponent } from '../../../core/common/base/base.component';
|
||||
import { ContactDialogComponent } from '../../../library/contact-dialog/contact-dialog.component';
|
||||
import { ContactSupportService } from '../../../core/services/contact-support/contact-support.service';
|
||||
import { UiNotificationService, SnackBarNotificationLevel } from '../../../core/services/notification/ui-notification-service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ContactEmailFormModel } from '../../../core/model/contact/contact-email-form-model';
|
||||
import { FormGroup, AbstractControl, FormControl, FormArray } from '@angular/forms';
|
||||
import { ValidationErrorModel } from '../../../common/forms/validation/error-model/validation-error-model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-sidebar-footer',
|
||||
templateUrl: './sidebar-footer.component.html',
|
||||
styleUrls: ['./sidebar-footer.component.css']
|
||||
})
|
||||
export class SidebarFooterComponent implements OnInit {
|
||||
export class SidebarFooterComponent extends BaseComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
private contactEmailFormModel: ContactEmailFormModel;
|
||||
private formGroup: FormGroup;
|
||||
|
||||
constructor(
|
||||
private dialog: MatDialog,
|
||||
private language: TranslateService,
|
||||
private contactSupportService: ContactSupportService,
|
||||
private uiNotificationService: UiNotificationService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.contactEmailFormModel = new ContactEmailFormModel();
|
||||
this.formGroup = this.contactEmailFormModel.buildForm();
|
||||
}
|
||||
|
||||
openContactDialog() {
|
||||
if (this.dialog.openDialogs.length > 0) {
|
||||
this.dialog.closeAll();
|
||||
}
|
||||
else {
|
||||
const dialogRef = this.dialog.open(ContactDialogComponent, {
|
||||
width: '400px',
|
||||
hasBackdrop: true,
|
||||
autoFocus: false,
|
||||
closeOnNavigation: true,
|
||||
disableClose: false,
|
||||
data: this.formGroup
|
||||
});
|
||||
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(data => {
|
||||
if (data) {
|
||||
this.contactSupportService.postEmail(data.value)
|
||||
.pipe(takeUntil(this._destroyed))
|
||||
.subscribe(
|
||||
complete => this.onCallbackSuccess(),
|
||||
error => this.onCallbackError(error)
|
||||
);
|
||||
this.formGroup.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onCallbackSuccess(): void {
|
||||
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-EMAIL-SEND'), SnackBarNotificationLevel.Success);
|
||||
}
|
||||
|
||||
onCallbackError(errorResponse: any) {
|
||||
this.setErrorModel(errorResponse.error);
|
||||
this.validateAllFormFields(this.formGroup);
|
||||
}
|
||||
|
||||
public setErrorModel(validationErrorModel: ValidationErrorModel) {
|
||||
Object.keys(validationErrorModel).forEach(item => {
|
||||
(<any>this.contactEmailFormModel.validationErrorModel)[item] = (<any>validationErrorModel)[item];
|
||||
});
|
||||
}
|
||||
|
||||
public validateAllFormFields(formControl: AbstractControl) {
|
||||
if (formControl instanceof FormControl) {
|
||||
formControl.updateValueAndValidity({ emitEvent: false });
|
||||
} else if (formControl instanceof FormGroup) {
|
||||
Object.keys(formControl.controls).forEach(item => {
|
||||
const control = formControl.get(item);
|
||||
this.validateAllFormFields(control);
|
||||
});
|
||||
} else if (formControl instanceof FormArray) {
|
||||
formControl.controls.forEach(item => {
|
||||
this.validateAllFormFields(item);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
width: 230px;
|
||||
border-top: 1px solid #fff;
|
||||
border-bottom: 2px solid #d4d4d4;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
|
||||
.sidebar-footer {
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SidebarComponent } from './sidebar.component';
|
||||
|
||||
describe('SidebarComponent', () => {
|
||||
let component: SidebarComponent;
|
||||
let fixture: ComponentFixture<SidebarComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SidebarComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SidebarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -4,11 +4,13 @@ import { CommonFormsModule } from '../../common/forms/common-forms.module';
|
|||
import { CommonUiModule } from '../../common/ui/common-ui.module';
|
||||
import { SidebarComponent } from './sidebar.component';
|
||||
import { SidebarFooterComponent } from './sidebar-footer/sidebar-footer.component';
|
||||
import { ContactDialogModule } from '../../library/contact-dialog/contact-dialog.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonUiModule,
|
||||
CommonFormsModule,
|
||||
ContactDialogModule,
|
||||
RouterModule
|
||||
],
|
||||
declarations: [
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"SUCCESSFUL-UPDATE": "Updated Successfully",
|
||||
"SUCCESSFUL-LOGIN": "Successful Login",
|
||||
"SUCCESSFUL-LOGOUT": "Successful Logout",
|
||||
"SUCCESSFUL-EMAIL-SEND": "Email sent successfully",
|
||||
"UNSUCCESSFUL-LOGOUT": "Unsuccessful Logout",
|
||||
"UNSUCCESSFUL-LOGIN": "Unsuccessful Login",
|
||||
"SUCCESSFUL-DATASET-PROFILE-DELETE": "Successful Delete",
|
||||
|
@ -863,6 +864,19 @@
|
|||
"WELCOME": "Welcome to OpenDMP",
|
||||
"WELCOME-MESSAGE": "Create, Link, Share Data Management Plans"
|
||||
},
|
||||
"CONTACT": {
|
||||
"SUPPORT": {
|
||||
"TITLE": "Contact Support",
|
||||
"SUBTITLE": "How can we help you?",
|
||||
"SUBJECT": "Subject",
|
||||
"DESCRIPTION": "Description",
|
||||
"CANCEL": "Cancel",
|
||||
"SEND": "Send"
|
||||
},
|
||||
"GUIDE": "Guide",
|
||||
"HELP": "Help",
|
||||
"GLOSSARY": "Glossary"
|
||||
},
|
||||
"DASHBOARD": {
|
||||
"MY-GRANTS": "My Grants",
|
||||
"GRANTS": "Grants",
|
||||
|
|
Loading…
Reference in New Issue