From f6319eac648c20fdb5b9fcd1d7a51c49381f8382 Mon Sep 17 00:00:00 2001 From: Konstantinos Triantafyllou Date: Wed, 4 Nov 2020 23:11:00 +0000 Subject: [PATCH] [Monitor Dashboard | Trunk]: Add alias error. Fix number indicator form validation git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-monitor-portal/trunk/monitor_dashboard@59775 d315682c-612b-4755-9ff5-7f18f6832af3 --- .../edit-stakeholder.component.ts | 2 +- src/app/topic/indicators.component.html | 17 +- src/app/topic/indicators.component.ts | 154 ++++++++++-------- src/app/topic/topic.module.ts | 7 +- src/app/utils/indicator-utils.ts | 4 +- src/app/utils/services/statistics.service.ts | 8 +- 6 files changed, 111 insertions(+), 81 deletions(-) diff --git a/src/app/general/edit-stakeholder/edit-stakeholder.component.ts b/src/app/general/edit-stakeholder/edit-stakeholder.component.ts index 8f79cda..17a22d5 100644 --- a/src/app/general/edit-stakeholder/edit-stakeholder.component.ts +++ b/src/app/general/edit-stakeholder/edit-stakeholder.component.ts @@ -20,7 +20,7 @@ declare var UIkit; [class.uk-padding-small]="!paddingLarge" [class.uk-padding-large]="paddingLarge" class="uk-overflow-auto" [formGroup]="stakeholderFb"> -
+
diff --git a/src/app/topic/indicators.component.html b/src/app/topic/indicators.component.html index b915fcb..d434776 100644 --- a/src/app/topic/indicators.component.html +++ b/src/app/topic/indicators.component.html @@ -295,13 +295,22 @@
-
+
+
diff --git a/src/app/topic/indicators.component.ts b/src/app/topic/indicators.component.ts index 918909b..8a6a0c3 100644 --- a/src/app/topic/indicators.component.ts +++ b/src/app/topic/indicators.component.ts @@ -76,7 +76,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV /** * Toggles */ - // public grid: boolean = true; + // public grid: boolean = true; public editing: boolean = false; /** Safe Urls*/ public safeUrls: Map = new Map([]); @@ -96,7 +96,8 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV public indicatorChildrenActionOnDelete: string; urlParameterizedMessage = ""; - constructor(private layoutService: LayoutService, + + constructor(private layoutService: LayoutService, private stakeholderService: StakeholderService, private statisticsService: StatisticsService, private userManagementService: UserManagementService, @@ -112,7 +113,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }); this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => { this.stakeholder = stakeholder; - if(this.stakeholder) { + if (this.stakeholder) { this.buildFilters(); this.buildSections(); this.filterCharts(); @@ -153,7 +154,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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]); + 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]); @@ -162,7 +163,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }); urls.forEach((indexes, pair) => { pair = JSON.parse(pair); - this.statisticsService.getNumbers(this.statisticsService.getSourceType(pair[0]), pair[1]).subscribe(response => { + 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 => { @@ -170,7 +171,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV result = result[jsonPath]; } }); - if(typeof result == 'string') { + if (typeof result == 'string') { this.numberResults.set(i + '-' + j, Number(result)); } }); @@ -179,9 +180,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } setPreview() { - if(this.stakeholder){ + if (this.stakeholder) { this.preview = '/' + this.stakeholder.alias; - if(this.stakeholder.topics[this.topicIndex]) { + 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; @@ -238,12 +239,12 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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); })); @@ -309,7 +310,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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); @@ -329,7 +330,6 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return sections; } - private filterStatus(sections: Section[], value): Section[] { if (value !== 'all') { @@ -344,7 +344,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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.additionalDescription && indicator.additionalDescription.toLowerCase().includes(value.toLowerCase())) || indicator.indicatorPaths.filter(indicatorPath => (indicatorPath.parameters && indicatorPath.parameters.title && indicatorPath.parameters.title.includes(value.toLowerCase()))).length > 0)); } @@ -404,11 +404,11 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } public addJsonPath(index: number) { - if(index==0 && this.getJsonPath(index).getRawValue()[index].indexOf(",")!=-1){ + 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){ + for (let i = 0; i < paths.length; i++) { + if (i != 0) { this.getJsonPath(index).push(this.fb.control('', Validators.required)); } } @@ -418,15 +418,43 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.getJsonPath(index).push(this.fb.control('', Validators.required)); } - public removeJsonPath(i: number, j:number) { + public removeJsonPath(i: number, j: number) { this.getJsonPath(i).removeAt(j); - this.getJsonPath(i).markAsDirty(); + 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; } @@ -444,8 +472,8 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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) { + 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({ @@ -455,56 +483,44 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV source: this.fb.control(source, Validators.required) } )); - - for(let index = 0; index < this.numberIndicatorPaths.length; index++) { + + 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 )){ + 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){ + 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{ + } else { this.urlParameterizedMessage = "This indicator couldn't be generated properly. Please make sure chart data is for the current stakeholder." } - }else { + } else { this.urlParameterizedMessage = ""; } - /* if(value != indicatorPath.url) { - (this.numberIndicatorPaths.at(index) as FormGroup).get('url').setValue( indicatorPath.url); - }*/ - if (!this.indicator.indicatorPaths[index]) { - this.indicator.indicatorPaths[index] = indicatorPath; - } else { - this.indicator.indicatorPaths[index] = indicatorPath; - } + /* 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 => { - if (!this.indicator.indicatorPaths[index]) { - this.indicator.indicatorPaths[index].jsonPath = value; - } else { - this.indicator.indicatorPaths[index].jsonPath = 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 => { - if (!this.indicator.indicatorPaths[index]) { - this.indicator.indicatorPaths[index].source = value; - } else { - this.indicator.indicatorPaths[index].source = value; - } + this.indicator.indicatorPaths[index].source = value; }) ); } } - public addChartIndicatorPath(value: string = '', parameters: FormArray = new FormArray([]), disableUrl: boolean = false, type:string=null) { + 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\.' + @@ -514,23 +530,23 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV type: this.fb.control(type) } )); - if(disableUrl) { - for(let index = 0; index < this.chartIndicatorPaths.length; index++) { + 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++) { + 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 ){ + 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){ + 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{ + } else { this.urlParameterizedMessage = "This chart couldn't be generated properly. Please make sure chart data is for the current stakeholder." } - }else { + } else { this.urlParameterizedMessage = ""; } (this.chartIndicatorPaths.at(index) as FormGroup).get('type').setValue(indicatorPath.type); @@ -600,10 +616,10 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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)); + 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.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), @@ -657,7 +673,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); }); } else { - this.indicator = new Indicator('', '', '', 'chart', 'medium', "PUBLIC",[]); + 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), @@ -692,8 +708,6 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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); } - console.debug("Indicator to svae"); - console.debug(this.indicator); let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, @@ -707,7 +721,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } else { this.section.indicators.push(indicator); } - if(this.indicator.type === "chart") { + if (this.indicator.type === "chart") { this.filterCharts(); this.chartIndicatorFb = null; } else { @@ -769,7 +783,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } refreshIndicator() { - this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths,'chart', true); + this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths, 'chart', true); this.indicator.indicatorPaths.forEach(indicatorPath => { indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); }); @@ -777,12 +791,12 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV deleteIndicatorOpen(section: Section, indicatorId: string, type: string, childrenAction: string = null) { this.indicatorChildrenActionOnDelete = null; - if(childrenAction == "delete") { + if (childrenAction == "delete") { this.indicatorChildrenActionOnDelete = childrenAction; - } else if(childrenAction == "disconnect") { + } 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); @@ -830,7 +844,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }); } - changeIndicatorStatus(sectionId: string, indicator: Indicator, visibility:Visibility) { + changeIndicatorStatus(sectionId: string, indicator: Indicator, visibility: Visibility) { this.editing = true; let path = [ this.stakeholder._id, @@ -978,9 +992,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV // this.deleteChartSectionModal.okButtonText = 'Yes'; // this.deleteChartSectionModal.open(); // } - + deleteSectionOpen(section: Section, index: number, type: IndicatorType, childrenAction: string = null) { - if(!this.editing && !section.defaultId) { + if (!this.editing && !section.defaultId) { this.sectionTypeToDelete = type; this.sectionChildrenActionOnDelete = null; if (childrenAction == "delete") { @@ -988,7 +1002,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } else if (childrenAction == "disconnect") { this.sectionChildrenActionOnDelete = childrenAction; } - + this.section = section; this.index = index; this.deleteSectionModal.alertTitle = 'Delete Section'; diff --git a/src/app/topic/topic.module.ts b/src/app/topic/topic.module.ts index 812a7c9..4be5040 100644 --- a/src/app/topic/topic.module.ts +++ b/src/app/topic/topic.module.ts @@ -24,15 +24,16 @@ import { group, refresh, close, - arrow_right + arrow_right, done } from "../openaireLibrary/utils/icons/icons"; import {IconsModule} from "../openaireLibrary/utils/icons/icons.module"; import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/page-content/page-content.module"; +import {LoadingModule} from "../openaireLibrary/utils/loading/loading.module"; @NgModule({ imports: [ CommonModule, TopicRoutingModule, ClickModule, RouterModule, FormsModule, AlertModalModule, - ReactiveFormsModule, InputModule, IconsModule, PageContentModule + ReactiveFormsModule, InputModule, IconsModule, PageContentModule, LoadingModule ], declarations: [ TopicComponent, IndicatorsComponent @@ -47,6 +48,6 @@ import {PageContentModule} from "../openaireLibrary/dashboard/sharedComponents/p }) export class TopicModule { constructor(private iconsService: IconsService) { - this.iconsService.registerIcons([preview, bullet, add, earth, lock, group, refresh, close, arrow_right]); + this.iconsService.registerIcons([preview, bullet, add, earth, lock, group, refresh, close, arrow_right, done]); } } diff --git a/src/app/utils/indicator-utils.ts b/src/app/utils/indicator-utils.ts index aad9755..e70eb4e 100644 --- a/src/app/utils/indicator-utils.ts +++ b/src/app/utils/indicator-utils.ts @@ -137,11 +137,11 @@ export class StakeholderUtils { } aliasValidator(elements: any[]): ValidatorFn { - return (control: AbstractControl): { [key: string]: boolean } | null => { + return (control: AbstractControl): { [key: string]: string } | null => { if (control.value && elements.find(element => element.alias === control.value )) { - return {'alias': true}; + return {'error': 'Alias already in use'}; } return null; } diff --git a/src/app/utils/services/statistics.service.ts b/src/app/utils/services/statistics.service.ts index 4c9d040..0977944 100644 --- a/src/app/utils/services/statistics.service.ts +++ b/src/app/utils/services/statistics.service.ts @@ -3,6 +3,7 @@ import {HttpClient} from "@angular/common/http"; import {EnvironmentSpecificService} from "../../openaireLibrary/utils/properties/environment-specific.service"; import {Observable} from "rxjs"; import {SourceType} from "../../openaireLibrary/monitor/entities/stakeholder"; +import {el} from "@angular/platform-browser/testing/src/browser_util"; @Injectable({ @@ -35,8 +36,13 @@ export class StatisticsService { }); return sourceType; } + getNumbers(source: SourceType, url: string): Observable { - return this.http.get(this.numberSources.get(source)[0] + url); + if(source !== null) { + return this.http.get(this.numberSources.get(source)[0] + url); + } else { + return this.http.get(url); + } } getChartUrl(source: SourceType, url: string): string {