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 "../utils/entities/stakeholder";
6
import {StakeholderService} from "../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
    });
142
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
143
      let i = 1;
144
      value = this.stakeholderUtils.generateAlias(value);
145
      this.form.controls['alias'].setValue(value);
146
      while (this.form.get('alias').invalid) {
147
        this.form.controls['alias'].setValue(value + i);
148
        i++;
149
      }
150
    }));
151
  }
152
  
153
  public editTopicOpen() {
154
    this.index = this.topicIndex;
155
    this.type = 'topic';
156
    this.buildTopic(this.stakeholder.topics[this.index]);
157
    this.editOpen();
158
  }
159
  
160
  public saveTopic() {
161
    if (!this.form.invalid) {
162
      let path = [this.stakeholder._id];
163
      let callback = (topic: Topic): void => {
164
        this.stakeholder.topics[this.index] = topic;
165
      };
166
      this.save('Topic has been successfully saved', path, this.form.value, callback, true);
167
    }
168
  }
169
  
170
  public toggleTopicStatus() {
171
    this.index = this.topicIndex;
172
    this.type = 'topic';
173
    let path = [
174
      this.stakeholder._id,
175
      this.stakeholder.topics[this.topicIndex]._id
176
    ];
177
    this.toggleStatus(this.stakeholder.topics[this.topicIndex], path);
178
  }
179
  
180
  public toggleTopicAccess() {
181
    this.index = this.topicIndex;
182
    this.type = 'topic';
183
    let path = [
184
      this.stakeholder._id,
185
      this.stakeholder.topics[this.topicIndex]._id
186
    ];
187
    this.toggleAccess(this.stakeholder.topics[this.topicIndex], path);
188
  }
189
  
190
  public deleteTopicOpen() {
191
    this.type = 'topic';
192
    this.index = this.topicIndex;
193
    this.element = this.stakeholder.topics[this.index];
194
    this.deleteOpen();
195
  }
196
  
197
  public deleteTopic() {
198
    let path: string[] = [
199
      this.stakeholder._id,
200
      this.stakeholder.topics[this.index]._id
201
    ];
202
    let callback = (): void => {
203
      this.stakeholder.topics.splice(this.index, 1);
204
    };
205
    this.delete('Topic has been successfully be deleted', path, callback, true);
206
  }
207
  
208
  public toggleCategory(index: number) {
209
    if (this.selectedCategoryIndex !== index) {
210
      this.selectedCategoryIndex = index;
211
      this.toggle = true;
212
    } else {
213
      this.toggle = !this.toggle;
214
    }
215
  }
216
  
217
  private buildCategory(category: Category) {
218
    let categories = this.stakeholder.topics[this.topicIndex].categories.filter(element => element._id !== category._id);
219
    this.form = this.fb.group({
220
      _id: this.fb.control(category._id),
221
      name: this.fb.control(category.name, Validators.required),
222
      description: this.fb.control(category.description),
223
      alias: this.fb.control(category.alias, [
224
          Validators.required,
225
          this.stakeholderUtils.aliasValidator(categories)
226
        ]
227
      ),
228
      isActive: this.fb.control(category.isActive),
229
      isPublic: this.fb.control(category.isPublic),
230
      defaultId: this.fb.control(category.defaultId),
231
      subCategories: this.fb.control(category.subCategories)
232
    });
233
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
234
      let i = 1;
235
      value = this.stakeholderUtils.generateAlias(value);
236
      this.form.controls['alias'].setValue(value);
237
      while (this.form.get('alias').invalid) {
238
        this.form.controls['alias'].setValue(value + i);
239
        i++;
240
      }
241
    }));
242
  }
243
  
244
  public editCategoryOpen(index: number = -1) {
245
    this.index = index;
246
    this.type = 'category';
247
    if (index === -1) {
248
      this.buildCategory(new Category(null, null, null, true, true));
249
    } else {
250
      this.buildCategory(this.stakeholder.topics[this.topicIndex].categories[index]);
251
    }
252
    this.editOpen();
253
  }
254
  
255
  public saveCategory() {
256
    if (!this.form.invalid) {
257
      let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id];
258
      let callback = (category: Category): void => {
259
        if (this.index === -1) {
260
          this.stakeholder.topics[this.topicIndex].categories.push(category);
261
        } else {
262
          this.stakeholder.topics[this.topicIndex].categories[this.index] = HelperFunctions.copy(category);
263
        }
264
      };
265
      if (this.index === -1) {
266
        this.save('Category has been successfully created', path, this.form.value, callback);
267
      } else {
268
        this.save('Category has been successfully saved', path, this.form.value, callback);
269
      }
270
    }
271
  }
272
  
273
  public toggleCategoryStatus(index: number) {
274
    this.index = index;
275
    this.type = 'category';
276
    let path = [
277
      this.stakeholder._id,
278
      this.stakeholder.topics[this.topicIndex]._id,
279
      this.stakeholder.topics[this.topicIndex].categories[this.index]._id
280
    ];
281
    this.toggleStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path);
282
  }
283
  
284
  public toggleCategoryAccess(index: number) {
285
      this.index = index;
286
      this.type = 'category';
287
      let path = [
288
          this.stakeholder._id,
289
          this.stakeholder.topics[this.topicIndex]._id,
290
          this.stakeholder.topics[this.topicIndex].categories[this.index]._id
291
      ];
292
      this.toggleAccess(this.stakeholder.topics[this.topicIndex].categories[this.index], path);
293
  }
294
  
295
  public deleteCategoryOpen(index: number) {
296
    this.type = 'category';
297
    this.index = index;
298
    this.element = this.stakeholder.topics[this.topicIndex].categories[this.index];
299
    this.deleteOpen();
300
  }
301
  
302
  public deleteCategory() {
303
    let path: string[] = [
304
      this.stakeholder._id,
305
      this.stakeholder.topics[this.topicIndex]._id,
306
      this.stakeholder.topics[this.topicIndex].categories[this.index]._id
307
    ];
308
    let callback = (): void => {
309
      this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1);
310
    };
311
    this.delete('Category has been successfully be deleted', path, callback);
312
  }
313
  
314
  private buildSubcategory(subCategory: SubCategory) {
315
    let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.filter(element => element._id !== subCategory._id);
316
    this.form = this.fb.group({
317
      _id: this.fb.control(subCategory._id),
318
      name: this.fb.control(subCategory.name, Validators.required),
319
      description: this.fb.control(subCategory.description),
320
      alias: this.fb.control(subCategory.alias, [
321
          Validators.required,
322
          this.stakeholderUtils.aliasValidator(subCategories)
323
        ]
324
      ),
325
      isActive: this.fb.control(subCategory.isActive),
326
      isPublic: this.fb.control(subCategory.isPublic),
327
      defaultId: this.fb.control(subCategory.defaultId),
328
      charts: this.fb.control(subCategory.charts),
329
      numbers: this.fb.control(subCategory.numbers)
330
    });
331
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
332
      let i = 1;
333
      value = this.stakeholderUtils.generateAlias(value);
334
      this.form.controls['alias'].setValue(value);
335
      while (this.form.get('alias').invalid) {
336
        this.form.controls['alias'].setValue(value + i);
337
        i++;
338
      }
339
    }));
340
  }
341
  
342
  public editSubCategoryOpen(index: number = -1) {
343
    this.index = index;
344
    this.type = 'subcategory';
345
    if (index === -1) {
346
      this.buildSubcategory(new SubCategory(null, null, null, true, true));
347
    } else {
348
      this.buildSubcategory(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[index]);
349
    }
350
    this.editOpen();
351
  }
352
  
353
  public saveSubCategory() {
354
    if (!this.form.invalid) {
355
      let path: string[] = [
356
        this.stakeholder._id,
357
        this.stakeholder.topics[this.topicIndex]._id,
358
        this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id
359
      ];
360
      let callback = (subCategory: SubCategory): void => {
361
        if (this.index === -1) {
362
          this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.push(subCategory);
363
        } else {
364
          this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index] = subCategory;
365
        }
366
      };
367
      if (this.index === -1) {
368
        this.save('Subcategory has been successfully created', path, this.form.value, callback);
369
      } else {
370
        this.save('Subcategory has been successfully saved', path, this.form.value, callback);
371
      }
372
    }
373
  }
374
    
375
    public toggleSubcategoryStatus(index: number) {
376
        this.index = index;
377
        this.type = 'subcategory';
378
        let path = [
379
            this.stakeholder._id,
380
            this.stakeholder.topics[this.topicIndex]._id,
381
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
382
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
383
        ];
384
        this.toggleStatus(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path);
385
    }
386
    
387
    public toggleSubcategoryAccess(index: number) {
388
        this.index = index;
389
        this.type = 'subcategory';
390
        let path = [
391
            this.stakeholder._id,
392
            this.stakeholder.topics[this.topicIndex]._id,
393
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
394
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
395
        ];
396
        this.toggleAccess(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path);
397
    }
398
  
399
  public deleteSubcategoryOpen(index) {
400
    this.type = 'subcategory';
401
    this.index = index;
402
    this.element = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index];
403
    this.deleteOpen();
404
  }
405
  
406
  public deleteSubcategory() {
407
    let path: string[] = [
408
      this.stakeholder._id,
409
      this.stakeholder.topics[this.topicIndex]._id,
410
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
411
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
412
    ];
413
    let callback = (): void => {
414
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.splice(this.index, 1);
415
    };
416
    this.delete('Subcategory has been successfully be deleted', path, callback);
417
  }
418
  
419
  private navigateToError() {
420
    this.router.navigate(['/error'], {queryParams: {'page': this.router.url}});
421
  }
422
  
423
  private editOpen() {
424
    this.editModal.cancelButtonText = 'Cancel';
425
    this.editModal.okButtonLeft = false;
426
    this.editModal.alertMessage = false;
427
    if (this.index === -1) {
428
      this.editModal.alertTitle = 'Create a new ' + this.type;
429
      this.editModal.okButtonText = 'Create';
430
    } else {
431
      this.editModal.alertTitle = 'Edit ' + this.type + '\'s information ';
432
      this.editModal.okButtonText = 'Save';
433
    }
434
    this.editModal.open();
435
  }
436
  
437
  private deleteOpen() {
438
    this.deleteModal.alertTitle = 'Delete ' + this.type;
439
    this.deleteModal.cancelButtonText = 'No';
440
    this.deleteModal.okButtonText = 'Yes';
441
    this.deleteModal.open();
442
  }
443
  
444
  private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) {
445
    this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => {
446
      callback(saveElement);
447
      UIkit.notification(message, {
448
        status: 'success',
449
        timeout: 3000,
450
        pos: 'top-left'
451
      });
452
      if (redirect) {
453
        this.router.navigate(['../' + saveElement.alias], {
454
          relativeTo: this.route
455
        });
456
      }
457
    }, error => {
458
      UIkit.notification(error.error.message, {
459
        status: 'danger',
460
        timeout: 3000,
461
        pos: 'top-left'
462
      });
463
    });
464
  }
465
  
466
  private delete(message: string, path: string[], callback: Function, redirect = false) {
467
    this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path).subscribe(() => {
468
      callback();
469
      UIkit.notification(message, {
470
        status: 'success',
471
        timeout: 3000,
472
        pos: 'top-left'
473
      });
474
      if (redirect) {
475
        this.back();
476
      }
477
    }, error => {
478
      UIkit.notification(error.error.message, {
479
        status: 'danger',
480
        timeout: 3000,
481
        pos: 'top-left'
482
      });
483
    });
484
  }
485
  
486
  private toggleStatus(element: Topic | Category | SubCategory, path: string[]) {
487
    this.stakeholderService.toggleStatus(this.properties.monitorServiceAPIURL, path).subscribe(isActive => {
488
      element.isActive = isActive;
489
      UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully changed to ' + (isActive ? 'active' : 'inactive'), {
490
        status: 'success',
491
        timeout: 3000,
492
        pos: 'top-left'
493
      });
494
    }, error => {
495
      UIkit.notification(error.error.message, {
496
        status: 'danger',
497
        timeout: 3000,
498
        pos: 'top-left'
499
      });
500
    });
501
  }
502
  
503
  private toggleAccess(element: Topic | Category | SubCategory, path: string[]) {
504
    this.stakeholderService.toggleAccess(this.properties.monitorServiceAPIURL, path).subscribe(isPublic => {
505
      element.isPublic = isPublic;
506
      UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully changed to ' + (isPublic ? 'public' : 'private'), {
507
        status: 'success',
508
        timeout: 3000,
509
        pos: 'top-left'
510
      });
511
    }, error => {
512
      UIkit.notification(error.error.message, {
513
        status: 'danger',
514
        timeout: 3000,
515
        pos: 'top-left'
516
      });
517
    });
518
  }
519
  
520
  back() {
521
    this.router.navigate(['../'], {
522
      relativeTo: this.route
523
    });
524
  }
525
  
526
  chooseSubcategory(categoryIndex: number, subcategoryIndex: number) {
527
    this.categoryIndex = categoryIndex;
528
    this.subCategoryIndex = subcategoryIndex;
529
  }
530
}
(5-5/6)