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 {
6
  Category,
7
  Stakeholder,
8
  SubCategory,
9
  Topic,
10
  Visibility
11
} from "../openaireLibrary/monitor/entities/stakeholder";
12
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
13
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
14
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
15
import {Subscriber, Subscription} from "rxjs";
16
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
17
import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils";
18
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
19
import {IDeactivateComponent} from "../openaireLibrary/utils/can-exit.guard";
20
import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
21
import {Option} from "../openaireLibrary/sharedComponents/input/input.component";
22
import {properties} from "../../environments/environment";
23

    
24
declare var UIkit;
25

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