Project

General

Profile

« Previous | Next » 

Revision 60968

[Library | Trunk]: Fix server errors. Input add validators for chips. Subscriber-invite: Change To field to chips, add short view

View differences:

modules/uoa-services-library/trunk/ng-openaire-library/src/app/utils/smooth-scroll.ts
11 11
  private lastRoute;
12 12
  
13 13
  constructor(private router: Router) {
14
    this.sub = router.events.subscribe(event => {
15
      if (event instanceof NavigationEnd) {
16
        if (this.interval) {
17
          clearInterval(this.interval);
18
        }
19
        const fragment = router.parseUrl(router.url).fragment;
20
        if (this.lastRoute !== this.getUrl(event.url)) {
21
          window.scrollTo({top: 0});
22
        }
23
        if (fragment) {
24
          let i = 0;
25
          this.interval = setInterval(() => {
26
            i++;
27
            const element = document.getElementById(fragment);
28
            if (element) {
29
              if (this.interval) {
14
    if(typeof window !== "undefined") {
15
      this.sub = router.events.subscribe(event => {
16
        if (event instanceof NavigationEnd) {
17
          if (this.interval) {
18
            clearInterval(this.interval);
19
          }
20
          const fragment = router.parseUrl(router.url).fragment;
21
          if (this.lastRoute !== this.getUrl(event.url)) {
22
            window.scrollTo({top: 0});
23
          }
24
          if (fragment) {
25
            let i = 0;
26
            this.interval = setInterval(() => {
27
              i++;
28
              const element = document.getElementById(fragment);
29
              if (element) {
30
                if (this.interval) {
31
                  clearInterval(this.interval);
32
                }
33
                const yOffset = -100;
34
                let position = 0;
35
                let interval = setInterval(() => {
36
                  if (position !== element.getBoundingClientRect().top) {
37
                    position = element.getBoundingClientRect().top;
38
                  } else {
39
                    clearInterval(interval);
40
                    const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset;
41
                    window.scrollTo({top: y, behavior: 'smooth'});
42
                  }
43
                }, 50);
44
              }
45
              if (i > 4 && this.interval) {
30 46
                clearInterval(this.interval);
31 47
              }
32
              const yOffset = -100;
33
              let position = 0;
34
              let interval = setInterval(() => {
35
                if (position !== element.getBoundingClientRect().top) {
36
                  position = element.getBoundingClientRect().top;
37
                } else {
38
                  clearInterval(interval);
39
                  const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset;
40
                  window.scrollTo({top: y, behavior: 'smooth'});
41
                }
42
              }, 50);
43
            }
44
            if (i > 4 && this.interval) {
45
              clearInterval(this.interval);
46
            }
47
          }, 100);
48
        } else {
49
          window.scrollTo({top: 0, behavior: 'smooth'});
48
            }, 100);
49
          } else {
50
            window.scrollTo({top: 0, behavior: 'smooth'});
51
          }
52
          this.lastRoute = this.getUrl(event.url);
50 53
        }
51
        this.lastRoute = this.getUrl(event.url);
52
      }
53
    });
54
      });
55
    }
54 56
  }
55 57
  
56 58
  private getUrl(url: string) {
modules/uoa-services-library/trunk/ng-openaire-library/src/app/utils/configuration/configuration.service.ts
118 118

  
119 119
  filtering(page_route: string) {
120 120
      let community: Portal = this.communityInformation.getValue();
121

  
122 121
      let pages: Page[] = <Page[]>community.pages;
123
      pages = pages.filter(function (page: Page) {
124
        return page.route == page_route;
125
      });
126

  
127 122
      if (pages) {
128
        let result = false;
129
        if (pages['length'] > 0 && pages[0].route == page_route) {
130
          result = pages[0].isEnabled;
131
        }
132
        return result;
123
        let page = pages.find((page: Page) => page.route == page_route);
124
        return page && page.isEnabled;
125
      } else {
126
        return false;
133 127
      }
134 128
  }
135 129

  
modules/uoa-services-library/trunk/ng-openaire-library/src/app/utils/icons/icons.ts
138 138
  name: 'reset',
139 139
  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>'
140 140
}
141

  
142
export const send = {
143
  name: 'send',
144
  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>'
145
}
modules/uoa-services-library/trunk/ng-openaire-library/src/app/sharedComponents/input/input.component.ts
11 11
  SimpleChanges,
12 12
  ViewChild
13 13
} from "@angular/core";
14
import {AbstractControl, FormArray, FormControl} from "@angular/forms";
14
import {AbstractControl, FormArray, FormControl, ValidatorFn} from "@angular/forms";
15 15
import {HelperFunctions} from "../../utils/HelperFunctions.class";
16 16
import {Observable, of, Subscription} from "rxjs";
17 17
import {MatSelect} from "@angular/material/select";
......
100 100
                  </span>
101 101
                </mat-chip>
102 102
                <div [class.uk-hidden]="formControl.value" class="uk-width-expand uk-position-relative chip-input">
103
                  <input #searchInput class="uk-width-1-1" [formControl]="searchControl" [matAutocomplete]="auto"
103
                  <input #searchInput [formControl]="searchControl" [matAutocomplete]="auto"
104 104
                         [matChipInputFor]="chipList" [matAutocompleteConnectedTo]="origin">
105 105
                  <div *ngIf="placeholder && !searchInput.value" class="placeholder uk-width-1-1"
106 106
                       (click)="searchInput.focus()">{{placeholder}}</div>
......
119 119
          <div [ngClass]="inputClass"
120 120
               [attr.uk-tooltip]="formControl.disabled?'title: This field is not editable; pos: bottom-left':null"
121 121
               [class.clickable]="formControl.enabled"
122
               [class.uk-form-danger]="formControl.invalid && formControl.touched" (click)="openSelect()">
122
               [class.uk-form-danger]="formControl.invalid && searchControl.invalid && searchControl.touched" (click)="openSelect()">
123 123
            <mat-form-field class="uk-width-1-1">
124 124
              <mat-chip-list #chipList>
125 125
                <mat-chip *ngFor="let chip of formAsArray.controls; let i=index" [selectable]="false"
......
130 130
                  </span>
131 131
                </mat-chip>
132 132
                <div class="uk-width-expand uk-position-relative chip-input">
133
                  <input #searchInput class="uk-width-1-1" [formControl]="searchControl" [matAutocomplete]="auto"
133
                  <input #searchInput style="width: calc(100% - 8px) !important;" [formControl]="searchControl" [matAutocomplete]="auto"
134 134
                         [matChipInputFor]="chipList" [matAutocompleteConnectedTo]="origin"
135 135
                         [matChipInputAddOnBlur]="addExtraChips && searchControl.value"
136 136
                         (matChipInputTokenEnd)="add($event)">
......
181 181
  /** Textarea options */
182 182
  @Input('rows') rows: number = 3;
183 183
  /** Select | chips available options */
184
  @Input('options') options: Option[];
184
  @Input('options') options: Option[] = [];
185 185
  @Input('hint') hint = null;
186 186
  @Input('placeholder') placeholder = '';
187 187
  @Input() inputClass: string = 'input-box';
......
200 200
  @Input() panelWidth: number = 300;
201 201
  @Input() panelClass: string = null;
202 202
  @Input() showOptionsOnEmpty: boolean = true;
203
  @Input() validators: ValidatorFn[];
203 204
  @Output() focusEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
204 205
  /** LogoUrl information */
205 206
  public secure: boolean = true;
......
248 249
      this.secure = (!this.initValue || this.initValue.includes('https://'));
249 250
    }
250 251
    if (this.type === 'chips' || this.type === 'autocomplete') {
251
      if(!this.options) {
252
        console.error('Please provide options to continue');
253
      } else {
252
      if(this.options) {
254 253
        this.filteredOptions = of(this.options);
255
        this.searchControl = new FormControl('');
254
        this.searchControl = new FormControl('', this.validators);
256 255
        this.subscriptions.push(this.searchControl.valueChanges.subscribe(value => {
257 256
          setTimeout(() => {
258 257
            this.searchInput.nativeElement.focus();
......
333 332
  }
334 333
  
335 334
  add(event: MatChipInputEvent) {
336
    if (this.addExtraChips && event.value) {
335
    if (this.addExtraChips && event.value && this.searchControl.valid) {
337 336
      this.stopPropagation();
338
      this.formAsArray.push(new FormControl(event.value));
337
      this.formAsArray.push(new FormControl(event.value, this.validators));
339 338
      this.formAsArray.markAsDirty();
340 339
      this.searchControl.setValue('');
341 340
      this.searchInput.nativeElement.value = '';
modules/uoa-services-library/trunk/ng-openaire-library/src/app/sharedComponents/subscriber-invite/subscriber-invite.component.ts
1 1
import {Component, Input, OnDestroy, OnInit} from "@angular/core";
2
import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, Validators} from "@angular/forms";
2
import {AbstractControl, FormBuilder, FormGroup, ValidationErrors, ValidatorFn, Validators} from "@angular/forms";
3 3
import {Subscriber} from "rxjs";
4 4
import {StringUtils} from "../../utils/string-utils.class";
5 5
import {Email} from "../../utils/email/email";
......
16 16
@Component({
17 17
  selector: 'subscriber-invite',
18 18
  template: `
19
    <div class="uk-grid uk-child-width-1-1" uk-grid [formGroup]="inviteForm">
19
    <div *ngIf="longView" class="uk-grid uk-child-width-1-1" uk-grid [formGroup]="inviteForm">
20 20
      <div dashboard-input [formInput]="inviteForm.get('name')" [gridSmall]="true">
21 21
        <div class="uk-text-bold field-label">
22 22
          From:
23 23
        </div>
24 24
      </div>
25
      <div dashboard-input [formInput]="inviteForm.get('recipients')" [gridSmall]="true">
26
        <div class="uk-text-bold field-label uk-margin-bottom">
25
      <div dashboard-input [formInput]="inviteForm.get('recipients')" type="chips" placeholder="Write email(s)" [addExtraChips]="true" [validators]="validators" [gridSmall]="true">
26
        <div class="uk-text-bold field-label">
27 27
          To *:
28 28
        </div>
29
        <span note>Separate multiple emails with a comma</span>
30 29
      </div>
31 30
      <div class="uk-grid uk-grid-small" uk-grid>
32 31
        <div class="uk-text-bold field-label">
......
34 33
        </div>
35 34
        <div class="uk-width-expand">
36 35
          <ckeditor *ngIf="isManager" class="form-control" formControlName="message" id="message"
37
                    debounce="400"
36
                    debounce="400" (ready)="loading = false"
38 37
                    [config]="{ extraAllowedContent: '* [uk-*](*) ; span', disallowedContent: 'script; *[on*]', removeButtons: 'Save,NewPage,DocProps,Preview,Print',
39 38
                                                                   extraPlugins: 'divarea'}"></ckeditor>
40 39
          <div *ngIf="!isManager" [innerHTML]="body.paragraphs"></div>
......
52 51
        </div>
53 52
      </div>
54 53
    </div>
54
    <div *ngIf="!longView">
55
      <div dashboard-input [formInput]="inviteForm.get('recipients')" type="chips" placeholder="Write email(s)" [addExtraChips]="true" [validators]="validators" [gridSmall]="true"></div>
56
    </div>
55 57
  `,
56 58
  styleUrls: ['subscriber-invite.component.css']
57 59
})
58 60
export class SubscriberInviteComponent implements OnInit, OnDestroy {
59 61
  @Input()
60 62
  public user: User;
61
  public community: CommunityInfo
63
  @Input()
64
  public longView: boolean = true;
65
  public community: CommunityInfo;
62 66
  public inviteForm: FormGroup;
63 67
  public email: Email;
64 68
  public body: Body;
65
  public loading: boolean = false;
69
  public validators: ValidatorFn[] = [Validators.email, Validators.required];
70
  public loading: boolean = true;
66 71
  private subscriptions: any[] = [];
67 72
  
68 73
  constructor(private fb: FormBuilder,
......
71 76
  }
72 77
  
73 78
  ngOnInit() {
79
    this.loading = this.longView;
74 80
    this.reset();
75 81
  }
76 82
  
......
90 96
    this.unsubscribe();
91 97
    this.inviteForm = this.fb.group({
92 98
      name: this.fb.control('', Validators.required),
93
      recipients: this.fb.control('', [Validators.required, this.emailsValidator]),
99
      recipients: this.fb.array([], Validators.required),
94 100
      message: this.fb.control('', Validators.required)
95 101
    });
96 102
    this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
......
102 108
      this.email = Composer.initializeInvitationsEmail(community.title);
103 109
      this.inviteForm.get('message').setValue(this.body.paragraphs);
104 110
    }));
105
  }
106
  
107
  emailsValidator(control: AbstractControl): ValidationErrors | null {
108
    if (control.value === '' || !control.value || StringUtils.validateEmails(control.value)) {
109
      return null;
111
    if(!this.isManager) {
112
      this.loading = false;
110 113
    }
111
    return { emails: true };
112 114
  }
113 115
  
114 116
  invite() {
115 117
    this.loading = true;
116
    this.parseRecipients();
117 118
    this.body.paragraphs = this.inviteForm.value.message;
118 119
    this.email.body = Composer.formatEmailBodyForInvitation(this.body);
120
    this.email.recipients = this.inviteForm.get('recipients').value;
119 121
    this.subscriptions.push(this.emailService.sendEmail(properties, this.email).subscribe(res => {
120 122
      if(res['success']) {
121 123
        UIkit.notification('Invitation to subscribe has been <b>sent</b>', {
......
130 132
          pos: 'bottom-right'
131 133
        });
132 134
      }
135
      this.reset();
133 136
      this.loading = false;
134 137
    },error => {
135 138
      UIkit.notification('An error has occurred. Please try again later', {
......
137 140
        timeout: 6000,
138 141
        pos: 'bottom-right'
139 142
      });
143
      this.reset();
140 144
      this.loading = false;
141 145
    }));
142 146
  }
143 147
  
144
  public parseRecipients() {
145
    // remove spaces
146
    let emails = this.inviteForm.get('recipients').value.replace(/\s/g, '');
147
    // remove commas
148
    emails = emails.split(",");
149
    
150
    // remove empty fields
151
    for (let i = 0; i < emails.length; i++) {
152
      if (!(emails[i] == "")) {
153
        this.email.recipients.push(emails[i]);
154
      }
155
    }
156
  }
157
  
158 148
  get isManager() {
159 149
    return Session.isPortalAdministrator(this.user) || Session.isCurator('community', this.user) || Session.isManager('community', this.community.communityId, this.user);
160 150
  }
161 151
  
162 152
  get valid() {
163
    return this.inviteForm && this.inviteForm.valid;
153
    return !this.loading && this.inviteForm && this.inviteForm.valid;
164 154
  }
165 155
}

Also available in: Unified diff