Project

General

Profile

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