Project

General

Profile

1
import {Component, Input, OnDestroy} from "@angular/core";
2
import {Stakeholder} from "../../openaireLibrary/monitor/entities/stakeholder";
3
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
4
import {StakeholderUtils} from "../../utils/indicator-utils";
5
import {Option} from "../../openaireLibrary/sharedComponents/input/input.component";
6
import {Subscriber, Subscription} from "rxjs";
7
import {EnvProperties} from "../../openaireLibrary/utils/properties/env-properties";
8
import {properties} from "../../../environments/environment";
9
import {StakeholderService} from "../../openaireLibrary/monitor/services/stakeholder.service";
10
import {UtilitiesService} from "../../openaireLibrary/services/utilities.service";
11
import {Session, User} from "../../openaireLibrary/login/utils/helper.class";
12
import {UserManagementService} from "../../openaireLibrary/services/user-management.service";
13

    
14
declare var UIkit;
15

    
16
@Component({
17
  selector: 'edit-stakeholder',
18
  template: `
19
    <div *ngIf="stakeholderFb && user" [ngStyle]="{'max-height': maxHeight}"
20
         [class.uk-padding-small]="!paddingLarge" [class.uk-padding-large]="paddingLarge"
21
         class="uk-overflow-auto"
22
         [formGroup]="stakeholderFb">
23
      <div class="uk-grid" uk-grid uk-height-match=".uk-form-hint">
24
        <div dashboard-input class="uk-width-1-2@m" [formInput]="stakeholderFb.get('name')" label="Name"
25
             placeholder="Write a name..."
26
             hint="Set a name for your profile."></div>
27
        <div dashboard-input class="uk-width-1-2@m" [formInput]="stakeholderFb.get('alias')"
28
             hint="Set an URL alias for your profile."
29
             label="URL Alias" placeholder="Write an alias..."></div>
30
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_id')"
31
             label="Index ID" placeholder="Write index ID.">
32
        </div>
33
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_name')"
34
             label="Index Name" placeholder="Write index name.">
35
        </div>
36
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('index_shortName')"
37
             label="Index Short Name" placeholder="Write index short name.">
38
        </div>
39
        <div dashboard-input class="uk-width-1-1" [type]="'textarea'" placeholder="Write a description..."
40
             hint="Write a description for your profile"
41
             [rows]="4" [formInput]="stakeholderFb.get('description')" label="Description"></div>
42
        <input #file id="photo" type="file" class="uk-hidden" (change)="fileChangeEvent($event)"/>
43
        <div dashboard-input class="uk-width-1-1" [hideControl]="stakeholderFb.get('isUpload').value"
44
             hint="Upload or link the logo of your profile" [placeholder]="'Write link to the logo'"
45
             [formInput]="stakeholderFb.get('logoUrl')" label="Logo">
46
          <div *ngIf="!stakeholderFb.get('isUpload').value" class="uk-width-2-5@l uk-width-1-1">
47
            <div class="uk-grid uk-flex uk-flex-middle" uk-grid>
48
              <div class="uk-width-3-4@l uk-width-1-1 uk-flex uk-flex-center">
49
                <button class="uk-button uk-button-secondary uk-flex uk-flex-middle uk-flex-wrap"
50
                        (click)="file.click()">
51
                  <icon name="cloud_upload" [flex]="true"></icon>
52
                  <span class="uk-margin-small-left">Upload a file</span>
53
                </button>
54
              </div>
55
              <div class="uk-text-center uk-text-bold uk-width-expand">
56
                OR
57
              </div>
58
            </div>
59
          </div>
60
          <div *ngIf="stakeholderFb.get('isUpload').value" class="uk-width-1-1 uk-flex uk-flex-middle">
61
            <div class="uk-card uk-card-default uk-text-center uk-border-circle">
62
              <img class="uk-position-center" [src]="photo">
63
            </div>
64
            <div class="uk-margin-left">
65
              <button (click)="remove()" class="uk-button-secondary outlined uk-icon-button">
66
                <icon name="remove"></icon>
67
              </button>
68
            </div>
69
            <div class="uk-margin-small-left">
70
              <button class="uk-button-secondary uk-icon-button" (click)="file.click()">
71
                <icon name="edit"></icon>
72
              </button>
73
            </div>
74
          </div>
75
        </div>
76
        <div *ngIf="uploadError" class="uk-text-danger uk-width-1-1">{{uploadError}}</div>
77
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('visibility')"
78
             [placeholder]="'Select a status'"
79
             label="Status" hint="Select the visibility status of your profile"
80
             [options]="stakeholderUtils.statuses" type="select">
81
        </div>
82
        <div dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('type')"
83
             [placeholder]="'Select a type'" hint="Select the type of your profile"
84
             label="Type" [options]="types" type="select">
85
        </div>
86
        <ng-container
87
            *ngIf="!stakeholderFb.get('isDefault').value && isNew && stakeholderFb.get('type').valid && defaultStakeholdersOptions">
88
          <div [placeholder]="'Select a template'"
89
               hint="Select a template for your profile"
90
               dashboard-input class="uk-width-1-3@m" [formInput]="stakeholderFb.get('defaultId')"
91
               label="Template" [options]="defaultStakeholdersOptions" type="select"></div>
92
        </ng-container>
93
      </div>
94
    </div>`,
95
  styleUrls: ['edit-stakeholder.component.css']
96
})
97
export class EditStakeholderComponent implements OnDestroy {
98
  @Input()
99
  public maxHeight = 'none';
100
  @Input()
101
  public paddingLarge: boolean = false;
102
  @Input()
103
  public disableAlias: boolean = false;
104
  public stakeholderFb: FormGroup;
105
  public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
106
  public defaultStakeholdersOptions: Option[];
107
  public defaultStakeholders: Stakeholder[];
108
  public stakeholders: Stakeholder[];
109
  public stakeholder: Stakeholder;
110
  public isDefault: boolean;
111
  public isNew: boolean;
112
  public types: Option[];
113
  public properties: EnvProperties = properties;
114
  private subscriptions: any[] = [];
115
  /**
116
   * Photo upload
117
   * */
118
  public file: File;
119
  public photo: string | ArrayBuffer;
120
  public uploadError: string;
121
  public deleteCurrentPhoto: boolean = false;
122
  private maxsize: number = 200 * 1024;
123
  user: User;
124
  
125
  constructor(private fb: FormBuilder,
126
              private stakeholderService: StakeholderService,
127
              private utilsService: UtilitiesService, private userManagementService: UserManagementService,) {
128
  }
129
  
130
  ngOnDestroy() {
131
    this.reset();
132
  }
133
  
134
  public init(stakeholder: Stakeholder, stakeholders: Stakeholder[], defaultStakeholders: Stakeholder[], isDefault: boolean, isNew: boolean) {
135
    this.reset();
136
    this.deleteCurrentPhoto = false;
137
    this.stakeholder = stakeholder;
138
    this.stakeholders = stakeholders;
139
    this.defaultStakeholders = defaultStakeholders;
140
    this.isDefault = isDefault;
141
    this.isNew = isNew;
142
    this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
143
        this.user = user;
144
        this.types = this.stakeholderUtils.getTypesByUserRoles(this.user, this.stakeholder.alias);
145
        this.stakeholderFb = this.fb.group({
146
          _id: this.fb.control(this.stakeholder._id),
147
          defaultId: this.fb.control(this.stakeholder.defaultId),
148
          name: this.fb.control(this.stakeholder.name, Validators.required),
149
          description: this.fb.control(this.stakeholder.description),
150
          index_name: this.fb.control(this.stakeholder.index_name, Validators.required),
151
          index_id: this.fb.control(this.stakeholder.index_id, Validators.required),
152
          index_shortName: this.fb.control(this.stakeholder.index_shortName, Validators.required),
153
          creationDate: this.fb.control(this.stakeholder.creationDate),
154
          alias: this.fb.control(this.stakeholder.alias,
155
            [
156
              Validators.required,
157
              this.stakeholderUtils.aliasValidator(
158
                (this.isDefault) ?
159
                  this.defaultStakeholders.filter(stakeholder => stakeholder.alias !== this.stakeholder.alias) :
160
                  this.stakeholders.filter(stakeholder => stakeholder.alias !== this.stakeholder.alias)
161
              )]
162
          ),
163
          isDefault: this.fb.control((this.isDefault)),
164
          visibility: this.fb.control(this.stakeholder.visibility, Validators.required),
165
          type: this.fb.control(this.stakeholder.type, Validators.required),
166
          topics: this.fb.control(this.stakeholder.topics),
167
          managers: this.fb.control(this.stakeholder.managers),
168
          isUpload: this.fb.control(this.stakeholder.isUpload),
169
          logoUrl: this.fb.control(this.stakeholder.logoUrl),
170
        });
171
        this.initPhoto();
172
        if (!isDefault) {
173
          this.subscriptions.push(this.stakeholderFb.get('type').valueChanges.subscribe(value => {
174
            this.onTypeChange(value, defaultStakeholders);
175
          }));
176
          this.stakeholderFb.setControl('defaultId', this.fb.control(stakeholder.defaultId, Validators.required));
177
        }
178
        if (!isNew) {
179
          if (this.isAdmin) {
180
            if (this.disableAlias) {
181
              setTimeout(() => {
182
                this.stakeholderFb.get('alias').disable();
183
              }, 0);
184
            }
185
          } else {
186
            setTimeout(() => {
187
              this.stakeholderFb.get('alias').disable();
188
              this.stakeholderFb.get('index_id').disable();
189
              this.stakeholderFb.get('index_name').disable();
190
              this.stakeholderFb.get('index_shortName').disable();
191
            }, 0);
192
          }
193
          setTimeout(() => {
194
            this.stakeholderFb.get('type').disable();
195
          }, 0);
196
        } else {
197
          setTimeout(() => {
198
            this.stakeholderFb.get('type').enable();
199
          }, 0);
200
        }
201
      }
202
    ));
203
  }
204
  
205
  public get isAdmin() {
206
    return Session.isPortalAdministrator(this.user);
207
  }
208
  
209
  public get disabled(): boolean {
210
    return (this.stakeholderFb && this.stakeholderFb.invalid) ||
211
      (this.stakeholderFb && this.stakeholderFb.pristine && !this.isNew && !this.file) ||
212
      (this.uploadError && this.uploadError.length > 0);
213
  }
214
  
215
  public get dirty(): boolean {
216
    return this.stakeholderFb && this.stakeholderFb.dirty;
217
  }
218
  
219
  reset() {
220
    this.uploadError = null;
221
    this.stakeholderFb = null;
222
    this.subscriptions.forEach(subscription => {
223
      if (subscription instanceof Subscription) {
224
        subscription.unsubscribe();
225
      }
226
    });
227
  }
228
  
229
  onTypeChange(value, defaultStakeholders: Stakeholder[]) {
230
    this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, Validators.required));
231
    this.defaultStakeholdersOptions = [{
232
      label: 'New blank profile',
233
      value: '-1'
234
    }];
235
    defaultStakeholders.filter(stakeholder => stakeholder.type === value).forEach(stakeholder => {
236
      this.defaultStakeholdersOptions.push({
237
        label: 'Use ' + stakeholder.name + ' profile',
238
        value: stakeholder._id
239
      })
240
    });
241
  }
242
  
243
  public save(callback: Function, errorCallback: Function = null) {
244
    if (this.file) {
245
      this.stakeholderFb.get('alias').enable();
246
      this.subscriptions.push(this.utilsService.uploadPhoto(this.properties.utilsService + "/upload/stakeholder/" + encodeURIComponent(this.stakeholderFb.value.alias), this.file).subscribe(res => {
247
        this.deletePhoto();
248
        this.removePhoto();
249
        this.stakeholderFb.get('logoUrl').setValue(res.filename);
250
        console.debug(this.stakeholderFb.value);
251
        this.saveStakeholder(callback, errorCallback);
252
      }, error => {
253
        this.uploadError = "An error has been occurred during upload your image. Try again later";
254
        this.saveStakeholder(callback, errorCallback);
255
      }));
256
    } else if (this.deleteCurrentPhoto) {
257
      this.deletePhoto();
258
      this.saveStakeholder(callback, errorCallback);
259
    } else {
260
      this.saveStakeholder(callback, errorCallback);
261
    }
262
  }
263
  
264
  public saveStakeholder(callback: Function, errorCallback: Function = null) {
265
    if (this.isNew) {
266
      if (!this.stakeholderFb.value.isDefault) {
267
        let stakeholder = this.defaultStakeholders.find(value => value._id === this.stakeholderFb.value.defaultId);
268
        this.stakeholderFb.setValue(this.stakeholderUtils.createFunderFromDefaultProfile(this.stakeholderFb.value,
269
          (stakeholder ? stakeholder.topics : [])));
270
      }
271
      this.removePhoto();
272
      this.subscriptions.push(this.stakeholderService.buildStakeholder(this.properties.monitorServiceAPIURL,
273
        this.stakeholderFb.value).subscribe(stakeholder => {
274
        UIkit.notification(stakeholder.name + ' has been <b>successfully created</b>', {
275
          status: 'success',
276
          timeout: 6000,
277
        pos: 'bottom-right'
278
        });
279
        callback(stakeholder);
280
      }, error => {
281
        UIkit.notification('An error has occurred. Please try again later', {
282
          status: 'danger',
283
          timeout: 6000,
284
        pos: 'bottom-right'
285
        });
286
        if (errorCallback) {
287
          errorCallback(error)
288
        }
289
      }));
290
    } else {
291
      this.stakeholderFb.get('type').enable();
292
      this.stakeholderFb.get('index_id').enable();
293
      this.stakeholderFb.get('index_name').enable();
294
      this.stakeholderFb.get('index_shortName').enable();
295
      this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, this.stakeholderFb.value).subscribe(stakeholder => {
296
        UIkit.notification(stakeholder.name + ' has been <b>successfully saved</b>', {
297
          status: 'success',
298
          timeout: 6000,
299
        pos: 'bottom-right'
300
        });
301
        callback(stakeholder);
302
      }, error => {
303
        UIkit.notification('An error has occurred. Please try again later', {
304
          status: 'danger',
305
          timeout: 6000,
306
        pos: 'bottom-right'
307
        });
308
      }));
309
    }
310
  }
311
  
312
  fileChangeEvent(event) {
313
    if (event.target.files && event.target.files[0]) {
314
      this.file = event.target.files[0];
315
      if (this.file.type !== 'image/png' && this.file.type !== 'image/jpeg') {
316
        this.uploadError = 'You must choose a file with type: image/png or image/jpeg!';
317
        this.stakeholderFb.get('isUpload').setValue(false);
318
        this.stakeholderFb.get('isUpload').markAsDirty();
319
        this.removePhoto();
320
      } else if (this.file.size > this.maxsize) {
321
        this.uploadError = 'File exceeds size\'s limit! Maximum resolution is 256x256 pixels.';
322
        this.stakeholderFb.get('isUpload').setValue(false);
323
        this.stakeholderFb.get('isUpload').markAsDirty();
324
        this.removePhoto();
325
      } else {
326
        this.uploadError = null;
327
        const reader = new FileReader();
328
        reader.readAsDataURL(this.file);
329
        reader.onload = () => {
330
          this.photo = reader.result;
331
          this.stakeholderFb.get('isUpload').setValue(true);
332
          this.stakeholderFb.get('isUpload').markAsDirty();
333
        };
334
      }
335
    }
336
  }
337
  
338
  initPhoto() {
339
    if (this.stakeholderFb.value.isUpload) {
340
      this.photo = this.properties.utilsService + "/download/" + this.stakeholderFb.get('logoUrl').value;
341
    }
342
  }
343
  
344
  removePhoto() {
345
    if (this.file) {
346
      if (typeof document != 'undefined') {
347
        (<HTMLInputElement>document.getElementById("photo")).value = "";
348
      }
349
      this.initPhoto();
350
      this.file = null;
351
    }
352
  }
353
  
354
  remove() {
355
    this.stakeholderFb.get('isUpload').setValue(false);
356
    this.stakeholderFb.get('isUpload').markAsDirty();
357
    this.removePhoto();
358
    this.stakeholderFb.setControl('logoUrl', this.fb.control(null));
359
    if (this.stakeholder.isUpload) {
360
      this.deleteCurrentPhoto = true;
361
    }
362
  }
363
  
364
  public deletePhoto() {
365
    if (this.stakeholder.logoUrl) {
366
      this.subscriptions.push(this.utilsService.deletePhoto(this.properties.utilsService + '/delete/stakeholder/' + this.stakeholder.logoUrl).subscribe());
367
    }
368
  }
369
}
(2-2/3)