Project

General

Profile

1
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
2
import {ActivatedRoute, Router} from '@angular/router';
3
import {DomSanitizer, Title} from '@angular/platform-browser';
4
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
5
import {
6
  Category,
7
  Section,
8
  Stakeholder,
9
  SubCategory,
10
  Topic,
11
  Visibility
12
} from "../openaireLibrary/monitor/entities/stakeholder";
13
import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
14
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
15
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
16
import {Subscriber, Subscription} from "rxjs";
17
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
18
import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils";
19
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
20
import {IDeactivateComponent} from "../openaireLibrary/utils/can-exit.guard";
21
import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
22
import {Option} from "../openaireLibrary/dashboard/sharedComponents/input/input.component";
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
  public subscriptions: any[] = [];
32
  public properties: EnvProperties;
33
  public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
34
  public indicatorUtils: IndicatorUtils = new IndicatorUtils();
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') deleteModal: AlertModal;
63
  @ViewChild('editModal') 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.route.data
82
      .subscribe((data: { envSpecific: EnvProperties }) => {
83
        this.properties = data.envSpecific;
84
        let subscription: Subscription;
85
        this.route.params.subscribe(params => {
86
          if (subscription) {
87
            subscription.unsubscribe();
88
          }
89
          subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
90
            if (stakeholder) {
91
              this.stakeholder = stakeholder;
92
              if(params['topic']) {
93
                this.topicIndex = this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']);
94
              }else{
95
                this.topicIndex = 0;
96
              }
97
              this.categoryIndex = 0;
98
              this.subCategoryIndex = 0;
99
              this.filters = this.fb.group({
100
                chartType: this.fb.control('all'),
101
                status: this.fb.control('all'),
102
                keyword: this.fb.control('')
103
              });
104
              if (this.topicIndex === -1) {
105
                this.navigateToError();
106
              } else {
107
                this.title.setTitle(stakeholder.name);
108
                this.toggle = true;
109
              }
110
            }
111
          });
112
          this.subscriptions.push(subscription);
113
        });
114
      });
115
  }
116
  
117
  public ngOnDestroy() {
118
  }
119
  
120
  canExit():boolean {
121
    this.subscriptions.forEach(value => {
122
      if (value instanceof Subscriber) {
123
        value.unsubscribe();
124
      }
125
    });
126
    this.stakeholderService.setStakeholder(this.stakeholder);
127
    return true;
128
  }
129
  
130
  hide(element: any) {
131
    UIkit.dropdown(element).hide();
132
  }
133
  
134
  public saveElement() {
135
    if (this.type === "topic") {
136
      this.saveTopic();
137
    } else if (this.type === "category") {
138
      this.saveCategory();
139
    } else {
140
      this.saveSubCategory();
141
    }
142
  }
143

    
144
  // public closeDeleteModal() {
145
  //   this.deleteModal.cancel();
146
  // }
147
  
148
  public deleteElement() {
149
    if (this.type === "topic") {
150
      this.deleteTopic();
151
    } else if (this.type === "category") {
152
      this.deleteCategory();
153
    } else {
154
      this.deleteSubcategory();
155
    }
156
  }
157
  
158
  private buildTopic(topic: Topic) {
159
    let topics = this.stakeholder.topics.filter(element => element._id !== topic._id);
160
    this.form = this.fb.group({
161
      _id: this.fb.control(topic._id),
162
      name: this.fb.control(topic.name, Validators.required),
163
      description: this.fb.control(topic.description),
164
      alias: this.fb.control(topic.alias, [
165
          Validators.required,
166
          this.stakeholderUtils.aliasValidator(topics)
167
        ]
168
      ),
169
      visibility: this.fb.control(topic.visibility),
170
      defaultId: this.fb.control(topic.defaultId),
171
      categories: this.fb.control(topic.categories),
172
      icon: this.fb.control(topic.icon)
173
    });
174
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
175
      let i = 1;
176
      value = this.stakeholderUtils.generateAlias(value);
177
      this.form.controls['alias'].setValue(value);
178
      while (this.form.get('alias').invalid) {
179
        this.form.controls['alias'].setValue(value + i);
180
        i++;
181
      }
182
    }));
183
  }
184
  
185
  public editTopicOpen(index= -1) {
186
    this.index = index;
187
    this.type = 'topic';
188
    if (index === -1) {
189
      this.buildTopic(new Topic(null, null, null, "PUBLIC"));
190
    } else {
191
      this.buildTopic(this.stakeholder.topics[index]);
192
    }
193
    this.editOpen();
194
  }
195
  
196
  public saveTopic() {
197
    if (!this.form.invalid) {
198
      let path = [this.stakeholder._id];
199
      let callback = (topic: Topic): void => {
200
        if (this.index === -1) {
201
          this.stakeholder.topics.push(topic);
202
        } else {
203
          this.stakeholder.topics[this.index] = HelperFunctions.copy(topic);
204
        }
205
      };
206
      if (this.index === -1) {
207
        this.save('Topic has been successfully created', path, this.form.value, callback);
208
      } else {
209
        this.save('Topic has been successfully saved', path, this.form.value, callback);
210
      }
211
    }
212
  }
213
  
214
  public changeTopicStatus(index: number, visibility:Visibility) {
215
    this.type = 'topic';
216
    let path = [
217
      this.stakeholder._id,
218
      this.stakeholder.topics[index]._id
219
    ];
220
    this.changeStatus(this.stakeholder.topics[index], path, visibility);
221
  }
222

    
223
  
224
  public deleteTopicOpen( index=this.topicIndex, childrenAction: string = null) {
225
    this.type = 'topic';
226
    this.index = index;
227
    this.element = this.stakeholder.topics[this.index];
228
    this.deleteOpen(childrenAction);
229
  }
230
  
231
  public deleteTopic(index=this.topicIndex) {
232
    let path: string[] = [
233
      this.stakeholder._id,
234
      this.stakeholder.topics[index]._id
235
    ];
236
    let callback = (): void => {
237
      this.stakeholder.topics.splice(index, 1);
238
    };
239
    this.delete('Topic has been successfully be deleted', path, callback, true);
240
  }
241
  
242
  public toggleCategory(index: number) {
243
    if (this.categoryIndex !== index) {
244
      this.categoryIndex = index;
245
      this.toggle = true;
246
    } else {
247
      this.toggle = !this.toggle;
248
    }
249
  }
250
  
251
  private buildCategory(category: Category) {
252
    let categories = this.stakeholder.topics[this.topicIndex].categories.filter(element => element._id !== category._id);
253
    this.form = this.fb.group({
254
      _id: this.fb.control(category._id),
255
      name: this.fb.control(category.name, Validators.required),
256
      description: this.fb.control(category.description),
257
      alias: this.fb.control(category.alias, [
258
          Validators.required,
259
          this.stakeholderUtils.aliasValidator(categories)
260
        ]
261
      ),
262
      visibility: this.fb.control(category.visibility),
263
      defaultId: this.fb.control(category.defaultId),
264
      subCategories: this.fb.control(category.subCategories)
265
    });
266
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
267
      let i = 1;
268
      value = this.stakeholderUtils.generateAlias(value);
269
      this.form.controls['alias'].setValue(value);
270
      while (this.form.get('alias').invalid) {
271
        this.form.controls['alias'].setValue(value + i);
272
        i++;
273
      }
274
    }));
275
  }
276
  
277
  public editCategoryOpen(index: number = -1) {
278
    this.index = index;
279
    this.type = 'category';
280
    if (index === -1) {
281
      this.buildCategory(new Category(null, null, null, "PUBLIC"));
282
    } else {
283
      this.buildCategory(this.stakeholder.topics[this.topicIndex].categories[index]);
284
    }
285
    this.editOpen();
286
  }
287
  
288
  public saveCategory() {
289
    if (!this.form.invalid) {
290
      let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id];
291
      let callback = (category: Category): void => {
292
        if (this.index === -1) {
293
          this.stakeholder.topics[this.topicIndex].categories.push(category);
294
        } else {
295
          this.stakeholder.topics[this.topicIndex].categories[this.index] = HelperFunctions.copy(category);
296
        }
297
      };
298
      if (this.index === -1) {
299
        this.save('Category has been successfully created', path, this.form.value, callback);
300
      } else {
301
        this.save('Category has been successfully saved', path, this.form.value, callback);
302
      }
303
    }
304
  }
305
  
306
  public changeCategoryStatus(index: number, visibility:Visibility) {
307
    this.index = index;
308
    this.type = 'category';
309
    let path = [
310
      this.stakeholder._id,
311
      this.stakeholder.topics[this.topicIndex]._id,
312
      this.stakeholder.topics[this.topicIndex].categories[this.index]._id
313
    ];
314
    this.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path, visibility);
315
  }
316

    
317
  
318
  public deleteCategoryOpen(index: number, childrenAction: string = null) {
319
    this.type = 'category';
320
    this.index = index;
321
    this.element = this.stakeholder.topics[this.topicIndex].categories[this.index];
322
    this.deleteOpen(childrenAction);
323
  }
324
  
325
  public deleteCategory() {
326
    let path: string[] = [
327
      this.stakeholder._id,
328
      this.stakeholder.topics[this.topicIndex]._id,
329
      this.stakeholder.topics[this.topicIndex].categories[this.index]._id
330
    ];
331
    let callback = (): void => {
332
      this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1);
333
    };
334
    this.delete('Category has been successfully be deleted', path, callback);
335
  }
336
  
337
  private buildSubcategory(subCategory: SubCategory) {
338
    let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.filter(element => element._id !== subCategory._id);
339
    this.form = this.fb.group({
340
      _id: this.fb.control(subCategory._id),
341
      name: this.fb.control(subCategory.name, Validators.required),
342
      description: this.fb.control(subCategory.description),
343
      alias: this.fb.control(subCategory.alias, [
344
          Validators.required,
345
          this.stakeholderUtils.aliasValidator(subCategories)
346
        ]
347
      ),
348
      visibility: this.fb.control(subCategory.visibility),
349
      defaultId: this.fb.control(subCategory.defaultId),
350
      charts: this.fb.control(subCategory.charts),
351
      numbers: this.fb.control(subCategory.numbers)
352
    });
353
    this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => {
354
      let i = 1;
355
      value = this.stakeholderUtils.generateAlias(value);
356
      this.form.controls['alias'].setValue(value);
357
      while (this.form.get('alias').invalid) {
358
        this.form.controls['alias'].setValue(value + i);
359
        i++;
360
      }
361
    }));
362
  }
363
  
364
  public editSubCategoryOpen(index: number = -1) {
365
    this.index = index;
366
    this.type = 'subcategory';
367
    if (index === -1) {
368
      this.buildSubcategory(new SubCategory(null, null, null, "PUBLIC"));
369
    } else {
370
      this.buildSubcategory(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[index]);
371
    }
372
    this.editOpen();
373
  }
374
  
375
  public saveSubCategory() {
376
    if (!this.form.invalid) {
377
      let path: string[] = [
378
        this.stakeholder._id,
379
        this.stakeholder.topics[this.topicIndex]._id,
380
        this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id
381
      ];
382
      let callback = (subCategory: SubCategory): void => {
383
        if (this.index === -1) {
384
          this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.push(subCategory);
385
        } else {
386
          this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index] = subCategory;
387
        }
388
      };
389
      if (this.index === -1) {
390
        this.save('Subcategory has been successfully created', path, this.form.value, callback);
391
      } else {
392
        this.save('Subcategory has been successfully saved', path, this.form.value, callback);
393
      }
394
    }
395
  }
396

    
397
    public changeSubcategoryStatus(index: number, visibility:Visibility) {
398
        this.index = index;
399
        this.type = 'subcategory';
400
        let path = [
401
            this.stakeholder._id,
402
            this.stakeholder.topics[this.topicIndex]._id,
403
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
404
            this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
405
        ];
406
        this.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path, visibility);
407
    }
408
    
409

    
410
  
411
  public deleteSubcategoryOpen(index, childrenAction: string = null) {
412
    this.type = 'subcategory';
413
    this.index = index;
414
    this.element = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index];
415
    this.deleteOpen(childrenAction);
416
  }
417
  
418
  public deleteSubcategory() {
419
    let path: string[] = [
420
      this.stakeholder._id,
421
      this.stakeholder.topics[this.topicIndex]._id,
422
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
423
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
424
    ];
425
    let callback = (): void => {
426
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.splice(this.index, 1);
427
    };
428
    this.delete('Subcategory has been successfully be deleted', path, callback);
429
  }
430
  
431
  private navigateToError() {
432
    this.router.navigate(['/error'], {queryParams: {'page': this.router.url}});
433
  }
434
  
435
  private editOpen() {
436
    this.editModal.cancelButtonText = 'Cancel';
437
    this.editModal.okButtonLeft = false;
438
    this.editModal.alertMessage = false;
439
    if (this.index === -1) {
440
      this.editModal.alertTitle = 'Create a new ' + this.type;
441
      this.editModal.okButtonText = 'Create';
442
    } else {
443
      this.editModal.alertTitle = 'Edit ' + this.type + '\'s information ';
444
      this.editModal.okButtonText = 'Save';
445
    }
446
    this.editModal.open();
447
  }
448
  
449
  private deleteOpen(childrenAction: string = null) {
450
    this.elementChildrenActionOnDelete = null;
451
    if(childrenAction == "delete") {
452
      this.elementChildrenActionOnDelete = childrenAction;
453
    } else if(childrenAction == "disconnect") {
454
      this.elementChildrenActionOnDelete = childrenAction;
455
    }
456

    
457
    this.deleteModal.alertTitle = 'Delete ' + this.type;
458
    this.deleteModal.cancelButtonText = 'No';
459
    this.deleteModal.okButtonText = 'Yes';
460
    // this.deleteModal.cancelButton = false;
461
    // this.deleteModal.okButton = false;
462
    this.deleteModal.open();
463
  }
464
  
465
  private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) {
466
    this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => {
467
      callback(saveElement);
468
      this.stakeholderService.setStakeholder(this.stakeholder);
469
      UIkit.notification(message, {
470
        status: 'success',
471
        timeout: 3000,
472
        pos: 'top-left'
473
      });
474
      if (redirect) {
475
        this.router.navigate(['../' + saveElement.alias], {
476
          relativeTo: this.route
477
        });
478
      }
479
    }, error => {
480
      UIkit.notification(error.error.message, {
481
        status: 'danger',
482
        timeout: 3000,
483
        pos: 'top-left'
484
      });
485
    });
486
  }
487
  
488
  private delete(message: string, path: string[], callback: Function, redirect = false) {
489
    this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.elementChildrenActionOnDelete).subscribe(() => {
490
      callback();
491
      this.stakeholderService.setStakeholder(this.stakeholder);
492
      UIkit.notification(message, {
493
        status: 'success',
494
        timeout: 3000,
495
        pos: 'top-left'
496
      });
497
      if (redirect) {
498
        this.back();
499
      }
500
    }, error => {
501
      UIkit.notification(error.error.message, {
502
        status: 'danger',
503
        timeout: 3000,
504
        pos: 'top-left'
505
      });
506
    });
507
  }
508

    
509
  public toggleStatusByIndex(index: number, visibility:Visibility, type) {
510
    if(type == "sub"){
511
      this.changeSubcategoryStatus(index,visibility);
512
    }else if(type == "cat"){
513
      this.changeCategoryStatus(index,visibility);
514
    }
515
    else if(type == "topic") {
516
      this.changeTopicStatus(index,visibility);
517
    }
518
  }
519
  
520
  private changeStatus(element: Topic | Category | SubCategory, path: string[], visibility:Visibility) {
521
    this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => {
522
      element.visibility = visibility;
523
      this.stakeholderService.setStakeholder(this.stakeholder);
524
      UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully changed to ' + element.visibility.toLowerCase(), {
525
        status: 'success',
526
        timeout: 3000,
527
        pos: 'top-left'
528
      });
529
    }, error => {
530
      UIkit.notification(error.error.message, {
531
        status: 'danger',
532
        timeout: 3000,
533
        pos: 'top-left'
534
      });
535
    });
536
  }
537
  
538
  back() {
539
    this.router.navigate(['../'], {
540
      relativeTo: this.route
541
    });
542
  }
543
  
544
  chooseSubcategory(categoryIndex: number, subcategoryIndex: number) {
545
    this.categoryIndex = categoryIndex;
546
    this.subCategoryIndex = subcategoryIndex;
547
  }
548

    
549
  public getPluralTypeName(): string {
550
    if(this.type == "topic") {
551
      return "Topics";
552
    } else if(this.type == "category") {
553
      return "Categories";
554
    } else if(this.type == "subcategory") {
555
      return "Subcategories";
556
    } else {
557
      return this.type;
558
    }
559
  }
560

    
561
  public get isSmallScreen() {
562
    return this.layoutService.isSmallScreen;
563
  }
564
  public get open() {
565
    return this.layoutService.open;
566
  }
567

    
568
  public toggleOpen(event: MouseEvent) {
569
    event.preventDefault();
570
    this.layoutService.setOpen(!this.open);
571
  }
572
}
(6-6/7)