[Library | Trunk]: Fix server errors. Input add validators for chips. Subscriber-invite: Change To field to chips, add short view
git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-library/trunk/ng-openaire-library/src/app@60968 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
parent
1bd9eb8ec2
commit
336f85aa97
|
@ -11,7 +11,7 @@ import {
|
||||||
SimpleChanges,
|
SimpleChanges,
|
||||||
ViewChild
|
ViewChild
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import {AbstractControl, FormArray, FormControl} from "@angular/forms";
|
import {AbstractControl, FormArray, FormControl, ValidatorFn} from "@angular/forms";
|
||||||
import {HelperFunctions} from "../../utils/HelperFunctions.class";
|
import {HelperFunctions} from "../../utils/HelperFunctions.class";
|
||||||
import {Observable, of, Subscription} from "rxjs";
|
import {Observable, of, Subscription} from "rxjs";
|
||||||
import {MatSelect} from "@angular/material/select";
|
import {MatSelect} from "@angular/material/select";
|
||||||
|
@ -100,7 +100,7 @@ export interface Option {
|
||||||
</span>
|
</span>
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
<div [class.uk-hidden]="formControl.value" class="uk-width-expand uk-position-relative chip-input">
|
<div [class.uk-hidden]="formControl.value" class="uk-width-expand uk-position-relative chip-input">
|
||||||
<input #searchInput class="uk-width-1-1" [formControl]="searchControl" [matAutocomplete]="auto"
|
<input #searchInput [formControl]="searchControl" [matAutocomplete]="auto"
|
||||||
[matChipInputFor]="chipList" [matAutocompleteConnectedTo]="origin">
|
[matChipInputFor]="chipList" [matAutocompleteConnectedTo]="origin">
|
||||||
<div *ngIf="placeholder && !searchInput.value" class="placeholder uk-width-1-1"
|
<div *ngIf="placeholder && !searchInput.value" class="placeholder uk-width-1-1"
|
||||||
(click)="searchInput.focus()">{{placeholder}}</div>
|
(click)="searchInput.focus()">{{placeholder}}</div>
|
||||||
|
@ -119,7 +119,7 @@ export interface Option {
|
||||||
<div [ngClass]="inputClass"
|
<div [ngClass]="inputClass"
|
||||||
[attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':null"
|
[attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':null"
|
||||||
[class.clickable]="formControl.enabled"
|
[class.clickable]="formControl.enabled"
|
||||||
[class.uk-form-danger]="formControl.invalid && formControl.touched" (click)="openSelect()">
|
[class.uk-form-danger]="formControl.invalid && searchControl.invalid && searchControl.touched" (click)="openSelect()">
|
||||||
<mat-form-field class="uk-width-1-1">
|
<mat-form-field class="uk-width-1-1">
|
||||||
<mat-chip-list #chipList>
|
<mat-chip-list #chipList>
|
||||||
<mat-chip *ngFor="let chip of formAsArray.controls; let i=index" [selectable]="false"
|
<mat-chip *ngFor="let chip of formAsArray.controls; let i=index" [selectable]="false"
|
||||||
|
@ -130,7 +130,7 @@ export interface Option {
|
||||||
</span>
|
</span>
|
||||||
</mat-chip>
|
</mat-chip>
|
||||||
<div class="uk-width-expand uk-position-relative chip-input">
|
<div class="uk-width-expand uk-position-relative chip-input">
|
||||||
<input #searchInput class="uk-width-1-1" [formControl]="searchControl" [matAutocomplete]="auto"
|
<input #searchInput style="width: calc(100% - 8px) !important;" [formControl]="searchControl" [matAutocomplete]="auto"
|
||||||
[matChipInputFor]="chipList" [matAutocompleteConnectedTo]="origin"
|
[matChipInputFor]="chipList" [matAutocompleteConnectedTo]="origin"
|
||||||
[matChipInputAddOnBlur]="addExtraChips && searchControl.value"
|
[matChipInputAddOnBlur]="addExtraChips && searchControl.value"
|
||||||
(matChipInputTokenEnd)="add($event)">
|
(matChipInputTokenEnd)="add($event)">
|
||||||
|
@ -181,7 +181,7 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
/** Textarea options */
|
/** Textarea options */
|
||||||
@Input('rows') rows: number = 3;
|
@Input('rows') rows: number = 3;
|
||||||
/** Select | chips available options */
|
/** Select | chips available options */
|
||||||
@Input('options') options: Option[];
|
@Input('options') options: Option[] = [];
|
||||||
@Input('hint') hint = null;
|
@Input('hint') hint = null;
|
||||||
@Input('placeholder') placeholder = '';
|
@Input('placeholder') placeholder = '';
|
||||||
@Input() inputClass: string = 'input-box';
|
@Input() inputClass: string = 'input-box';
|
||||||
|
@ -200,6 +200,7 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
@Input() panelWidth: number = 300;
|
@Input() panelWidth: number = 300;
|
||||||
@Input() panelClass: string = null;
|
@Input() panelClass: string = null;
|
||||||
@Input() showOptionsOnEmpty: boolean = true;
|
@Input() showOptionsOnEmpty: boolean = true;
|
||||||
|
@Input() validators: ValidatorFn[];
|
||||||
@Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
|
@Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||||
/** LogoUrl information */
|
/** LogoUrl information */
|
||||||
public secure: boolean = true;
|
public secure: boolean = true;
|
||||||
|
@ -248,11 +249,9 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
this.secure = (!this.initValue || this.initValue.includes('https://'));
|
this.secure = (!this.initValue || this.initValue.includes('https://'));
|
||||||
}
|
}
|
||||||
if (this.type === 'chips' || this.type === 'autocomplete') {
|
if (this.type === 'chips' || this.type === 'autocomplete') {
|
||||||
if(!this.options) {
|
if(this.options) {
|
||||||
console.error('Please provide options to continue');
|
|
||||||
} else {
|
|
||||||
this.filteredOptions = of(this.options);
|
this.filteredOptions = of(this.options);
|
||||||
this.searchControl = new FormControl('');
|
this.searchControl = new FormControl('', this.validators);
|
||||||
this.subscriptions.push(this.searchControl.valueChanges.subscribe(value => {
|
this.subscriptions.push(this.searchControl.valueChanges.subscribe(value => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.searchInput.nativeElement.focus();
|
this.searchInput.nativeElement.focus();
|
||||||
|
@ -333,9 +332,9 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
add(event: MatChipInputEvent) {
|
add(event: MatChipInputEvent) {
|
||||||
if (this.addExtraChips && event.value) {
|
if (this.addExtraChips && event.value && this.searchControl.valid) {
|
||||||
this.stopPropagation();
|
this.stopPropagation();
|
||||||
this.formAsArray.push(new FormControl(event.value));
|
this.formAsArray.push(new FormControl(event.value, this.validators));
|
||||||
this.formAsArray.markAsDirty();
|
this.formAsArray.markAsDirty();
|
||||||
this.searchControl.setValue('');
|
this.searchControl.setValue('');
|
||||||
this.searchInput.nativeElement.value = '';
|
this.searchInput.nativeElement.value = '';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {Component, Input, OnDestroy, OnInit} from "@angular/core";
|
import {Component, Input, OnDestroy, OnInit} from "@angular/core";
|
||||||
import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, Validators} from "@angular/forms";
|
import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators} from "@angular/forms";
|
||||||
import {Subscriber} from "rxjs";
|
import {Subscriber} from "rxjs";
|
||||||
import {StringUtils} from "../../utils/string-utils.class";
|
import {StringUtils} from "../../utils/string-utils.class";
|
||||||
import {Email} from "../../utils/email/email";
|
import {Email} from "../../utils/email/email";
|
||||||
|
@ -16,17 +16,16 @@ declare var UIkit;
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'subscriber-invite',
|
selector: 'subscriber-invite',
|
||||||
template: `
|
template: `
|
||||||
<div class="uk-grid uk-child-width-1-1" uk-grid [formGroup]="inviteForm">
|
<div *ngIf="longView" class="uk-grid uk-child-width-1-1" uk-grid [formGroup]="inviteForm">
|
||||||
<div dashboard-input [formInput]="inviteForm.get('name')" [gridSmall]="true">
|
<div dashboard-input [formInput]="inviteForm.get('name')" [gridSmall]="true">
|
||||||
<div class="uk-text-bold field-label">
|
<div class="uk-text-bold field-label">
|
||||||
From:
|
From:
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div dashboard-input [formInput]="inviteForm.get('recipients')" [gridSmall]="true">
|
<div dashboard-input [formInput]="inviteForm.get('recipients')" type="chips" placeholder="Write email(s)" [addExtraChips]="true" [validators]="validators" [gridSmall]="true">
|
||||||
<div class="uk-text-bold field-label uk-margin-bottom">
|
<div class="uk-text-bold field-label">
|
||||||
To *:
|
To *:
|
||||||
</div>
|
</div>
|
||||||
<span note>Separate multiple emails with a comma</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="uk-grid uk-grid-small" uk-grid>
|
<div class="uk-grid uk-grid-small" uk-grid>
|
||||||
<div class="uk-text-bold field-label">
|
<div class="uk-text-bold field-label">
|
||||||
|
@ -34,7 +33,7 @@ declare var UIkit;
|
||||||
</div>
|
</div>
|
||||||
<div class="uk-width-expand">
|
<div class="uk-width-expand">
|
||||||
<ckeditor *ngIf="isManager" class="form-control" formControlName="message" id="message"
|
<ckeditor *ngIf="isManager" class="form-control" formControlName="message" id="message"
|
||||||
debounce="400"
|
debounce="400" (ready)="loading = false"
|
||||||
[config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]', removeButtons: 'Save,NewPage,DocProps,Preview,Print',
|
[config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]', removeButtons: 'Save,NewPage,DocProps,Preview,Print',
|
||||||
extraPlugins: 'divarea'}"></ckeditor>
|
extraPlugins: 'divarea'}"></ckeditor>
|
||||||
<div *ngIf="!isManager" [innerHTML]="body.paragraphs"></div>
|
<div *ngIf="!isManager" [innerHTML]="body.paragraphs"></div>
|
||||||
|
@ -52,17 +51,23 @@ declare var UIkit;
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div *ngIf="!longView">
|
||||||
|
<div dashboard-input [formInput]="inviteForm.get('recipients')" type="chips" placeholder="Write email(s)" [addExtraChips]="true" [validators]="validators" [gridSmall]="true"></div>
|
||||||
|
</div>
|
||||||
`,
|
`,
|
||||||
styleUrls: ['subscriber-invite.component.css']
|
styleUrls: ['subscriber-invite.component.css']
|
||||||
})
|
})
|
||||||
export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||||
@Input()
|
@Input()
|
||||||
public user: User;
|
public user: User;
|
||||||
public community: CommunityInfo
|
@Input()
|
||||||
|
public longView: boolean = true;
|
||||||
|
public community: CommunityInfo;
|
||||||
public inviteForm: FormGroup;
|
public inviteForm: FormGroup;
|
||||||
public email: Email;
|
public email: Email;
|
||||||
public body: Body;
|
public body: Body;
|
||||||
public loading: boolean = false;
|
public validators: ValidatorFn[] = [Validators.email, Validators.required];
|
||||||
|
public loading: boolean = true;
|
||||||
private subscriptions: any[] = [];
|
private subscriptions: any[] = [];
|
||||||
|
|
||||||
constructor(private fb: FormBuilder,
|
constructor(private fb: FormBuilder,
|
||||||
|
@ -71,6 +76,7 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.loading = this.longView;
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +96,7 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||||
this.unsubscribe();
|
this.unsubscribe();
|
||||||
this.inviteForm = this.fb.group({
|
this.inviteForm = this.fb.group({
|
||||||
name: this.fb.control('', Validators.required),
|
name: this.fb.control('', Validators.required),
|
||||||
recipients: this.fb.control('', [Validators.required, this.emailsValidator]),
|
recipients: this.fb.array([], Validators.required),
|
||||||
message: this.fb.control('', Validators.required)
|
message: this.fb.control('', Validators.required)
|
||||||
});
|
});
|
||||||
this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
|
this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
|
||||||
|
@ -102,20 +108,16 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||||
this.email = Composer.initializeInvitationsEmail(community.title);
|
this.email = Composer.initializeInvitationsEmail(community.title);
|
||||||
this.inviteForm.get('message').setValue(this.body.paragraphs);
|
this.inviteForm.get('message').setValue(this.body.paragraphs);
|
||||||
}));
|
}));
|
||||||
|
if(!this.isManager) {
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
emailsValidator(control: AbstractControl): ValidationErrors | null {
|
|
||||||
if (control.value === '' || !control.value || StringUtils.validateEmails(control.value)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return { emails: true };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
invite() {
|
invite() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.parseRecipients();
|
|
||||||
this.body.paragraphs = this.inviteForm.value.message;
|
this.body.paragraphs = this.inviteForm.value.message;
|
||||||
this.email.body = Composer.formatEmailBodyForInvitation(this.body);
|
this.email.body = Composer.formatEmailBodyForInvitation(this.body);
|
||||||
|
this.email.recipients = this.inviteForm.get('recipients').value;
|
||||||
this.subscriptions.push(this.emailService.sendEmail(properties, this.email).subscribe(res => {
|
this.subscriptions.push(this.emailService.sendEmail(properties, this.email).subscribe(res => {
|
||||||
if(res['success']) {
|
if(res['success']) {
|
||||||
UIkit.notification('Invitation to subscribe has been <b>sent</b>', {
|
UIkit.notification('Invitation to subscribe has been <b>sent</b>', {
|
||||||
|
@ -130,6 +132,7 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||||
pos: 'bottom-right'
|
pos: 'bottom-right'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.reset();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},error => {
|
},error => {
|
||||||
UIkit.notification('An error has occurred. Please try again later', {
|
UIkit.notification('An error has occurred. Please try again later', {
|
||||||
|
@ -137,29 +140,16 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||||
timeout: 6000,
|
timeout: 6000,
|
||||||
pos: 'bottom-right'
|
pos: 'bottom-right'
|
||||||
});
|
});
|
||||||
|
this.reset();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
public parseRecipients() {
|
|
||||||
// remove spaces
|
|
||||||
let emails = this.inviteForm.get('recipients').value.replace(/\s/g, '');
|
|
||||||
// remove commas
|
|
||||||
emails = emails.split(",");
|
|
||||||
|
|
||||||
// remove empty fields
|
|
||||||
for (let i = 0; i < emails.length; i++) {
|
|
||||||
if (!(emails[i] == "")) {
|
|
||||||
this.email.recipients.push(emails[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isManager() {
|
get isManager() {
|
||||||
return Session.isPortalAdministrator(this.user) || Session.isCurator('community', this.user) || Session.isManager('community', this.community.communityId, this.user);
|
return Session.isPortalAdministrator(this.user) || Session.isCurator('community', this.user) || Session.isManager('community', this.community.communityId, this.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
get valid() {
|
get valid() {
|
||||||
return this.inviteForm && this.inviteForm.valid;
|
return !this.loading && this.inviteForm && this.inviteForm.valid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,18 +118,12 @@ export class ConfigurationService{
|
||||||
|
|
||||||
filtering(page_route: string) {
|
filtering(page_route: string) {
|
||||||
let community: Portal = this.communityInformation.getValue();
|
let community: Portal = this.communityInformation.getValue();
|
||||||
|
|
||||||
let pages: Page[] = <Page[]>community.pages;
|
let pages: Page[] = <Page[]>community.pages;
|
||||||
pages = pages.filter(function (page: Page) {
|
|
||||||
return page.route == page_route;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pages) {
|
if (pages) {
|
||||||
let result = false;
|
let page = pages.find((page: Page) => page.route == page_route);
|
||||||
if (pages['length'] > 0 && pages[0].route == page_route) {
|
return page && page.isEnabled;
|
||||||
result = pages[0].isEnabled;
|
} else {
|
||||||
}
|
return false;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,3 +138,8 @@ export const reset = {
|
||||||
name: 'reset',
|
name: 'reset',
|
||||||
data: '<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><polyline fill="#000" points="1 2 2 2 2 6 6 6 6 7 1 7 1 2"></polyline><path fill="none" stroke="#000" stroke-width="1.1" d="M2.1,6.548 C3.391,3.29 6.746,1 10.5,1 C15.5,1 19.5,5 19.5,10 C19.5,15 15.5,19 10.5,19 C5.5,19 1.5,15 1.5,10"></path></svg>'
|
data: '<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><polyline fill="#000" points="1 2 2 2 2 6 6 6 6 7 1 7 1 2"></polyline><path fill="none" stroke="#000" stroke-width="1.1" d="M2.1,6.548 C3.391,3.29 6.746,1 10.5,1 C15.5,1 19.5,5 19.5,10 C19.5,15 15.5,19 10.5,19 C5.5,19 1.5,15 1.5,10"></path></svg>'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const send = {
|
||||||
|
name: 'send',
|
||||||
|
data: '<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 24 24" width="20" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>'
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ export class SmoothScroll {
|
||||||
private lastRoute;
|
private lastRoute;
|
||||||
|
|
||||||
constructor(private router: Router) {
|
constructor(private router: Router) {
|
||||||
|
if(typeof window !== "undefined") {
|
||||||
this.sub = router.events.subscribe(event => {
|
this.sub = router.events.subscribe(event => {
|
||||||
if (event instanceof NavigationEnd) {
|
if (event instanceof NavigationEnd) {
|
||||||
if (this.interval) {
|
if (this.interval) {
|
||||||
|
@ -52,6 +53,7 @@ export class SmoothScroll {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getUrl(url: string) {
|
private getUrl(url: string) {
|
||||||
return url.split('?')[0].split('#')[0];
|
return url.split('?')[0].split('#')[0];
|
||||||
|
|
Loading…
Reference in New Issue