[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,
|
||||
ViewChild
|
||||
} 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 {Observable, of, Subscription} from "rxjs";
|
||||
import {MatSelect} from "@angular/material/select";
|
||||
|
@ -100,7 +100,7 @@ export interface Option {
|
|||
</span>
|
||||
</mat-chip>
|
||||
<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">
|
||||
<div *ngIf="placeholder && !searchInput.value" class="placeholder uk-width-1-1"
|
||||
(click)="searchInput.focus()">{{placeholder}}</div>
|
||||
|
@ -119,7 +119,7 @@ export interface Option {
|
|||
<div [ngClass]="inputClass"
|
||||
[attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':null"
|
||||
[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-chip-list #chipList>
|
||||
<mat-chip *ngFor="let chip of formAsArray.controls; let i=index" [selectable]="false"
|
||||
|
@ -130,7 +130,7 @@ export interface Option {
|
|||
</span>
|
||||
</mat-chip>
|
||||
<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"
|
||||
[matChipInputAddOnBlur]="addExtraChips && searchControl.value"
|
||||
(matChipInputTokenEnd)="add($event)">
|
||||
|
@ -181,7 +181,7 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
|||
/** Textarea options */
|
||||
@Input('rows') rows: number = 3;
|
||||
/** Select | chips available options */
|
||||
@Input('options') options: Option[];
|
||||
@Input('options') options: Option[] = [];
|
||||
@Input('hint') hint = null;
|
||||
@Input('placeholder') placeholder = '';
|
||||
@Input() inputClass: string = 'input-box';
|
||||
|
@ -200,6 +200,7 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
|||
@Input() panelWidth: number = 300;
|
||||
@Input() panelClass: string = null;
|
||||
@Input() showOptionsOnEmpty: boolean = true;
|
||||
@Input() validators: ValidatorFn[];
|
||||
@Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
/** LogoUrl information */
|
||||
public secure: boolean = true;
|
||||
|
@ -248,11 +249,9 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
|||
this.secure = (!this.initValue || this.initValue.includes('https://'));
|
||||
}
|
||||
if (this.type === 'chips' || this.type === 'autocomplete') {
|
||||
if(!this.options) {
|
||||
console.error('Please provide options to continue');
|
||||
} else {
|
||||
if(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 => {
|
||||
setTimeout(() => {
|
||||
this.searchInput.nativeElement.focus();
|
||||
|
@ -333,9 +332,9 @@ export class InputComponent implements OnInit, OnDestroy, OnChanges {
|
|||
}
|
||||
|
||||
add(event: MatChipInputEvent) {
|
||||
if (this.addExtraChips && event.value) {
|
||||
if (this.addExtraChips && event.value && this.searchControl.valid) {
|
||||
this.stopPropagation();
|
||||
this.formAsArray.push(new FormControl(event.value));
|
||||
this.formAsArray.push(new FormControl(event.value, this.validators));
|
||||
this.formAsArray.markAsDirty();
|
||||
this.searchControl.setValue('');
|
||||
this.searchInput.nativeElement.value = '';
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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 {StringUtils} from "../../utils/string-utils.class";
|
||||
import {Email} from "../../utils/email/email";
|
||||
|
@ -16,17 +16,16 @@ declare var UIkit;
|
|||
@Component({
|
||||
selector: 'subscriber-invite',
|
||||
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 class="uk-text-bold field-label">
|
||||
From:
|
||||
</div>
|
||||
</div>
|
||||
<div dashboard-input [formInput]="inviteForm.get('recipients')" [gridSmall]="true">
|
||||
<div class="uk-text-bold field-label uk-margin-bottom">
|
||||
<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">
|
||||
To *:
|
||||
</div>
|
||||
<span note>Separate multiple emails with a comma</span>
|
||||
</div>
|
||||
<div class="uk-grid uk-grid-small" uk-grid>
|
||||
<div class="uk-text-bold field-label">
|
||||
|
@ -34,7 +33,7 @@ declare var UIkit;
|
|||
</div>
|
||||
<div class="uk-width-expand">
|
||||
<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',
|
||||
extraPlugins: 'divarea'}"></ckeditor>
|
||||
<div *ngIf="!isManager" [innerHTML]="body.paragraphs"></div>
|
||||
|
@ -52,17 +51,23 @@ declare var UIkit;
|
|||
</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']
|
||||
})
|
||||
export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
||||
@Input()
|
||||
public user: User;
|
||||
public community: CommunityInfo
|
||||
@Input()
|
||||
public longView: boolean = true;
|
||||
public community: CommunityInfo;
|
||||
public inviteForm: FormGroup;
|
||||
public email: Email;
|
||||
public body: Body;
|
||||
public loading: boolean = false;
|
||||
public validators: ValidatorFn[] = [Validators.email, Validators.required];
|
||||
public loading: boolean = true;
|
||||
private subscriptions: any[] = [];
|
||||
|
||||
constructor(private fb: FormBuilder,
|
||||
|
@ -71,6 +76,7 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.loading = this.longView;
|
||||
this.reset();
|
||||
}
|
||||
|
||||
|
@ -90,7 +96,7 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
|||
this.unsubscribe();
|
||||
this.inviteForm = this.fb.group({
|
||||
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)
|
||||
});
|
||||
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.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() {
|
||||
this.loading = true;
|
||||
this.parseRecipients();
|
||||
this.body.paragraphs = this.inviteForm.value.message;
|
||||
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 => {
|
||||
if(res['success']) {
|
||||
UIkit.notification('Invitation to subscribe has been <b>sent</b>', {
|
||||
|
@ -130,6 +132,7 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
|||
pos: 'bottom-right'
|
||||
});
|
||||
}
|
||||
this.reset();
|
||||
this.loading = false;
|
||||
},error => {
|
||||
UIkit.notification('An error has occurred. Please try again later', {
|
||||
|
@ -137,29 +140,16 @@ export class SubscriberInviteComponent implements OnInit, OnDestroy {
|
|||
timeout: 6000,
|
||||
pos: 'bottom-right'
|
||||
});
|
||||
this.reset();
|
||||
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() {
|
||||
return Session.isPortalAdministrator(this.user) || Session.isCurator('community', this.user) || Session.isManager('community', this.community.communityId, this.user);
|
||||
}
|
||||
|
||||
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) {
|
||||
let community: Portal = this.communityInformation.getValue();
|
||||
|
||||
let pages: Page[] = <Page[]>community.pages;
|
||||
pages = pages.filter(function (page: Page) {
|
||||
return page.route == page_route;
|
||||
});
|
||||
|
||||
if (pages) {
|
||||
let result = false;
|
||||
if (pages['length'] > 0 && pages[0].route == page_route) {
|
||||
result = pages[0].isEnabled;
|
||||
}
|
||||
return result;
|
||||
let page = pages.find((page: Page) => page.route == page_route);
|
||||
return page && page.isEnabled;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,3 +138,8 @@ export const 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>'
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
constructor(private router: Router) {
|
||||
if(typeof window !== "undefined") {
|
||||
this.sub = router.events.subscribe(event => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
if (this.interval) {
|
||||
|
@ -52,6 +53,7 @@ export class SmoothScroll {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getUrl(url: string) {
|
||||
return url.split('?')[0].split('#')[0];
|
||||
|
|
Loading…
Reference in New Issue