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 {Role, Session, User} 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
import {Notification} from "../openaireLibrary/notifications/notifications";
35
import {NotificationUtils} from "../openaireLibrary/notifications/notification-utils";
36
import {NotifyFormComponent} from "../openaireLibrary/notifications/notify-form/notify-form.component";
37

    
38
declare var UIkit;
39

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

    
1190
}
(3-3/7)