import { AfterViewInit, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild } from "@angular/core"; import { Indicator, IndicatorPath, IndicatorType, Section, Stakeholder, Visibility } from "../openaireLibrary/monitor/entities/stakeholder"; import {IndicatorUtils, StakeholderUtils} from "../utils/indicator-utils"; import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; import {AlertModal} from "../openaireLibrary/utils/modal/alert"; import {StatisticsService} from "../utils/services/statistics.service"; import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class"; import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser"; import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service"; import {EnvProperties} from "../openaireLibrary/utils/properties/env-properties"; import {Subscriber} from "rxjs"; import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service"; import {Router} from "@angular/router"; import {Session} from "../openaireLibrary/login/utils/helper.class"; import {UserManagementService} from "../openaireLibrary/services/user-management.service"; declare var UIkit; @Component({ selector: 'indicators', templateUrl: './indicators.component.html', styleUrls: ['indicators.component.css'] }) export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit { @Input() public properties: EnvProperties = null; @Input() public topicIndex: number = 0; @Input() public categoryIndex: number = 0; @Input() public subcategoryIndex: number = 0; public stakeholder: Stakeholder = null; public user = null; public preview: string; public indicatorUtils: IndicatorUtils = new IndicatorUtils(); public stakeholderUtils: StakeholderUtils = new StakeholderUtils(); public numberIndicatorFb: FormGroup; public chartIndicatorFb: FormGroup; public chartSections: FormArray; public numberSections: FormArray; /** * Editable indicator */ public section: Section; public indicator: Indicator; public index: number = -1; /** * Displayed chart and numbers base on Top filters */ public displayCharts: Section[] = []; public displayNumbers: Section[] = []; /** * Top filters */ @Input() public filters: FormGroup; /** * Toggles */ // public grid: boolean = true; public editing: boolean = false; /** Safe Urls*/ public safeUrls: Map = new Map([]); public numberResults: Map = new Map(); private subscriptions: any[] = []; private urlSubscriptions: any[] = []; @ViewChild('editChartModal') editChartModal: AlertModal; @ViewChild('editNumberModal') editNumberModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal; //@ViewChild('deleteAllModal') deleteAllModal: AlertModal; //@ViewChild('deleteAndDisconnectModal') deleteAndDisconnectModal: AlertModal; //@ViewChild('deleteChartSectionModal') deleteChartSectionModal: AlertModal; //@ViewChild('deleteNumberSectionModal') deleteNumberSectionModal: AlertModal; @ViewChild('deleteSectionModal') deleteSectionModal: AlertModal; public sectionTypeToDelete: string; public sectionChildrenActionOnDelete: string; public indicatorChildrenActionOnDelete: string; urlParameterizedMessage = ""; constructor(private layoutService: LayoutService, private stakeholderService: StakeholderService, private statisticsService: StatisticsService, private userManagementService: UserManagementService, private fb: FormBuilder, private router: Router, private cdr: ChangeDetectorRef, private sanitizer: DomSanitizer) { } ngOnInit(): void { this.userManagementService.getUserInfo().subscribe(user => { this.user = user; }); this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => { this.stakeholder = stakeholder; if (this.stakeholder) { this.buildFilters(); this.buildSections(); this.filterCharts(); this.filterNumbers(); this.setPreview(); } }); } ngOnDestroy(): void { this.subscriptions.forEach(value => { if (value instanceof Subscriber) { value.unsubscribe(); } else if (value instanceof Function) { value(); } }); } ngAfterViewInit(): void { this.initReorder(); } ngOnChanges(changes: SimpleChanges): void { if (this.canEdit) { if (changes.topicIndex || changes.categoryIndex || changes.subcategoryIndex) { this.buildFilters(); this.initReorder(); } this.filterCharts(); this.filterNumbers(); } this.setPreview(); } setNumberIndicators() { this.numberResults.clear(); let urls: Map = new Map(); this.numbers.forEach((section, i) => { section.indicators.forEach((number, j) => { let url = this.indicatorUtils.getFullUrlWithFilters(this.stakeholder, number.indicatorPaths[0]); const pair = JSON.stringify([number.indicatorPaths[0].source, url]); const indexes = urls.get(pair) ? urls.get(pair) : []; indexes.push([i, j]); urls.set(pair, indexes); }); }); urls.forEach((indexes, pair) => { pair = JSON.parse(pair); this.statisticsService.getNumbers(this.statisticsService.getSourceType(pair[0]), pair[1]).subscribe(response => { indexes.forEach(([i, j]) => { let result = JSON.parse(JSON.stringify(response)); this.numbers[i].indicators[j].indicatorPaths[0].jsonPath.forEach(jsonPath => { if (result) { result = result[jsonPath]; } }); if (typeof result == 'string' || typeof result == 'number') { this.numberResults.set(i + '-' + j, Number(result)); } }); }); }); } setPreview() { if (this.stakeholder) { this.preview = '/' + this.stakeholder.alias; if (this.stakeholder.topics[this.topicIndex]) { this.preview = '/' + this.stakeholder.alias + '/' + this.stakeholder.topics[this.topicIndex].alias; if (this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]) { this.preview += '/' + this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].alias; if (this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]) { this.preview += '/' + this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].alias; } } } } } initReorder() { this.subscriptions.forEach(value => { if (value instanceof Function) { value(); } }); if (document !== undefined) { let callback = (list, type: IndicatorType): void => { let items: HTMLCollection = list.current.children; let reordered = []; for (let i = 0; i < items.length; i++) { if (items.item(i).id) { reordered.push(items.item(i).id); } } this.reorderIndicators(list.current.id.toString().split('-')[1], type, reordered); }; this.numbers.forEach((section) => { this.subscriptions.push(UIkit.util.on(document, 'moved', '#number-' + section._id, (list): void => { callback(list, "number"); })); this.subscriptions.push(UIkit.util.on(document, 'added', '#number-' + section._id, (list): void => { callback(list, "number"); })); this.subscriptions.push(UIkit.util.on(document, 'removed', '#number-' + section._id, (list): void => { callback(list, "number"); })); }); this.charts.forEach((section) => { this.subscriptions.push(UIkit.util.on(document, 'moved', '#chart-' + section._id, (list): void => { callback(list, "chart"); })); this.subscriptions.push(UIkit.util.on(document, 'added', '#chart-' + section._id, (list): void => { callback(list, "chart"); })); this.subscriptions.push(UIkit.util.on(document, 'removed', '#chart-' + section._id, (list): void => { callback(list, "chart"); })); }); } } hide(element: any) { UIkit.dropdown(element).hide(); } private buildFilters() { this.subscriptions.push(this.filters.get('chartType').valueChanges.subscribe(value => { this.onChartTypeChange(value); })); this.subscriptions.push(this.filters.get('status').valueChanges.subscribe(value => { this.onStatusChange(value); })); this.subscriptions.push(this.filters.get('keyword').valueChanges.subscribe(value => { this.onKeywordChange(value); })); } private buildSections() { this.numberSections = this.fb.array([]); this.numbers.forEach(section => { this.numberSections.push(this.fb.group({ _id: this.fb.control(section._id), title: this.fb.control(section.title), stakeholderAlias: this.fb.control(section.stakeholderAlias), defaultId: this.fb.control(section.defaultId), type: this.fb.control(section.type), indicators: this.fb.control(section.indicators) })); }); this.chartSections = this.fb.array([]); this.charts.forEach(section => { this.chartSections.push(this.fb.group({ _id: this.fb.control(section._id), title: this.fb.control(section.title), stakeholderAlias: this.fb.control(section.stakeholderAlias), defaultId: this.fb.control(section.defaultId), type: this.fb.control(section.type), indicators: this.fb.control(section.indicators) })); }); } filterCharts() { this.displayCharts = this.filterChartType( this.filterStatus(this.filterByKeyword(HelperFunctions.copy(this.charts), this.filters.value.keyword), this.filters.value.status), this.filters.value.chartType ); this.displayCharts.forEach(section => { section.indicators.forEach(indicator => { indicator.indicatorPaths.forEach(indicatorPath => { let url = this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath); if (!this.safeUrls.get('url')) { indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); this.safeUrls.set(url, indicatorPath.safeResourceUrl); } }); }) }); this.buildSections(); } filterNumbers() { this.displayNumbers = this.filterStatus( this.filterByKeyword(HelperFunctions.copy(this.numbers), this.filters.value.keyword), this.filters.value.status); this.buildSections(); this.setNumberIndicators(); } onChartTypeChange(value) { this.displayCharts = this.filterChartType(HelperFunctions.copy(this.charts), value); } onStatusChange(value) { this.displayCharts = this.filterStatus(HelperFunctions.copy(this.charts), value); this.displayNumbers = this.filterStatus(HelperFunctions.copy(this.numbers), value); } onKeywordChange(value) { this.displayCharts = this.filterByKeyword(HelperFunctions.copy(this.charts), value); this.displayNumbers = this.filterByKeyword(HelperFunctions.copy(this.numbers), value); } private filterChartType(sections: Section[], value): Section[] { if (value !== 'all') { sections.forEach(section => section.indicators = section.indicators.filter(indicator => indicator.indicatorPaths.filter(indicatorPath => indicatorPath.type === value).length > 0)); } return sections; } private filterStatus(sections: Section[], value): Section[] { if (value !== 'all') { sections.forEach(section => section.indicators = section.indicators.filter(indicator => indicator.visibility === value)); } return sections; } private filterByKeyword(sections: Section[], value): Section[] { if (value !== null && value !== '') { sections.forEach(section => section.indicators = section.indicators.filter(indicator => (indicator.name && indicator.name.toLowerCase().includes(value.toLowerCase())) || (indicator.description && indicator.description.toLowerCase().includes(value.toLowerCase())) || (indicator.additionalDescription && indicator.additionalDescription.toLowerCase().includes(value.toLowerCase())) || indicator.indicatorPaths.filter(indicatorPath => (indicatorPath.parameters && indicatorPath.parameters.title && indicatorPath.parameters.title.includes(value.toLowerCase()))).length > 0)); } return sections; } get charts(): Section[] { if (this.stakeholder.topics[this.topicIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]) { return this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].charts; } else { return []; } } set charts(sections: Section[]) { this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].charts = sections; } get numbers(): Section[] { if (this.stakeholder.topics[this.topicIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]) { return this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].numbers; } else { return []; } } set numbers(sections: Section[]) { this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].numbers = sections; } get open(): boolean { return this.layoutService.open; } get canReorder(): boolean { return this.filters.value.chartType === 'all' && this.filters.value.status === 'all' && this.filters.value.keyword === '' && !this.editing; } get canEdit() { return this.stakeholder && this.stakeholder.topics[this.topicIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex] && this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]; } public get numberIndicatorPaths(): FormArray { return this.numberIndicatorFb.get('indicatorPaths') as FormArray; } public get chartIndicatorPaths(): FormArray { return this.chartIndicatorFb.get('indicatorPaths') as FormArray; } public addJsonPath(index: number) { if (index == 0 && this.getJsonPath(index).getRawValue()[index].indexOf(",") != -1) { //if in the first path there are more than one paaths comma separated, split them and autogenerate the forms let paths = this.getJsonPath(index).getRawValue()[index].split(","); for (let i = 0; i < paths.length; i++) { if (i != 0) { this.getJsonPath(index).push(this.fb.control('', Validators.required)); } } this.getJsonPath(index).setValue(paths) return; } this.getJsonPath(index).push(this.fb.control('', Validators.required)); } public removeJsonPath(i: number, j: number) { this.getJsonPath(i).removeAt(j); if (this.getJsonPath(i).length !== this.getCurrentJsonPath(i).length) { this.getJsonPath(i).markAsDirty(); } } public validateJsonPath(index: number) { let indicatorPath: FormGroup = this.numberIndicatorPaths.at(index); this.getJsonPath(index).disable(); this.statisticsService.getNumbers(null, indicatorPath.get('url').value).subscribe(response => { let result = JSON.parse(JSON.stringify(response)); this.getJsonPath(index).controls.forEach(jsonPath => { if (result) { result = result[jsonPath.value]; } }); setTimeout( () => { if (typeof result == 'string') { this.getJsonPath(index).enable(); this.getJsonPath(index).setErrors(null); } else { this.getJsonPath(index).enable(); this.getJsonPath(index).setErrors({invalid: true}); } }, 1000); }); } public getJsonPath(index: number): FormArray { return this.numberIndicatorPaths.at(index).get('jsonPath') as FormArray; } public getCurrentJsonPath(index: number): string[] { return this.section.indicators[this.index].indicatorPaths[index].jsonPath; } public getParameters(index: number): FormArray { return this.chartIndicatorPaths.at(index).get('parameters') as FormArray; } public getParameter(index: number, key: string): FormControl { return this.getParameters(index).controls.filter(control => control.value.key === key)[0] as FormControl; } private getSecureUrlByStakeHolder(indicatorPath: IndicatorPath) { return this.sanitizer.bypassSecurityTrustResourceUrl( this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath))); } private getUrlByStakeHolder(indicatorPath: IndicatorPath) { return this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)); } public addNumberIndicatorPath(url: string = '', parameters: FormArray = new FormArray([]), source: string = 'search', jsonPath: FormArray = new FormArray([])) { if (jsonPath.length === 0) { jsonPath.push(this.fb.control('', Validators.required)); } this.numberIndicatorPaths.push(this.fb.group({ url: this.fb.control(url, Validators.required), jsonPath: jsonPath, // parameters: parameters, source: this.fb.control(source, Validators.required) } )); for (let index = 0; index < this.numberIndicatorPaths.length; index++) { this.subscriptions.push(this.numberIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => { if (this.numberIndicatorPaths.at(index).get('url').valid) { let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByNumberUrl(this.statisticsService.getNumberSource(value), value, this.stakeholder, this.numberIndicatorPaths.at(index).get('jsonPath').value); 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) || (!indicatorPath.chartObject && indicatorPath.url.indexOf("index_id") == -1 && indicatorPath.url.indexOf("index_name") == -1 && (indicatorPath.url).indexOf("index_shortName") == -1)) { // default profile if (this.stakeholder.defaultId == null) { this.urlParameterizedMessage = "This indicator couldn't be generated properly. Stakeholders based on this profile may not inherit the data correctly." } else { this.urlParameterizedMessage = "This indicator couldn't be generated properly. Please make sure chart data is for the current stakeholder." } } else { this.urlParameterizedMessage = ""; } /* if(value != indicatorPath.url) { (this.numberIndicatorPaths.at(index) as FormGroup).get('url').setValue( indicatorPath.url); }*/ this.indicator.indicatorPaths[index] = indicatorPath; (this.numberIndicatorPaths.at(index) as FormGroup).get('source').setValue(indicatorPath.source); } }) ); this.subscriptions.push(this.numberIndicatorPaths.at(index).get('jsonPath').valueChanges.subscribe(value => { this.indicator.indicatorPaths[index].jsonPath = value; //this.getJsonPath(index).setErrors({invalid: true}); }) ); this.subscriptions.push(this.numberIndicatorPaths.at(index).get('source').valueChanges.subscribe(value => { this.indicator.indicatorPaths[index].source = value; }) ); } } public addChartIndicatorPath(value: string = '', parameters: FormArray = new FormArray([]), disableUrl: boolean = false, type: string = null) { this.chartIndicatorPaths.push(this.fb.group({ url: this.fb.control(value, [Validators.required, Validators.pattern('https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.' + '[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.' + '[a-zA-Z0-9]+\.[^\s]{2,}')]), parameters: parameters, type: this.fb.control(type) } )); if (disableUrl) { for (let index = 0; index < this.chartIndicatorPaths.length; index++) { this.chartIndicatorPaths.at(index).get('url').disable(); } } else { for (let index = 0; index < this.chartIndicatorPaths.length; index++) { this.urlSubscriptions.push(this.chartIndicatorPaths.at(index).get('url').valueChanges.subscribe(value => { if (this.chartIndicatorPaths.at(index).get('url').valid) { let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.statisticsService.getChartSource(value), value, this.chartIndicatorPaths.at(index).get('type').value, this.stakeholder); 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) { // default profile if (this.stakeholder.defaultId == null) { this.urlParameterizedMessage = "This chart couldn't be generated properly. Stakeholders based on this profile may not inherit the data correctly." } else { this.urlParameterizedMessage = "This chart couldn't be generated properly. Please make sure chart data is for the current stakeholder." } } else { this.urlParameterizedMessage = ""; } (this.chartIndicatorPaths.at(index) as FormGroup).get('type').setValue(indicatorPath.type); let parameters = this.getParametersAsFormArray(indicatorPath); (this.chartIndicatorPaths.at(index) as FormGroup).setControl('parameters', parameters); if (!this.indicator.indicatorPaths[index]) { this.indicator.indicatorPaths[index] = indicatorPath; this.indicator.indicatorPaths[index].safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); } else { indicatorPath.safeResourceUrl = this.indicator.indicatorPaths[index].safeResourceUrl; this.indicator.indicatorPaths[index] = indicatorPath; } } }) ); } } } private getJsonPathAsFormArray(indicatorPath: IndicatorPath): FormArray { let jsonPath = this.fb.array([]); if (indicatorPath.jsonPath) { indicatorPath.jsonPath.forEach(path => { jsonPath.push(this.fb.control(path, Validators.required)); }); } return jsonPath; } private getParametersAsFormArray(indicatorPath: IndicatorPath): FormArray { let parameters = this.fb.array([]); if (indicatorPath.parameters) { Object.keys(indicatorPath.parameters).forEach(key => { if (this.indicatorUtils.ignoredParameters.indexOf(key) === -1) { if (this.indicatorUtils.parametersValidators.has(key)) { parameters.push(this.fb.group({ key: this.fb.control(key), value: this.fb.control(indicatorPath.parameters[key], this.indicatorUtils.parametersValidators.get(key)) })); } else { parameters.push(this.fb.group({ key: this.fb.control(key), value: this.fb.control(indicatorPath.parameters[key]) })); } } }); } return parameters; } public editNumberIndicatorOpen(section: Section, id = null) { this.urlParameterizedMessage = ""; this.section = section; this.index = (id) ? section.indicators.findIndex(value => value._id === id) : -1; if (this.index !== -1) { this.indicator = HelperFunctions.copy(this.section.indicators[this.index]); this.numberIndicatorFb = this.fb.group({ _id: this.fb.control(this.indicator._id), name: this.fb.control(this.indicator.name, Validators.required), description: this.fb.control(this.indicator.description), additionalDescription: this.fb.control(this.indicator.additionalDescription), visibility: this.fb.control(this.indicator.visibility), indicatorPaths: this.fb.array([], Validators.required), type: this.fb.control(this.indicator.type), width: this.fb.control(this.indicator.width), defaultId: this.fb.control(this.indicator.defaultId) }); this.indicator.indicatorPaths.forEach(indicatorPath => { this.addNumberIndicatorPath(this.statisticsService.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)), indicatorPath.parameters, indicatorPath.source, this.getJsonPathAsFormArray(indicatorPath)); }); } else { this.indicator = new Indicator('', '', '', 'number', 'small', "PUBLIC", []); this.numberIndicatorFb = this.fb.group({ _id: this.fb.control(this.indicator._id), name: this.fb.control(this.indicator.name, Validators.required), description: this.fb.control(this.indicator.description), additionalDescription: this.fb.control(this.indicator.additionalDescription), visibility: this.fb.control(this.indicator.visibility), indicatorPaths: this.fb.array([], Validators.required), type: this.fb.control(this.indicator.type), width: this.fb.control(this.indicator.width), defaultId: this.fb.control(this.indicator.defaultId) }); this.addNumberIndicatorPath(); } if(this.indicator.defaultId) { setTimeout(() => { this.numberIndicatorFb.get('additionalDescription').disable(); }, 0); } this.editNumberModal.cancelButtonText = 'Cancel'; this.editNumberModal.okButtonLeft = false; this.editNumberModal.alertMessage = false; if (this.index === -1) { this.editNumberModal.alertTitle = 'Create a new number indicator'; this.editNumberModal.okButtonText = 'Save'; } else { this.editNumberModal.alertTitle = 'Edit number indicator\'s information'; this.editNumberModal.okButtonText = 'Save Changes'; } this.editNumberModal.open(); } public editChartIndicatorOpen(section: Section, id = null) { this.urlParameterizedMessage = ""; this.urlSubscriptions.forEach(value => { if (value instanceof Subscriber) { value.unsubscribe(); } }); this.section = section; this.index = (id) ? section.indicators.findIndex(value => value._id === id) : -1; if (this.index !== -1) { this.indicator = HelperFunctions.copy(this.section.indicators[this.index]); this.chartIndicatorFb = this.fb.group({ _id: this.fb.control(this.indicator._id), name: this.fb.control(this.indicator.name), description: this.fb.control(this.indicator.description), additionalDescription: this.fb.control(this.indicator.additionalDescription), visibility: this.fb.control(this.indicator.visibility), indicatorPaths: this.fb.array([]), width: this.fb.control(this.indicator.width), defaultId: this.fb.control(this.indicator.defaultId) }); this.indicator.indicatorPaths.forEach(indicatorPath => { this.addChartIndicatorPath(this.getUrlByStakeHolder(indicatorPath), this.getParametersAsFormArray(indicatorPath), this.indicator.defaultId !== null, indicatorPath.type); indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); }); } else { this.indicator = new Indicator('', '', '', 'chart', 'medium', "PUBLIC", []); this.chartIndicatorFb = this.fb.group({ _id: this.fb.control(this.indicator._id), name: this.fb.control(this.indicator.name), description: this.fb.control(this.indicator.description), additionalDescription: this.fb.control(this.indicator.additionalDescription), visibility: this.fb.control(this.indicator.visibility), indicatorPaths: this.fb.array([]), width: this.fb.control(this.indicator.width, Validators.required), defaultId: this.fb.control(this.indicator.defaultId) }); this.addChartIndicatorPath(); } if(this.indicator.defaultId) { setTimeout(() => { this.chartIndicatorFb.get('additionalDescription').disable(); }, 0); } this.editChartModal.cancelButtonText = 'Cancel'; this.editChartModal.okButtonLeft = false; this.editChartModal.alertMessage = false; if (this.index === -1) { this.editChartModal.alertTitle = 'Create a new chart indicator'; this.editChartModal.okButtonText = 'Save'; } else { this.editChartModal.alertTitle = 'Edit chart indicator\'s information'; this.editChartModal.okButtonText = 'Save Changes'; } this.editChartModal.open(); } saveIndicator() { this.editing = true; if (this.indicator.type === 'chart') { this.chartIndicatorFb.get('additionalDescription').enable(); this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, this.indicator.type, true); this.section = this.charts.find(section => section._id === this.section._id); } else { this.numberIndicatorFb.get('additionalDescription').enable(); this.indicator = this.indicatorUtils.generateIndicatorByForm(this.numberIndicatorFb.value, this.indicator.indicatorPaths, this.indicator.type, false); this.section = this.numbers.find(section => section._id === this.section._id); } let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id, this.section._id ]; this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, this.indicator, path).subscribe(indicator => { if (this.index !== -1) { this.section.indicators[this.index] = indicator; } else { this.section.indicators.push(indicator); } if (this.indicator.type === "chart") { this.filterCharts(); this.chartIndicatorFb = null; } else { this.filterNumbers(); this.numberIndicatorFb = null; } UIkit.notification('Indicator has been successfully saved', { status: 'success', timeout: 3000, pos: 'top-left' }); this.editing = false; }, error => { this.chartIndicatorFb = null; UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); this.editing = false; }); } reorderIndicators(sectionId: string, type: IndicatorType, indicatorIds: string[]) { this.editing = true; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id, sectionId ]; this.stakeholderService.reorderIndicators(this.properties.monitorServiceAPIURL, path, indicatorIds, type).subscribe(indicators => { if (type === 'chart') { this.charts.find(section => section._id === sectionId).indicators = indicators; this.filterCharts(); } else { this.numbers.find(section => section._id === sectionId).indicators = indicators; this.filterNumbers(); } this.editing = false; }); } hasDifference(index: number): boolean { let hasDifference = false; this.chartIndicatorPaths.at(index).value.parameters.forEach((parameter) => { if (parameter.value !== this.indicator.indicatorPaths[index].parameters[parameter.key]) { hasDifference = true; return; } }); return hasDifference || this.indicator.indicatorPaths[index].safeResourceUrl.toString() !== this.getSecureUrlByStakeHolder(this.indicator.indicatorPaths[index]).toString(); } public get isAdministrator(): boolean { return Session.isPortalAdministrator(this.user) || Session.isMonitorCurator(this.user); } refreshIndicator() { this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, 'chart', true); this.indicator.indicatorPaths.forEach(indicatorPath => { indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); }); } deleteIndicatorOpen(section: Section, indicatorId: string, type: string, childrenAction: string = null) { this.indicatorChildrenActionOnDelete = null; if (childrenAction == "delete") { this.indicatorChildrenActionOnDelete = childrenAction; } else if (childrenAction == "disconnect") { this.indicatorChildrenActionOnDelete = childrenAction; } this.section = section; if (type === 'chart') { this.index = this.charts.find(value => value._id == section._id).indicators.findIndex(value => value._id == indicatorId); } else { this.index = this.numbers.find(value => value._id == section._id).indicators.findIndex(value => value._id == indicatorId); } this.indicator = section.indicators.find(value => value._id == indicatorId); this.deleteModal.alertTitle = 'Delete indicator'; this.deleteModal.cancelButtonText = 'No'; this.deleteModal.okButtonText = 'Yes'; this.deleteModal.open(); } deleteIndicator() { this.editing = true; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id, this.section._id, this.indicator._id ]; this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.indicatorChildrenActionOnDelete).subscribe(() => { if (this.indicator.type === 'chart') { this.charts.find(section => section._id === this.section._id).indicators.splice(this.index, 1); this.filterCharts(); } else { this.numbers.find(section => section._id === this.section._id).indicators.splice(this.index, 1); this.filterNumbers(); } UIkit.notification('Indicator has been successfully deleted', { status: 'success', timeout: 3000, pos: 'top-left' }); this.editing = false; }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); this.editing = false; }); } changeIndicatorStatus(sectionId: string, indicator: Indicator, visibility: Visibility) { this.editing = true; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id, sectionId, indicator._id ]; this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => { indicator.visibility = visibility; UIkit.notification('Indicator has been successfully changed to ' + indicator.visibility.toLowerCase(), { status: 'success', timeout: 3000, pos: 'top-left' }); this.editing = false; }, error => { UIkit.notification('An error has been occurred. Try again later', { status: 'danger', timeout: 3000, pos: 'top-left' }); this.editing = false; }); } /*toggleIndicatorAccess(sectionId: string, indicator: Indicator) { this.editing = true; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id, sectionId, indicator._id ]; this.stakeholderService.toggleAccess(this.properties.monitorServiceAPIURL, path).subscribe(visibility => { indicator.visibility = visibility; UIkit.notification('Indicator has been successfully changed to ' + (visibility?'public':'private'), { status: 'success', timeout: 3000, pos: 'top-left' }); this.editing = false; }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); this.editing = false; }); }*/ saveSection(section: Section, index: number, type: IndicatorType = "chart") { this.editing = true; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id ]; this.stakeholderService.saveSection(this.properties.monitorServiceAPIURL, section, path, index).subscribe(section => { if (type === 'chart') { this.charts[index] = section; this.filterCharts(); } else { this.numbers[index] = section; this.filterNumbers(); } this.initReorder(); UIkit.notification('Section has been successfully saved', { status: 'success', timeout: 3000, pos: 'top-left' }); this.editing = false; }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); this.editing = false; }); } createSection(index = -1, type: IndicatorType = 'chart') { this.editing = true; this.section = new Section(type, null, null, this.stakeholder.alias); let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id ]; this.stakeholderService.saveSection(this.properties.monitorServiceAPIURL, this.section, path, index).subscribe(section => { if (type === 'chart') { if (index !== -1) { this.charts.splice(index, 0, section); } else { this.charts.push(section); } this.filterCharts(); } else { if (index !== -1) { this.numbers.splice(index, 0, section); } else { this.numbers.push(section); } this.filterNumbers(); } this.initReorder(); UIkit.notification('Section has been successfully created', { status: 'success', timeout: 3000, pos: 'top-left' }); this.editing = false; }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); this.editing = false; }); } // deleteNumberSectionOpen(section: Section, index: number) { // this.section = section; // this.index = index; // this.deleteNumberSectionModal.alertTitle = 'Delete Section'; // this.deleteNumberSectionModal.cancelButtonText = 'No'; // this.deleteNumberSectionModal.okButtonText = 'Yes'; // this.deleteNumberSectionModal.open(); // } // // deleteChartSectionOpen(section: Section, index: number) { // this.section = section; // this.index = index; // this.deleteChartSectionModal.alertTitle = 'Delete Section'; // this.deleteChartSectionModal.cancelButtonText = 'No'; // this.deleteChartSectionModal.okButtonText = 'Yes'; // this.deleteChartSectionModal.open(); // } deleteSectionOpen(section: Section, index: number, type: IndicatorType, childrenAction: string = null) { if (!this.editing && !section.defaultId) { this.sectionTypeToDelete = type; this.sectionChildrenActionOnDelete = null; if (childrenAction == "delete") { this.sectionChildrenActionOnDelete = childrenAction; } else if (childrenAction == "disconnect") { this.sectionChildrenActionOnDelete = childrenAction; } this.section = section; this.index = index; this.deleteSectionModal.alertTitle = 'Delete Section'; this.deleteSectionModal.cancelButtonText = 'No'; this.deleteSectionModal.okButtonText = 'Yes'; this.deleteSectionModal.open(); } } deleteSection() { this.editing = true; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]._id, this.section._id ]; this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.sectionChildrenActionOnDelete).subscribe(() => { if (this.sectionTypeToDelete === "chart") { this.charts.splice(this.index, 1); this.filterCharts(); } else { this.numbers.splice(this.index, 1); this.filterNumbers(); } this.initReorder(); UIkit.notification('Section has been successfully deleted', { status: 'success', timeout: 3000, pos: 'top-left' }); this.editing = false; }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); this.editing = false; }); } }