Project

General

Profile

1
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
2
import {ActivatedRoute, Router} from '@angular/router';
3
import {Title} from '@angular/platform-browser';
4
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
5
import {Category, Section, Stakeholder, SubCategory, Topic} from "../openaireLibrary/monitor/entities/stakeholder";
6
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
7
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
8
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
9
import {Subscriber, Subscription} from "rxjs";
10
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
11
import {StakeholderUtils} from "../utils/indicator-utils";
12
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
13
import {IDeactivateComponent} from "../openaireLibrary/utils/can-exit.guard";
14

    
15
declare var UIkit;
16

    
17
@Component({
18
  selector: 'topic',
19
  templateUrl: './topic.component.html',
20
})
21
export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent {
22
  public subscriptions: any[] = [];
23
  public properties: EnvProperties;
24
  public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
25
  public loading: boolean = true;
26
  public stakeholder: Stakeholder;
27
  /**
28
   * Current topic
29
   **/
30
  public topicIndex: number = 0;
31
  /**
32
   * categoryIndex: Current category to be edited, selectedCategoryIndex: selected on menu(opened)
33
   */
34
  public categoryIndex: number = 0;
35
  public selectedCategoryIndex: number = 0;
36
  /**
37
   * Current Subcategory to be edited
38
   */
39
  public subCategoryIndex: number = 0;
40
  /**
41
   * Current element and index of topic, category or subcategory to be deleted.
42
   */
43
  public form: FormGroup;
44
  public element: Topic | Category | SubCategory;
45
  public type: 'topic' | 'category' | 'subcategory' = "topic";
46
  public index: number = -1;
47
  /**
48
   * Check form validity
49
   */
50
  public toggle: boolean = false;
51
  
52
  @ViewChild('deleteModal') deleteModal: AlertModal;
53
  @ViewChild('editModal') editModal: AlertModal;
54
  
55
  constructor(
56
    private route: ActivatedRoute,
57
    private router: Router,
58
    private title: Title,
59
    private fb: FormBuilder,
60
    private stakeholderService: StakeholderService) {
61
  }
62
  
63
  public ngOnInit() {
64
    this.route.data
65
      .subscribe((data: { envSpecific: EnvProperties }) => {
66
        this.properties = data.envSpecific;
67
        let subscription: Subscription;
68
        this.route.params.subscribe(params => {
69
          if (subscription) {
70
            subscription.unsubscribe();
71
          }
72
          subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
73
            if (stakeholder) {
74
              this.stakeholder = stakeholder;
75
              this.topicIndex = this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']);
76
              if (this.topicIndex === -1) {
77
                this.navigateToError();
78
              } else {
79
                this.title.setTitle(stakeholder.index_shortName + ' | ' + this.stakeholder.topics[this.topicIndex].name);
80
                this.toggle = true;
81
              }
82
            }
83
          });
84
          this.subscriptions.push(subscription);
85
        });
86
      });
87
  }
88
  
89
  public ngOnDestroy() {
90
  }
91
  
92
  canExit():boolean {
93
    this.subscriptions.forEach(value => {
94
      if (value instanceof Subscriber) {
95
        value.unsubscribe();
96
      }
97
    });
98
    this.stakeholderService.setStakeholder(this.stakeholder);
99
    return true;
100
  }
101
  
102
  hide(element: any) {
103
    UIkit.dropdown(element).hide();
104
  }
105
  
106
  public saveElement() {
107
    if (this.type === "topic") {
108
      this.saveTopic();
109
    } else if (this.type === "category") {
110
      this.saveCategory();
111
    } else {
112
      this.saveSubCategory();
113
    }
114
  }
115
  
116
  public deleteElement() {
117
    if (this.type === "topic") {
118
      this.deleteTopic();
119
    } else if (this.type === "category") {
120
      this.deleteCategory();
121
    } else {
122
      this.deleteSubcategory();
123
    }
124
  }
125
  
126
  private buildTopic(topic: Topic) {
127
    let topics = this.stakeholder.topics.filter(element => element._id !== topic._id);
128
    this.form = this.fb.group({
129
      _id: this.fb.control(topic._id),
130
      name: this.fb.control(topic.name, Validators.required),
131
      description: this.fb.control(topic.description),
132
      alias: this.fb.control(topic.alias, [
133
          Validators.required,
134
          this.stakeholderUtils.aliasValidator(topics)
135
        ]
136
      ),
137
      isActive: this.fb.control(topic.isActive),
138
      isPublic: this.fb.control(topic.isPublic),
139
      defaultId: this.fb.control(topic.defaultId),
140
      categories: this.fb.control(topic.categories),
141
      icon: this.fb.control(topic.icon)
142
    });
143
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
144
      let i = 1;
145
      value = this.stakeholderUtils.generateAlias(value);
146
      this.form.controls['alias'].setValue(value);
147
      while (this.form.get('alias').invalid) {
148
        this.form.controls['alias'].setValue(value + i);
149
        i++;
150
      }
151
    }));
152
  }
153
  
154
  public editTopicOpen() {
155
    this.index = this.topicIndex;
156
    this.type = 'topic';
157
    this.buildTopic(this.stakeholder.topics[this.index]);
158
    this.editOpen();
159
  }
160
  
161
  public saveTopic() {
162
    if (!this.form.invalid) {
163
      let path = [this.stakeholder._id];
164
      let callback = (topic: Topic): void => {
165
        this.stakeholder.topics[this.index] = topic;
166
      };
167
      this.save('Topic has been successfully saved', path, this.form.value, callback, true);
168
    }
169
  }
170
  
171
  public toggleTopicStatus() {
172
    this.index = this.topicIndex;
173
    this.type = 'topic';
174
    let path = [
175
      this.stakeholder._id,
176
      this.stakeholder.topics[this.topicIndex]._id
177
    ];
178
    this.toggleStatus(this.stakeholder.topics[this.topicIndex], path);
179
  }
180
  
181
  public toggleTopicAccess() {
182
    this.index = this.topicIndex;
183
    this.type = 'topic';
184
    let path = [
185
      this.stakeholder._id,
186
      this.stakeholder.topics[this.topicIndex]._id
187
    ];
188
    this.toggleAccess(this.stakeholder.topics[this.topicIndex], path);
189
  }
190
  
191
  public deleteTopicOpen() {
192
    this.type = 'topic';
193
    this.index = this.topicIndex;
194
    this.element = this.stakeholder.topics[this.index];
195
    this.deleteOpen();
196
  }
197
  
198
  public deleteTopic() {
199
    let path: string[] = [
200
      this.stakeholder._id,
201
      this.stakeholder.topics[this.index]._id
202
    ];
203
    let callback = (): void => {
204
      this.stakeholder.topics.splice(this.index, 1);
205
    };
206
    this.delete('Topic has been successfully be deleted', path, callback, true);
207
  }
208
  
209
  public toggleCategory(index: number) {
210
    if (this.selectedCategoryIndex !== index) {
211
      this.selectedCategoryIndex = index;
212
      this.toggle = true;
213
    } else {
214
      this.toggle = !this.toggle;
215
    }
216
  }
217
  
218
  private buildCategory(category: Category) {
219
    let categories = this.stakeholder.topics[this.topicIndex].categories.filter(element => element._id !== category._id);
220
    this.form = this.fb.group({
221
      _id: this.fb.control(category._id),
222
      name: this.fb.control(category.name, Validators.required),
223
      description: this.fb.control(category.description),
224
      alias: this.fb.control(category.alias, [
225
          Validators.required,
226
          this.stakeholderUtils.aliasValidator(categories)
227
        ]
228
      ),
229
      isActive: this.fb.control(category.isActive),
230
      isPublic: this.fb.control(category.isPublic),
231
      defaultId: this.fb.control(category.defaultId),
232
      subCategories: this.fb.control(category.subCategories)
233
    });
234
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
235
      let i = 1;
236
      value = this.stakeholderUtils.generateAlias(value);
237
      this.form.controls['alias'].setValue(value);
238
      while (this.form.get('alias').invalid) {
239
        this.form.controls['alias'].setValue(value + i);
240
        i++;
241
      }
242
    }));
243
  }
244
  
245
  public editCategoryOpen(index: number = -1) {
246
    this.index = index;
247
    this.type = 'category';
248
    if (index === -1) {
249
      this.buildCategory(new Category(null, null, null, true, true));
250
    } else {
251
      this.buildCategory(this.stakeholder.topics[this.topicIndex].categories[index]);
252
    }
253
    this.editOpen();
254
  }
255
  
256
  public saveCategory() {
257
    if (!this.form.invalid) {
258
      let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id];
259
      let callback = (category: Category): void => {
260
        if (this.index === -1) {
261
          this.stakeholder.topics[this.topicIndex].categories.push(category);
262
        } else {
263
          this.stakeholder.topics[this.topicIndex].categories[this.index] = HelperFunctions.copy(category);
264
        }
265
      };
266
      if (this.index === -1) {
267
        this.save('Category has been successfully created', path, this.form.value, callback);
268
      } else {
269
        this.save('Category has been successfully saved', path, this.form.value, callback);
270
      }
271
    }
272
  }
273
  
274
  public toggleCategoryStatus(index: number) {
275
    this.index = index;
276
    this.type = 'category';
277
    let path = [
278
      this.stakeholder._id,
279
      this.stakeholder.topics[this.topicIndex]._id,
280
      this.stakeholder.topics[this.topicIndex].categories[this.index]._id
281
    ];
282
    this.toggleStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path);
283
  }
284
  
285
  public toggleCategoryAccess(index: number) {
286
      this.index = index;
287
      this.type = 'category';
288
      let path = [
289
          this.stakeholder._id,
290
          this.stakeholder.topics[this.topicIndex]._id,
291
          this.stakeholder.topics[this.topicIndex].categories[this.index]._id
292
      ];
293
      this.toggleAccess(this.stakeholder.topics[this.topicIndex].categories[this.index], path);
294
  }
295
  
296
  public deleteCategoryOpen(index: number) {
297
    this.type = 'category';
298
    this.index = index;
299
    this.element = this.stakeholder.topics[this.topicIndex].categories[this.index];
300
    this.deleteOpen();
301
  }
302
  
303
  public deleteCategory() {
304
    let path: string[] = [
305
      this.stakeholder._id,
306
      this.stakeholder.topics[this.topicIndex]._id,
307
      this.stakeholder.topics[this.topicIndex].categories[this.index]._id
308
    ];
309
    let callback = (): void => {
310
      this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1);
311
    };
312
    this.delete('Category has been successfully be deleted', path, callback);
313
  }
314
  
315
  private buildSubcategory(subCategory: SubCategory) {
316
    let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.filter(element => element._id !== subCategory._id);
317
    this.form = this.fb.group({
318
      _id: this.fb.control(subCategory._id),
319
      name: this.fb.control(subCategory.name, Validators.required),
320
      description: this.fb.control(subCategory.description),
321
      alias: this.fb.control(subCategory.alias, [
322
          Validators.required,
323
          this.stakeholderUtils.aliasValidator(subCategories)
324
        ]
325
      ),
326
      isActive: this.fb.control(subCategory.isActive),
327
      isPublic: this.fb.control(subCategory.isPublic),
328
      defaultId: this.fb.control(subCategory.defaultId),
329
      charts: this.fb.control(subCategory.charts),
330
      numbers: this.fb.control(subCategory.numbers)
331
    });
332
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
333
      let i = 1;
334
      value = this.stakeholderUtils.generateAlias(value);
335
      this.form.controls['alias'].setValue(value);
336
      while (this.form.get('alias').invalid) {
337
        this.form.controls['alias'].setValue(value + i);
338
        i++;
339
      }
340
    }));
341
  }
342
  
343
  public editSubCategoryOpen(index: number = -1) {
344
    this.index = index;
345
    this.type = 'subcategory';
346
    if (index === -1) {
347
      this.buildSubcategory(new SubCategory(null, null, null, true, true));
348
    } else {
349
      this.buildSubcategory(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[index]);
350
    }
351
    this.editOpen();
352
  }
353
  
354
  public saveSubCategory() {
355
    if (!this.form.invalid) {
356
      let path: string[] = [
357
        this.stakeholder._id,
358
        this.stakeholder.topics[this.topicIndex]._id,
359
        this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id
360
      ];
361
      let callback = (subCategory: SubCategory): void => {
362
        if (this.index === -1) {
363
          this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.push(subCategory);
364
        } else {
365
          this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index] = subCategory;
366
        }
367
      };
368
      if (this.index === -1) {
369
        this.save('Subcategory has been successfully created', path, this.form.value, callback);
370
      } else {
371
        this.save('Subcategory has been successfully saved', path, this.form.value, callback);
372
      }
373
    }
374
  }
375
    
376
    public toggleSubcategoryStatus(index: number) {
377
        this.index = index;
378
        this.type = 'subcategory';
379
        let path = [
380
            this.stakeholder._id,
381
            this.stakeholder.topics[this.topicIndex]._id,
382
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
383
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
384
        ];
385
        this.toggleStatus(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path);
386
    }
387
    
388
    public toggleSubcategoryAccess(index: number) {
389
        this.index = index;
390
        this.type = 'subcategory';
391
        let path = [
392
            this.stakeholder._id,
393
            this.stakeholder.topics[this.topicIndex]._id,
394
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
395
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
396
        ];
397
        this.toggleAccess(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path);
398
    }
399
  
400
  public deleteSubcategoryOpen(index) {
401
    this.type = 'subcategory';
402
    this.index = index;
403
    this.element = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index];
404
    this.deleteOpen();
405
  }
406
  
407
  public deleteSubcategory() {
408
    let path: string[] = [
409
      this.stakeholder._id,
410
      this.stakeholder.topics[this.topicIndex]._id,
411
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
412
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
413
    ];
414
    let callback = (): void => {
415
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.splice(this.index, 1);
416
    };
417
    this.delete('Subcategory has been successfully be deleted', path, callback);
418
  }
419
  
420
  private navigateToError() {
421
    this.router.navigate(['/error'], {queryParams: {'page': this.router.url}});
422
  }
423
  
424
  private editOpen() {
425
    this.editModal.cancelButtonText = 'Cancel';
426
    this.editModal.okButtonLeft = false;
427
    this.editModal.alertMessage = false;
428
    if (this.index === -1) {
429
      this.editModal.alertTitle = 'Create a new ' + this.type;
430
      this.editModal.okButtonText = 'Create';
431
    } else {
432
      this.editModal.alertTitle = 'Edit ' + this.type + '\'s information ';
433
      this.editModal.okButtonText = 'Save';
434
    }
435
    this.editModal.open();
436
  }
437
  
438
  private deleteOpen() {
439
    this.deleteModal.alertTitle = 'Delete ' + this.type;
440
    this.deleteModal.cancelButtonText = 'No';
441
    this.deleteModal.okButtonText = 'Yes';
442
    this.deleteModal.open();
443
  }
444
  
445
  private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) {
446
    this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => {
447
      callback(saveElement);
448
      UIkit.notification(message, {
449
        status: 'success',
450
        timeout: 3000,
451
        pos: 'top-left'
452
      });
453
      if (redirect) {
454
        this.router.navigate(['../' + saveElement.alias], {
455
          relativeTo: this.route
456
        });
457
      }
458
    }, error => {
459
      UIkit.notification(error.error.message, {
460
        status: 'danger',
461
        timeout: 3000,
462
        pos: 'top-left'
463
      });
464
    });
465
  }
466
  
467
  private delete(message: string, path: string[], callback: Function, redirect = false) {
468
    this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path).subscribe(() => {
469
      callback();
470
      UIkit.notification(message, {
471
        status: 'success',
472
        timeout: 3000,
473
        pos: 'top-left'
474
      });
475
      if (redirect) {
476
        this.back();
477
      }
478
    }, error => {
479
      UIkit.notification(error.error.message, {
480
        status: 'danger',
481
        timeout: 3000,
482
        pos: 'top-left'
483
      });
484
    });
485
  }
486
  
487
  private toggleStatus(element: Topic | Category | SubCategory, path: string[]) {
488
    this.stakeholderService.toggleStatus(this.properties.monitorServiceAPIURL, path).subscribe(isActive => {
489
      element.isActive = isActive;
490
      UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully changed to ' + (isActive ? 'active' : 'inactive'), {
491
        status: 'success',
492
        timeout: 3000,
493
        pos: 'top-left'
494
      });
495
    }, error => {
496
      UIkit.notification(error.error.message, {
497
        status: 'danger',
498
        timeout: 3000,
499
        pos: 'top-left'
500
      });
501
    });
502
  }
503
  
504
  private toggleAccess(element: Topic | Category | SubCategory, path: string[]) {
505
    this.stakeholderService.toggleAccess(this.properties.monitorServiceAPIURL, path).subscribe(isPublic => {
506
      element.isPublic = isPublic;
507
      UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully changed to ' + (isPublic ? 'public' : 'private'), {
508
        status: 'success',
509
        timeout: 3000,
510
        pos: 'top-left'
511
      });
512
    }, error => {
513
      UIkit.notification(error.error.message, {
514
        status: 'danger',
515
        timeout: 3000,
516
        pos: 'top-left'
517
      });
518
    });
519
  }
520
  
521
  back() {
522
    this.router.navigate(['../'], {
523
      relativeTo: this.route
524
    });
525
  }
526
  
527
  chooseSubcategory(categoryIndex: number, subcategoryIndex: number) {
528
    this.categoryIndex = categoryIndex;
529
    this.subCategoryIndex = subcategoryIndex;
530
  }
531
}
(5-5/6)