Project

General

Profile

1
import {
2
  AfterViewInit,
3
  ChangeDetectorRef,
4
  Component,
5
  Input,
6
  OnChanges,
7
  OnDestroy,
8
  OnInit,
9
  SimpleChanges,
10
  ViewChild
11
} from "@angular/core";
12
import {
13
  Indicator,
14
  IndicatorPath, IndicatorSize,
15
  IndicatorType,
16
  Section,
17
  Stakeholder,
18
  Visibility
19
} from "../openaireLibrary/monitor/entities/stakeholder";
20
import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils";
21
import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
22
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
23
import {StatisticsService} from "../utils/services/statistics.service";
24
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
25
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";
26
import {Reorder, StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service";
27
import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties";
28
import {Subscriber} from "rxjs";
29
import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service";
30
import {Router} from "@angular/router";
31
import {Session} from "../openaireLibrary/login/utils/helper.class";
32
import {UserManagementService} from "../openaireLibrary/services/user-management.service";
33
import {StringUtils} from "../openaireLibrary/utils/string-utils.class";
34

    
35
declare var UIkit;
36

    
37
@Component({
38
  selector: 'indicators',
39
  templateUrl: './indicators.component.html',
40
  styleUrls: ['indicators.component.css']
41
})
42
export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
43
  
44
  @Input()
45
  public properties: EnvProperties = null;
46
  @Input()
47
  public topicIndex: number = 0;
48
  @Input()
49
  public categoryIndex: number = 0;
50
  @Input()
51
  public subcategoryIndex: number = 0;
52
  public stakeholder: Stakeholder = null;
53
  public user = null;
54
  public preview: string;
55
  public indicatorUtils: IndicatorUtils = new IndicatorUtils();
56
  public stakeholderUtils: StakeholderUtils = new StakeholderUtils();
57
  public numberIndicatorFb: FormGroup;
58
  public chartIndicatorFb: FormGroup;
59
  public chartSections: FormArray;
60
  public numberSections: FormArray;
61
  /**
62
   * Editable indicator
63
   */
64
  public section: Section;
65
  public indicator: Indicator;
66
  public index: number = -1;
67
  /**
68
   * Displayed chart and numbers base on Top filters
69
   */
70
  public displayCharts: Section[] = [];
71
  public displayNumbers: Section[] = [];
72
  /**
73
   * Top filters
74
   */
75
  @Input()
76
  public filters: FormGroup;
77
  public editing: boolean = false;
78
  /** Safe Urls*/
79
  public safeUrls: Map<string, SafeResourceUrl> = new Map<string, SafeResourceUrl>([]);
80
  public numberResults: Map<string, number> = new Map<string, number>();
81
  private subscriptions: any[] = [];
82
  private urlSubscriptions: any[] = [];
83
  @ViewChild('editChartModal') editChartModal: AlertModal;
84
  @ViewChild('editNumberModal') editNumberModal: AlertModal;
85
  @ViewChild('deleteModal') deleteModal: AlertModal;
86
  //@ViewChild('deleteAllModal') deleteAllModal: AlertModal;
87
  //@ViewChild('deleteAndDisconnectModal') deleteAndDisconnectModal: AlertModal;
88
  //@ViewChild('deleteChartSectionModal') deleteChartSectionModal: AlertModal;
89
  //@ViewChild('deleteNumberSectionModal') deleteNumberSectionModal: AlertModal;
90
  @ViewChild('deleteSectionModal') deleteSectionModal: AlertModal;
91
  public sectionTypeToDelete: string;
92
  public sectionChildrenActionOnDelete: string;
93
  public indicatorChildrenActionOnDelete: string;
94
  
95
  urlParameterizedMessage = null;
96
  
97
  constructor(private layoutService: LayoutService,
98
              private stakeholderService: StakeholderService,
99
              private statisticsService: StatisticsService,
100
              private userManagementService: UserManagementService,
101
              private fb: FormBuilder,
102
              private router: Router,
103
              private cdr: ChangeDetectorRef,
104
              private sanitizer: DomSanitizer) {
105
  }
106
  
107
  ngOnInit(): void {
108
    this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => {
109
      this.user = user;
110
    }));
111
    this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
112
      this.stakeholder = stakeholder;
113
      if (this.stakeholder) {
114
        this.buildFilters();
115
        this.buildSections();
116
        this.filterCharts();
117
        this.filterNumbers();
118
        this.setPreview();
119
      }
120
    }));
121
  }
122
  
123
  ngOnDestroy(): void {
124
    this.subscriptions.forEach(value => {
125
      if (value instanceof Subscriber) {
126
        value.unsubscribe();
127
      } else if (value instanceof Function) {
128
        value();
129
      }
130
    });
131
    this.urlSubscriptions.forEach(value => {
132
      if (value instanceof Subscriber) {
133
        value.unsubscribe();
134
      }
135
    });
136
  }
137
  
138
  ngAfterViewInit(): void {
139
    this.initReorder();
140
  }
141
  
142
  ngOnChanges(changes: SimpleChanges): void {
143
    if (this.canEdit) {
144
      if (changes.topicIndex || changes.categoryIndex || changes.subcategoryIndex) {
145
        this.buildFilters();
146
        this.initReorder();
147
      }
148
      this.filterCharts();
149
      this.filterNumbers();
150
    }
151
    this.setPreview();
152
  }
153
  
154
  setNumberIndicators() {
155
    this.numberResults.clear();
156
    let urls: Map<string, [number, number][]> = new Map<string, [number, number][]>();
157
    this.numbers.forEach((section, i) => {
158
      section.indicators.forEach((number, j) => {
159
        let url = this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, number.indicatorPaths[0]);
160
        const pair = JSON.stringify([number.indicatorPaths[0].source, url]);
161
        const indexes = urls.get(pair) ? urls.get(pair) : [];
162
        indexes.push([i, j]);
163
        urls.set(pair, indexes);
164
      });
165
    });
166
    urls.forEach((indexes, pair) => {
167
      pair = JSON.parse(pair);
168
      this.subscriptions.push(this.statisticsService.getNumbers(this.statisticsService.getSourceType(pair[0]), pair[1]).subscribe(response => {
169
        indexes.forEach(([i, j]) => {
170
          let result = JSON.parse(JSON.stringify(response));
171
          this.numbers[i].indicators[j].indicatorPaths[0].jsonPath.forEach(jsonPath => {
172
            if (result) {
173
              result = result[jsonPath];
174
            }
175
          });
176
          if (typeof result === 'string' || typeof result === 'number') {
177
            result = Number(result);
178
            if (result === Number.NaN) {
179
              result = 0;
180
            }
181
          } else {
182
            result = 0;
183
          }
184
          this.numberResults.set(i + '-' + j, result);
185
        });
186
      }));
187
    });
188
  }
189
  
190
  setPreview() {
191
    if (this.stakeholder) {
192
      this.preview = '/' + this.stakeholder.alias;
193
      if (this.stakeholder.topics[this.topicIndex]) {
194
        this.preview = '/' + this.stakeholder.alias + '/' + this.stakeholder.topics[this.topicIndex].alias;
195
        if (this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]) {
196
          this.preview += '/' + this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].alias;
197
          if (this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]) {
198
            this.preview += '/' + this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].alias;
199
          }
200
        }
201
      }
202
    }
203
  }
204
  
205
  initReorder() {
206
    this.subscriptions.forEach(value => {
207
      if (value instanceof Function) {
208
        value();
209
      }
210
    });
211
    if (document !== undefined) {
212
      let callback = (list, type: IndicatorType, action: 'moved' | 'added' | 'removed'): void => {
213
        let items: HTMLCollection = list.current.children;
214
        let reordered = [];
215
        for (let i = 0; i < items.length; i++) {
216
          if (items.item(i).id) {
217
            reordered.push(items.item(i).id);
218
          }
219
        }
220
        let reorder: Reorder = {
221
          action: action,
222
          target: list.detail[1].id,
223
          ids: reordered
224
        }
225
        this.reorderIndicators(list.current.id.toString().split('-')[1], type, reorder);
226
      };
227
      this.numbers.forEach((section) => {
228
        this.subscriptions.push(UIkit.util.on(document, 'moved', '#number-' + section._id, (list): void => {
229
          callback(list, "number", 'moved');
230
        }));
231
        this.subscriptions.push(UIkit.util.on(document, 'added', '#number-' + section._id, (list): void => {
232
          callback(list, "number", 'added');
233
        }));
234
        this.subscriptions.push(UIkit.util.on(document, 'removed', '#number-' + section._id, (list): void => {
235
          callback(list, "number", 'removed');
236
        }));
237
      });
238
      this.charts.forEach((section) => {
239
        this.subscriptions.push(UIkit.util.on(document, 'moved', '#chart-' + section._id, (list): void => {
240
          callback(list, "chart", 'moved');
241
        }));
242
        this.subscriptions.push(UIkit.util.on(document, 'added', '#chart-' + section._id, (list): void => {
243
          callback(list, "chart", 'added');
244
        }));
245
        this.subscriptions.push(UIkit.util.on(document, 'removed', '#chart-' + section._id, (list): void => {
246
          callback(list, "chart", 'removed');
247
        }));
248
      });
249
    }
250
  }
251
  
252
  hide(element: any) {
253
    UIkit.dropdown(element).hide();
254
  }
255
  
256
  private buildFilters() {
257
    this.subscriptions.push(this.filters.get('chartType').valueChanges.subscribe(value => {
258
      this.onChartTypeChange(value);
259
    }));
260
    
261
    this.subscriptions.push(this.filters.get('status').valueChanges.subscribe(value => {
262
      this.onStatusChange(value);
263
    }));
264
    this.subscriptions.push(this.filters.get('keyword').valueChanges.subscribe(value => {
265
      this.onKeywordChange(value);
266
    }));
267
  }
268
  
269
  private buildSections() {
270
    this.numberSections = this.fb.array([]);
271
    this.numbers.forEach(section => {
272
      this.numberSections.push(this.fb.group({
273
        _id: this.fb.control(section._id),
274
        title: this.fb.control(section.title),
275
        creationDate: this.fb.control(section.creationDate),
276
        stakeholderAlias: this.fb.control(section.stakeholderAlias),
277
        defaultId: this.fb.control(section.defaultId),
278
        type: this.fb.control(section.type),
279
        indicators: this.fb.control(section.indicators)
280
      }));
281
    });
282
    this.chartSections = this.fb.array([]);
283
    this.charts.forEach(section => {
284
      this.chartSections.push(this.fb.group({
285
        _id: this.fb.control(section._id),
286
        title: this.fb.control(section.title),
287
        creationDate: this.fb.control(section.creationDate),
288
        stakeholderAlias: this.fb.control(section.stakeholderAlias),
289
        defaultId: this.fb.control(section.defaultId),
290
        type: this.fb.control(section.type),
291
        indicators: this.fb.control(section.indicators)
292
      }));
293
    });
294
  }
295
  
296
  filterCharts() {
297
    this.displayCharts = this.filterChartType(
298
      this.filterStatus(this.filterByKeyword(HelperFunctions.copy(this.charts), this.filters.value.keyword),
299
        this.filters.value.status),
300
      this.filters.value.chartType
301
    );
302
    this.displayCharts.forEach(section => {
303
      section.indicators.forEach(indicator => {
304
        indicator.indicatorPaths.forEach(indicatorPath => {
305
          let url = this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath);
306
          if (!this.safeUrls.get('url')) {
307
            indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath);
308
            this.safeUrls.set(url, indicatorPath.safeResourceUrl);
309
          }
310
        });
311
      })
312
    });
313
    this.buildSections();
314
  }
315
  
316
  filterNumbers() {
317
    this.displayNumbers = this.filterStatus(
318
      this.filterByKeyword(HelperFunctions.copy(this.numbers), this.filters.value.keyword),
319
      this.filters.value.status);
320
    this.buildSections();
321
    this.setNumberIndicators();
322
  }
323
  
324
  onChartTypeChange(value) {
325
    this.displayCharts = this.filterChartType(HelperFunctions.copy(this.charts), value);
326
  }
327
  
328
  
329
  onStatusChange(value) {
330
    this.displayCharts = this.filterStatus(HelperFunctions.copy(this.charts), value);
331
    this.displayNumbers = this.filterStatus(HelperFunctions.copy(this.numbers), value);
332
  }
333
  
334
  onKeywordChange(value) {
335
    this.displayCharts = this.filterByKeyword(HelperFunctions.copy(this.charts), value);
336
    this.displayNumbers = this.filterByKeyword(HelperFunctions.copy(this.numbers), value);
337
  }
338
  
339
  private filterChartType(sections: Section[], value): Section[] {
340
    if (value !== 'all') {
341
      sections.forEach(section =>
342
        section.indicators = section.indicators.filter(indicator =>
343
          indicator.indicatorPaths.filter(indicatorPath => indicatorPath.type === value).length > 0));
344
    }
345
    return sections;
346
  }
347
  
348
  
349
  private filterStatus(sections: Section[], value): Section[] {
350
    if (value !== 'all') {
351
      sections.forEach(section =>
352
        section.indicators = section.indicators.filter(indicator => indicator.visibility === value));
353
    }
354
    return sections;
355
  }
356
  
357
  private filterByKeyword(sections: Section[], value): Section[] {
358
    if (value !== null && value !== '') {
359
      sections.forEach(section =>
360
        section.indicators = section.indicators.filter(indicator => (indicator.name && indicator.name.toLowerCase().includes(value.toLowerCase()))
361
          || (indicator.description && indicator.description.toLowerCase().includes(value.toLowerCase()))
362
          || (indicator.additionalDescription && indicator.additionalDescription.toLowerCase().includes(value.toLowerCase()))
363
          || indicator.indicatorPaths.filter(indicatorPath => (indicatorPath.parameters && indicatorPath.parameters.title &&
364
            indicatorPath.parameters.title.includes(value.toLowerCase()))).length > 0));
365
    }
366
    return sections;
367
  }
368
  
369
  get charts(): Section[] {
370
    if (this.stakeholder.topics[this.topicIndex] &&
371
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] &&
372
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]) {
373
      return this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].charts;
374
    } else {
375
      return [];
376
    }
377
  }
378
  
379
  set charts(sections: Section[]) {
380
    this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].charts = sections;
381
  }
382
  
383
  get numbers(): Section[] {
384
    if (this.stakeholder.topics[this.topicIndex] &&
385
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] &&
386
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]) {
387
      return this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].numbers;
388
    } else {
389
      return [];
390
    }
391
  }
392
  
393
  set numbers(sections: Section[]) {
394
    this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].numbers = sections;
395
  }
396
  
397
  get open(): boolean {
398
    return this.layoutService.open;
399
  }
400
  
401
  get canReorder(): boolean {
402
    return this.filters.value.chartType === 'all' &&
403
      this.filters.value.status === 'all' && this.filters.value.keyword === '' && !this.editing;
404
  }
405
  
406
  get canEdit() {
407
    return this.stakeholder &&
408
      this.stakeholder.topics[this.topicIndex] &&
409
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] &&
410
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex];
411
  }
412
  
413
  public get numberIndicatorPaths(): FormArray {
414
    return this.numberIndicatorFb.get('indicatorPaths') as FormArray;
415
  }
416
  
417
  public get chartIndicatorPaths(): FormArray {
418
    return this.chartIndicatorFb.get('indicatorPaths') as FormArray;
419
  }
420
  
421
  public getNumberClassBySize(size: IndicatorSize) {
422
    if (size === 'small') {
423
      return 'uk-width-1-4@xl uk-width-1-3@l uk-width-1-2@m uk-width-1-1';
424
    } else if (size === 'medium') {
425
      return 'uk-width-1-3@l uk-width-1-2@m uk-width-1-1';
426
    } else {
427
      return 'uk-width-1-2@l uk-width-1-1@m uk-width-1-1';
428
    }
429
  }
430
  
431
  public getChartClassBySize(size: IndicatorSize) {
432
    if (size === 'small') {
433
      return 'uk-width-1-3@xl uk-width-1-2@m uk-width-1-1';
434
    } else if (size === 'medium') {
435
      return 'uk-width-1-2@l uk-width-1-1';
436
    } else {
437
      return 'uk-width-1-1';
438
    }
439
  }
440
  
441
  public addJsonPath(index: number) {
442
    if (index == 0 && this.getJsonPath(index).getRawValue()[index].indexOf(",") != -1) {
443
      //if in the first path there are more than one paths comma separated, split them and autogenerate the forms
444
      let paths = this.getJsonPath(index).getRawValue()[index].split(",");
445
      for (let i = 0; i < paths.length; i++) {
446
        if (i != 0) {
447
          this.getJsonPath(index).push(this.fb.control('', Validators.required));
448
        }
449
      }
450
      this.getJsonPath(index).setValue(paths)
451
    } else {
452
      this.getJsonPath(index).push(this.fb.control('', Validators.required));
453
    }
454
  }
455
  
456
  public removeJsonPath(i: number, j: number) {
457
    if(this.getJsonPath(i).enabled) {
458
      this.getJsonPath(i).removeAt(j);
459
    }
460
  }
461
  
462
  public validateJsonPath(index: number, dirty: boolean = false) {
463
    let indicatorPath: FormGroup = <FormGroup>this.numberIndicatorPaths.at(index);
464
    if (this.indicator.defaultId === null) {
465
      this.getJsonPath(index).disable();
466
    }
467
    indicatorPath.get('result').setErrors({validating: true});
468
    this.subscriptions.push(this.statisticsService.getNumbers(null, indicatorPath.get('url').value).subscribe(response => {
469
      let result = JSON.parse(JSON.stringify(response));
470
      this.getJsonPath(index).controls.forEach(jsonPath => {
471
        if (result) {
472
          result = result[jsonPath.value];
473
        }
474
      });
475
      setTimeout(() => {
476
        if (this.indicator.defaultId === null) {
477
          this.getJsonPath(index).enable();
478
          if(dirty) {
479
            this.getJsonPath(index).markAsDirty();
480
          }
481
        }
482
        indicatorPath.get('result').setErrors(null);
483
        if (typeof result === 'string' || typeof result === 'number') {
484
          result = Number(result);
485
          if (result !== Number.NaN) {
486
            indicatorPath.get('result').setValue(result);
487
          } else {
488
            indicatorPath.get('result').setValue(0);
489
          }
490
        } else {
491
          indicatorPath.get('result').setValue(0);
492
        }
493
      }, 500);
494
    }, error => {
495
      setTimeout(() => {
496
        if (this.indicator.defaultId === null) {
497
          this.getJsonPath(index).enable();
498
          if (dirty) {
499
            this.getJsonPath(index).markAsDirty();
500
          }
501
        }
502
        indicatorPath.get('result').setErrors(null);
503
        indicatorPath.get('result').setValue(0);
504
      }, 500);
505
    }));
506
  }
507
  
508
  public getJsonPath(index: number): FormArray {
509
    return this.numberIndicatorPaths.at(index).get('jsonPath') as FormArray;
510
  }
511
  
512
  public getCurrentJsonPath(index: number): string[] {
513
    return this.section.indicators[this.index].indicatorPaths[index].jsonPath;
514
  }
515
  
516
  public getParameters(index: number): FormArray {
517
    return this.chartIndicatorPaths.at(index).get('parameters') as FormArray;
518
  }
519
  
520
  public getParameter(index: number, key: string): FormControl {
521
    return this.getParameters(index).controls.filter(control => control.value.key === key)[0] as FormControl;
522
  }
523
  
524
  private getSecureUrlByStakeHolder(indicatorPath: IndicatorPath) {
525
    return this.sanitizer.bypassSecurityTrustResourceUrl(
526
      this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)));
527
  }
528
  
529
  private getUrlByStakeHolder(indicatorPath: IndicatorPath) {
530
    return this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath));
531
  }
532
  
533
  public addNumberIndicatorPath(url: string = '', parameters: FormArray = new FormArray([]), source: string = 'stats-tool', jsonPath: FormArray = new FormArray([])) {
534
    if (jsonPath.length === 0) {
535
      jsonPath.push(this.fb.control('', Validators.required));
536
    }
537
    this.numberIndicatorPaths.push(this.fb.group({
538
        url: this.fb.control(url, [Validators.required, StringUtils.urlValidator()]),
539
        jsonPath: jsonPath,
540
        result: this.fb.control(0, Validators.required),
541
        // parameters: parameters,
542
        source: this.fb.control(source, Validators.required)
543
      }
544
    ));
545
    for (let index = 0; index < this.numberIndicatorPaths.length; index++) {
546
      if (this.numberIndicatorPaths.at(index).get('url').valid) {
547
        this.validateJsonPath(index);
548
      }
549
      if (this.indicator.defaultId === null) {
550
        this.subscriptions.push(this.numberIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => {
551
            this.numberIndicatorPaths.at(index).get('result').setValue(null);
552
            if (this.numberIndicatorPaths.at(index).get('url').valid) {
553
              let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.statisticsService.getNumberSource(value), value, this.stakeholder, this.numberIndicatorPaths.at(index).get('jsonPath').value, this.statisticsService.numberSources.get(this.statisticsService.getNumberSource(value)));
554
              if ((indicatorPath.chartObject && Object.keys(indicatorPath.parameters).indexOf("index_id") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_name") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_shortName") == -1)
555
                || (!indicatorPath.chartObject && indicatorPath.url.indexOf("index_id") == -1 && indicatorPath.url.indexOf("index_name") == -1 && (indicatorPath.url).indexOf("index_shortName") == -1)) {
556
                // default profile
557
                if (this.stakeholder.defaultId == null) {
558
                  this.urlParameterizedMessage = "This indicator couldn't be generated properly. Stakeholders based on this profile may not inherit the data correctly."
559
                } else {
560
                  this.urlParameterizedMessage = "This indicator couldn't be generated properly. Please make sure chart data is for the current stakeholder."
561
                }
562
              } else {
563
                this.urlParameterizedMessage = null;
564
              }
565
              if (this.indicator.indicatorPaths[index]) {
566
                this.indicator.indicatorPaths[index] = indicatorPath;
567
              } else {
568
                this.indicator.indicatorPaths.push(indicatorPath);
569
              }
570
              if (indicatorPath.source) {
571
                this.numberIndicatorPaths.at(index).get('source').setValue(indicatorPath.source);
572
              }
573
              if (indicatorPath.jsonPath.length > 1 && this.getJsonPath(index).length == 1) {
574
                let paths = indicatorPath.jsonPath;
575
                for (let i = 0; i < paths.length; i++) {
576
                  if (i == this.getJsonPath(index).length) {
577
                    this.getJsonPath(index).push(this.fb.control('', Validators.required));
578
                  }
579
                }
580
                this.getJsonPath(index).setValue(paths)
581
              }
582
            } else {
583
              this.urlParameterizedMessage = null;
584
            }
585
          })
586
        );
587
        
588
        this.subscriptions.push(this.numberIndicatorPaths.at(index).get('jsonPath').valueChanges.subscribe(value => {
589
            if (this.indicator.indicatorPaths[index]) {
590
              this.indicator.indicatorPaths[index].jsonPath = value;
591
            }
592
            this.numberIndicatorPaths.at(index).get('result').setValue(null);
593
          })
594
        );
595
        this.subscriptions.push(this.numberIndicatorPaths.at(index).get('source').valueChanges.subscribe(value => {
596
            if (this.indicator.indicatorPaths[index]) {
597
              this.indicator.indicatorPaths[index].source = value;
598
            }
599
          })
600
        );
601
      } else {
602
        this.numberIndicatorPaths.at(index).get('url').disable();
603
        this.numberIndicatorPaths.at(index).get('jsonPath').disable();
604
        this.numberIndicatorPaths.at(index).get('source').disable();
605
      }
606
    }
607
  }
608
  
609
  public addChartIndicatorPath(value: string = '', parameters: FormArray = new FormArray([]), disableUrl: boolean = false, type: string = null) {
610
    this.chartIndicatorPaths.push(this.fb.group({
611
        url: this.fb.control(value, [Validators.required, StringUtils.urlValidator()]),
612
        parameters: parameters,
613
        type: this.fb.control(type)
614
      }
615
    ));
616
    if (disableUrl) {
617
      for (let index = 0; index < this.chartIndicatorPaths.length; index++) {
618
        this.chartIndicatorPaths.at(index).get('url').disable();
619
      }
620
    } else {
621
      for (let index = 0; index < this.chartIndicatorPaths.length; index++) {
622
        this.urlSubscriptions.push(this.chartIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => {
623
            if (this.chartIndicatorPaths.at(index).get('url').valid) {
624
              let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.statisticsService.getChartSource(value), value, this.chartIndicatorPaths.at(index).get('type').value, this.stakeholder);
625
              if (indicatorPath.chartObject && Object.keys(indicatorPath.parameters).indexOf("index_id") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_name") == -1 && Object.keys(indicatorPath.parameters).indexOf("index_shortName") == -1) {
626
                // default profile
627
                if (this.stakeholder.defaultId == null) {
628
                  this.urlParameterizedMessage = "This chart couldn't be generated properly. Stakeholders based on this profile may not inherit the data correctly."
629
                } else {
630
                  this.urlParameterizedMessage = "This chart couldn't be generated properly. Please make sure chart data is for the current stakeholder."
631
                }
632
              } else {
633
                this.urlParameterizedMessage = null;
634
              }
635
              (this.chartIndicatorPaths.at(index) as FormGroup).get('type').setValue(indicatorPath.type);
636
              let parameters = this.getParametersAsFormArray(indicatorPath);
637
              (this.chartIndicatorPaths.at(index) as FormGroup).setControl('parameters', parameters);
638
              if (!this.indicator.indicatorPaths[index]) {
639
                this.indicator.indicatorPaths[index] = indicatorPath;
640
                this.indicator.indicatorPaths[index].safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath);
641
              } else {
642
                indicatorPath.safeResourceUrl = this.indicator.indicatorPaths[index].safeResourceUrl;
643
                this.indicator.indicatorPaths[index] = indicatorPath;
644
              }
645
            } else {
646
              this.urlParameterizedMessage = null;
647
            }
648
          })
649
        );
650
      }
651
    }
652
  }
653
  
654
  private getJsonPathAsFormArray(indicatorPath: IndicatorPath): FormArray {
655
    let jsonPath = this.fb.array([]);
656
    if (indicatorPath.jsonPath) {
657
      indicatorPath.jsonPath.forEach(path => {
658
        jsonPath.push(this.fb.control(path, Validators.required));
659
      });
660
    }
661
    return jsonPath;
662
  }
663
  
664
  private getParametersAsFormArray(indicatorPath: IndicatorPath): FormArray {
665
    let parameters = this.fb.array([]);
666
    if (indicatorPath.parameters) {
667
      Object.keys(indicatorPath.parameters).forEach(key => {
668
        if (this.indicatorUtils.ignoredParameters.indexOf(key) === -1) {
669
          if (this.indicatorUtils.parametersValidators.has(key)) {
670
            parameters.push(this.fb.group({
671
              key: this.fb.control(key),
672
              value: this.fb.control(indicatorPath.parameters[key], this.indicatorUtils.parametersValidators.get(key))
673
            }));
674
          } else {
675
            parameters.push(this.fb.group({
676
              key: this.fb.control(key),
677
              value: this.fb.control(indicatorPath.parameters[key])
678
            }));
679
          }
680
        }
681
      });
682
    }
683
    return parameters;
684
  }
685
  
686
  public editNumberIndicatorOpen(section: Section, id = null) {
687
    this.urlParameterizedMessage = null;
688
    this.section = section;
689
    this.index = (id) ? section.indicators.findIndex(value => value._id === id) : -1;
690
    if (this.index !== -1) {
691
      this.indicator = HelperFunctions.copy(this.section.indicators[this.index]);
692
      this.numberIndicatorFb = this.fb.group({
693
        _id: this.fb.control(this.indicator._id),
694
        name: this.fb.control(this.indicator.name, Validators.required),
695
        description: this.fb.control(this.indicator.description),
696
        creationDate: this.fb.control(this.indicator.creationDate),
697
        additionalDescription: this.fb.control(this.indicator.additionalDescription),
698
        visibility: this.fb.control(this.indicator.visibility),
699
        indicatorPaths: this.fb.array([], Validators.required),
700
        type: this.fb.control(this.indicator.type),
701
        width: this.fb.control(this.indicator.width),
702
        height: this.fb.control(this.indicator.height),
703
        defaultId: this.fb.control(this.indicator.defaultId)
704
      });
705
      this.indicator.indicatorPaths.forEach(indicatorPath => {
706
        this.addNumberIndicatorPath(this.statisticsService.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)), indicatorPath.parameters, indicatorPath.source, this.getJsonPathAsFormArray(indicatorPath));
707
      });
708
    } else {
709
      this.indicator = new Indicator('', '', '', 'number', 'small', 'small', "PUBLIC", []);
710
      this.numberIndicatorFb = this.fb.group({
711
        _id: this.fb.control(this.indicator._id),
712
        name: this.fb.control(this.indicator.name, Validators.required),
713
        description: this.fb.control(this.indicator.description),
714
        additionalDescription: this.fb.control(this.indicator.additionalDescription),
715
        visibility: this.fb.control(this.indicator.visibility),
716
        indicatorPaths: this.fb.array([], Validators.required),
717
        type: this.fb.control(this.indicator.type),
718
        width: this.fb.control(this.indicator.width),
719
        height: this.fb.control(this.indicator.height),
720
        defaultId: this.fb.control(this.indicator.defaultId)
721
      });
722
      this.addNumberIndicatorPath();
723
    }
724
    if (this.indicator.defaultId) {
725
      setTimeout(() => {
726
        this.numberIndicatorFb.get('description').disable();
727
      }, 0);
728
    }
729
    this.editNumberModal.cancelButtonText = 'Cancel';
730
    this.editNumberModal.okButtonLeft = false;
731
    this.editNumberModal.alertMessage = false;
732
    if (this.index === -1) {
733
      this.editNumberModal.alertTitle = 'Create a new number indicator';
734
      this.editNumberModal.okButtonText = 'Save';
735
    } else {
736
      this.editNumberModal.alertTitle = 'Edit number indicator\'s information';
737
      this.editNumberModal.okButtonText = 'Save Changes';
738
    }
739
    this.editNumberModal.open();
740
  }
741
  
742
  public editChartIndicatorOpen(section: Section, id = null) {
743
    this.urlParameterizedMessage = null;
744
    this.urlSubscriptions.forEach(value => {
745
      if (value instanceof Subscriber) {
746
        value.unsubscribe();
747
      }
748
    });
749
    this.section = section;
750
    this.index = (id) ? section.indicators.findIndex(value => value._id === id) : -1;
751
    if (this.index !== -1) {
752
      this.indicator = HelperFunctions.copy(this.section.indicators[this.index]);
753
      this.chartIndicatorFb = this.fb.group({
754
        _id: this.fb.control(this.indicator._id),
755
        name: this.fb.control(this.indicator.name),
756
        creationDate: this.fb.control(this.indicator.creationDate),
757
        description: this.fb.control(this.indicator.description),
758
        additionalDescription: this.fb.control(this.indicator.additionalDescription),
759
        visibility: this.fb.control(this.indicator.visibility),
760
        indicatorPaths: this.fb.array([]),
761
        width: this.fb.control(this.indicator.width),
762
        height: this.fb.control(this.indicator.height),
763
        defaultId: this.fb.control(this.indicator.defaultId)
764
      });
765
      this.indicator.indicatorPaths.forEach(indicatorPath => {
766
        this.addChartIndicatorPath(this.getUrlByStakeHolder(indicatorPath),
767
          this.getParametersAsFormArray(indicatorPath), this.indicator.defaultId !== null, indicatorPath.type);
768
        indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath);
769
      });
770
    } else {
771
      this.indicator = new Indicator('', '', '', 'chart', 'medium', 'medium', "PUBLIC", []);
772
      this.chartIndicatorFb = this.fb.group({
773
        _id: this.fb.control(this.indicator._id),
774
        name: this.fb.control(this.indicator.name),
775
        description: this.fb.control(this.indicator.description),
776
        additionalDescription: this.fb.control(this.indicator.additionalDescription),
777
        visibility: this.fb.control(this.indicator.visibility),
778
        indicatorPaths: this.fb.array([]),
779
        width: this.fb.control(this.indicator.width, Validators.required),
780
        height: this.fb.control(this.indicator.height, Validators.required),
781
        defaultId: this.fb.control(this.indicator.defaultId)
782
      });
783
      this.addChartIndicatorPath();
784
    }
785
    if (this.indicator.defaultId) {
786
      setTimeout(() => {
787
        this.chartIndicatorFb.get('description').disable();
788
      }, 0);
789
    }
790
    this.editChartModal.cancelButtonText = 'Cancel';
791
    this.editChartModal.okButtonLeft = false;
792
    this.editChartModal.alertMessage = false;
793
    if (this.index === -1) {
794
      this.editChartModal.alertTitle = 'Create a new chart indicator';
795
      this.editChartModal.okButtonText = 'Save';
796
    } else {
797
      this.editChartModal.alertTitle = 'Edit chart indicator\'s information';
798
      this.editChartModal.okButtonText = 'Save Changes';
799
    }
800
    this.editChartModal.open();
801
  }
802
  
803
  saveIndicator() {
804
    this.editing = true;
805
    if (this.indicator.type === 'chart') {
806
      this.chartIndicatorFb.get('description').enable();
807
      this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, this.indicator.type, true);
808
      this.section = this.charts.find(section => section._id === this.section._id);
809
    } else {
810
      this.numberIndicatorFb.get('description').enable();
811
      this.indicator = this.indicatorUtils.generateIndicatorByForm(this.numberIndicatorFb.value, this.indicator.indicatorPaths, this.indicator.type, false);
812
      this.section = this.numbers.find(section => section._id === this.section._id);
813
    }
814
    let path = [
815
      this.stakeholder._id,
816
      this.stakeholder.topics[this.topicIndex]._id,
817
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id,
818
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id,
819
      this.section._id
820
    ];
821
    this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, this.indicator, path).subscribe(indicator => {
822
      if (this.index !== -1) {
823
        this.section.indicators[this.index] = indicator;
824
      } else {
825
        this.section.indicators.push(indicator);
826
      }
827
      if (this.indicator.type === "chart") {
828
        this.filterCharts();
829
        this.chartIndicatorFb = null;
830
      } else {
831
        this.filterNumbers();
832
        this.numberIndicatorFb = null;
833
      }
834
      UIkit.notification('Indicator has been <b>successfully saved</b>', {
835
        status: 'success',
836
        timeout: 6000,
837
        pos: 'bottom-right'
838
      });
839
      this.editing = false;
840
    }, error => {
841
      this.chartIndicatorFb = null;
842
      UIkit.notification(error.error.message, {
843
        status: 'danger',
844
        timeout: 6000,
845
        pos: 'bottom-right'
846
      });
847
      this.editing = false;
848
    }));
849
  }
850
  
851
  reorderIndicators(sectionId: string, type: IndicatorType, reorder: Reorder) {
852
    this.editing = true;
853
    let path = [
854
      this.stakeholder._id,
855
      this.stakeholder.topics[this.topicIndex]._id,
856
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id,
857
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id,
858
      sectionId
859
    ];
860
    this.subscriptions.push(this.stakeholderService.reorderIndicators(this.properties.monitorServiceAPIURL, path, reorder, type).subscribe(indicators => {
861
      if (type === 'chart') {
862
        this.charts.find(section => section._id === sectionId).indicators = indicators;
863
        this.filterCharts();
864
      } else {
865
        this.numbers.find(section => section._id === sectionId).indicators = indicators;
866
        this.filterNumbers();
867
      }
868
      this.editing = false;
869
    }));
870
  }
871
  
872
  hasDifference(index: number): boolean {
873
    let hasDifference = false;
874
    this.chartIndicatorPaths.at(index).value.parameters.forEach((parameter) => {
875
      if (parameter.value !== this.indicator.indicatorPaths[index].parameters[parameter.key]) {
876
        hasDifference = true;
877
        return;
878
      }
879
    });
880
    return hasDifference || this.indicator.indicatorPaths[index].safeResourceUrl.toString() !==
881
      this.getSecureUrlByStakeHolder(this.indicator.indicatorPaths[index]).toString();
882
  }
883
  
884
  public get isAdministrator(): boolean {
885
    return Session.isPortalAdministrator(this.user);
886
  }
887
  
888
  public get isCurator(): boolean {
889
    return this.isAdministrator || Session.isMonitorCurator(this.user);
890
  }
891
  
892
  refreshIndicator() {
893
    this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, 'chart', true);
894
    this.indicator.indicatorPaths.forEach(indicatorPath => {
895
      indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath);
896
    });
897
  }
898
  
899
  deleteIndicatorOpen(section: Section, indicatorId: string, type: string, childrenAction: string = null) {
900
    this.indicatorChildrenActionOnDelete = null;
901
    if (childrenAction == "delete") {
902
      this.indicatorChildrenActionOnDelete = childrenAction;
903
    } else if (childrenAction == "disconnect") {
904
      this.indicatorChildrenActionOnDelete = childrenAction;
905
    }
906
    
907
    this.section = section;
908
    if (type === 'chart') {
909
      this.index = this.charts.find(value => value._id == section._id).indicators.findIndex(value => value._id == indicatorId);
910
    } else {
911
      this.index = this.numbers.find(value => value._id == section._id).indicators.findIndex(value => value._id == indicatorId);
912
    }
913
    this.indicator = section.indicators.find(value => value._id == indicatorId);
914
    this.deleteModal.alertTitle = 'Delete indicator';
915
    this.deleteModal.cancelButtonText = 'No';
916
    this.deleteModal.okButtonText = 'Yes';
917
    this.deleteModal.open();
918
  }
919
  
920
  deleteIndicator() {
921
    this.editing = true;
922
    let path = [
923
      this.stakeholder._id,
924
      this.stakeholder.topics[this.topicIndex]._id,
925
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id,
926
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id,
927
      this.section._id,
928
      this.indicator._id
929
    ];
930
    this.subscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.indicatorChildrenActionOnDelete).subscribe(() => {
931
      if (this.indicator.type === 'chart') {
932
        this.charts.find(section => section._id === this.section._id).indicators.splice(this.index, 1);
933
        this.filterCharts();
934
      } else {
935
        this.numbers.find(section => section._id === this.section._id).indicators.splice(this.index, 1);
936
        this.filterNumbers();
937
      }
938
      UIkit.notification('Indicator has been <b>successfully deleted</b>', {
939
        status: 'success',
940
        timeout: 6000,
941
        pos: 'bottom-right'
942
      });
943
      this.editing = false;
944
    }, error => {
945
      UIkit.notification(error.error.message, {
946
        status: 'danger',
947
        timeout: 6000,
948
        pos: 'bottom-right'
949
      });
950
      this.editing = false;
951
    }));
952
  }
953
  
954
  changeIndicatorStatus(sectionId: string, indicator: Indicator, visibility: Visibility) {
955
    this.editing = true;
956
    let path = [
957
      this.stakeholder._id,
958
      this.stakeholder.topics[this.topicIndex]._id,
959
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id,
960
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id,
961
      sectionId,
962
      indicator._id
963
    ];
964
    this.subscriptions.push(this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => {
965
      indicator.visibility = visibility;
966
      UIkit.notification('Indicator has been <b>successfully changed</b> to ' + indicator.visibility.toLowerCase(), {
967
        status: 'success',
968
        timeout: 6000,
969
        pos: 'bottom-right'
970
      });
971
      this.editing = false;
972
    }, error => {
973
      UIkit.notification('An error has been occurred. Try again later', {
974
        status: 'danger',
975
        timeout: 6000,
976
        pos: 'bottom-right'
977
      });
978
      this.editing = false;
979
    }));
980
  }
981
  
982
  saveSection(section: Section, index: number, type: IndicatorType = "chart") {
983
    this.editing = true;
984
    let path = [
985
      this.stakeholder._id,
986
      this.stakeholder.topics[this.topicIndex]._id,
987
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id,
988
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id
989
    ];
990
    this.subscriptions.push(this.stakeholderService.saveSection(this.properties.monitorServiceAPIURL, section, path, index).subscribe(section => {
991
      if (type === 'chart') {
992
        this.charts[index] = section;
993
        this.filterCharts();
994
      } else {
995
        this.numbers[index] = section;
996
        this.filterNumbers();
997
      }
998
      this.initReorder();
999
      UIkit.notification('Section has been <b>successfully saved</b>', {
1000
        status: 'success',
1001
        timeout: 6000,
1002
        pos: 'bottom-right'
1003
      });
1004
      this.editing = false;
1005
    }, error => {
1006
      UIkit.notification(error.error.message, {
1007
        status: 'danger',
1008
        timeout: 6000,
1009
        pos: 'bottom-right'
1010
      });
1011
      this.editing = false;
1012
    }));
1013
  }
1014
  
1015
  createSection(index = -1, type: IndicatorType = 'chart') {
1016
    this.editing = true;
1017
    this.section = new Section(type, null, null, this.stakeholder.alias);
1018
    let path = [
1019
      this.stakeholder._id,
1020
      this.stakeholder.topics[this.topicIndex]._id,
1021
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id,
1022
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id
1023
    ];
1024
    this.subscriptions.push(this.stakeholderService.saveSection(this.properties.monitorServiceAPIURL, this.section, path, index).subscribe(section => {
1025
      if (type === 'chart') {
1026
        if (index !== -1) {
1027
          this.charts.splice(index, 0, section);
1028
        } else {
1029
          this.charts.push(section);
1030
        }
1031
        this.filterCharts();
1032
      } else {
1033
        if (index !== -1) {
1034
          this.numbers.splice(index, 0, section);
1035
        } else {
1036
          this.numbers.push(section);
1037
        }
1038
        this.filterNumbers();
1039
      }
1040
      this.initReorder();
1041
      UIkit.notification('Section has been <b>successfully created</b>', {
1042
        status: 'success',
1043
        timeout: 6000,
1044
        pos: 'bottom-right'
1045
      });
1046
      this.editing = false;
1047
    }, error => {
1048
      UIkit.notification(error.error.message, {
1049
        status: 'danger',
1050
        timeout: 6000,
1051
        pos: 'bottom-right'
1052
      });
1053
      this.editing = false;
1054
    }));
1055
  }
1056
  
1057
  // deleteNumberSectionOpen(section: Section, index: number) {
1058
  //   this.section = section;
1059
  //   this.index = index;
1060
  //   this.deleteNumberSectionModal.alertTitle = 'Delete Section';
1061
  //   this.deleteNumberSectionModal.cancelButtonText = 'No';
1062
  //   this.deleteNumberSectionModal.okButtonText = 'Yes';
1063
  //   this.deleteNumberSectionModal.open();
1064
  // }
1065
  //
1066
  // deleteChartSectionOpen(section: Section, index: number) {
1067
  //   this.section = section;
1068
  //   this.index = index;
1069
  //   this.deleteChartSectionModal.alertTitle = 'Delete Section';
1070
  //   this.deleteChartSectionModal.cancelButtonText = 'No';
1071
  //   this.deleteChartSectionModal.okButtonText = 'Yes';
1072
  //   this.deleteChartSectionModal.open();
1073
  // }
1074
  
1075
  deleteSectionOpen(section: Section, index: number, type: IndicatorType, childrenAction: string = null) {
1076
    if (!this.editing && !section.defaultId) {
1077
      this.sectionTypeToDelete = type;
1078
      this.sectionChildrenActionOnDelete = null;
1079
      if (childrenAction == "delete") {
1080
        this.sectionChildrenActionOnDelete = childrenAction;
1081
      } else if (childrenAction == "disconnect") {
1082
        this.sectionChildrenActionOnDelete = childrenAction;
1083
      }
1084
      
1085
      this.section = section;
1086
      this.index = index;
1087
      this.deleteSectionModal.alertTitle = 'Delete Section';
1088
      this.deleteSectionModal.cancelButtonText = 'No';
1089
      this.deleteSectionModal.okButtonText = 'Yes';
1090
      this.deleteSectionModal.open();
1091
    }
1092
  }
1093
  
1094
  deleteSection() {
1095
    this.editing = true;
1096
    let path = [
1097
      this.stakeholder._id,
1098
      this.stakeholder.topics[this.topicIndex]._id,
1099
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id,
1100
      this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id,
1101
      this.section._id
1102
    ];
1103
    this.subscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.sectionChildrenActionOnDelete).subscribe(() => {
1104
      if (this.sectionTypeToDelete === "chart") {
1105
        this.charts.splice(this.index, 1);
1106
        this.filterCharts();
1107
      } else {
1108
        this.numbers.splice(this.index, 1);
1109
        this.filterNumbers();
1110
      }
1111
      this.initReorder();
1112
      UIkit.notification('Section has been <b>successfully deleted</b>', {
1113
        status: 'success',
1114
        timeout: 6000,
1115
        pos: 'bottom-right'
1116
      });
1117
      this.editing = false;
1118
    }, error => {
1119
      UIkit.notification(error.error.message, {
1120
        status: 'danger',
1121
        timeout: 6000,
1122
        pos: 'bottom-right'
1123
      });
1124
      this.editing = false;
1125
    }));
1126
  }
1127
}
(3-3/7)