diff --git a/src/app/topic/indicators.component.html b/src/app/topic/indicators.component.html index ace4693..a5735eb 100644 --- a/src/app/topic/indicators.component.html +++ b/src/app/topic/indicators.component.html @@ -114,15 +114,15 @@
@@ -151,6 +151,31 @@ +
+
+
+
+ add + Create a custom Indicator +
+
+
+
+
+ Create a new number Indicator +
+
+ add +
+
+
+
+

Chart Indicators

@@ -312,32 +337,92 @@
- -
-
-
+
+
+
-
-
-
+
+
+
+ Number Settings +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ JSON Path +
+
+
+
+ close +
+ arrow_forward +
+
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
Chart Settings
-
-
+
indicator permanently. Are you sure you want to proceed? + + You are about to delete this section and his indicators permanently. + Are you sure you want to proceed? + You are about to delete this section and his indicators permanently. Are you sure you want to proceed? diff --git a/src/app/topic/indicators.component.ts b/src/app/topic/indicators.component.ts index 383685b..4d9d276 100644 --- a/src/app/topic/indicators.component.ts +++ b/src/app/topic/indicators.component.ts @@ -22,6 +22,8 @@ import {Subscriber} from "rxjs"; import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service"; import {Option} from "../openaireLibrary/dashboard/sharedComponents/input/input.component"; import {Router} from "@angular/router"; +import {Session} from "../openaireLibrary/login/utils/helper.class"; +import {UserManagementService} from "../openaireLibrary/services/user-management.service"; declare var UIkit; @@ -41,9 +43,11 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV public subcategoryIndex: number = 0; @Input() public stakeholder: Stakeholder = null; + public user = null; public preview: string; public indicatorUtils: IndicatorUtils = new IndicatorUtils(); - public indicatorFb: FormGroup; + public numberIndicatorFb: FormGroup; + public chartIndicatorFb: FormGroup; public chartSections: FormArray; public numberSections: FormArray; /** @@ -74,14 +78,17 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV private subscriptions: any[] = []; private urlSubscriptions: any[] = []; - @ViewChild('editModal') editModal: AlertModal; + @ViewChild('editChartModal') editChartModal: AlertModal; + @ViewChild('editNumberModal') editNumberModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal; @ViewChild('deleteChartSectionModal') deleteChartSectionModal: AlertModal; - + @ViewChild('deleteNumberSectionModal') deleteNumberSectionModal: AlertModal; + urlParameterizedMessage = ""; constructor(private layoutService: LayoutService, private stakeholderService: StakeholderService, private statisticsService: StatisticsService, + private userManagementService: UserManagementService, private fb: FormBuilder, private router: Router, private cdr: ChangeDetectorRef, @@ -89,6 +96,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } ngOnInit(): void { + this.userManagementService.getUserInfo().subscribe(user => { + this.user = user; + }); this.buildFilters(); this.buildSections(); } @@ -244,6 +254,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.filterByKeyword(HelperFunctions.copy(this.numbers), this.filters.value.keyword), this.filters.value.status), this.filters.value.privacy); + console.log(this.numbers); this.buildSections(); } @@ -295,7 +306,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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.description && indicator.description.toLowerCase().includes(value.toLowerCase())) + || indicator.indicatorPaths.filter(indicatorPath => (indicatorPath.parameters && indicatorPath.parameters.title && + indicatorPath.parameters.title.includes(value.toLowerCase()))).length > 0)); } return sections; } @@ -344,12 +357,28 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex]; } - public get indicatorPaths(): FormArray { - return this.indicatorFb.get('indicatorPaths') as FormArray; + 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) { + this.getJsonPath(index).push(this.fb.control('', Validators.required)); + } + + public removeJsonPath(i: number, j:number) { + this.getJsonPath(i).removeAt(j); + } + + public getJsonPath(index: number): FormArray { + return this.numberIndicatorPaths.at(index).get('jsonPath') as FormArray; } public getParameters(index: number): FormArray { - return this.indicatorPaths.at(index).get('parameters') as FormArray; + return this.chartIndicatorPaths.at(index).get('parameters') as FormArray; } public getParameter(index: number, key: string): FormControl { @@ -365,8 +394,20 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return this.statisticsService.getChartUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)); } - public addIndicatorPath(value: string = '', parameters: FormArray = new FormArray([]), disableUrl: boolean = false, type:string=null) { - this.indicatorPaths.push(this.fb.group({ + public addNumberIndicatorPath(url: string = '', 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, + source: this.fb.control(source, Validators.required) + } + )); + } + + 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\.' + @@ -376,14 +417,14 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } )); if(disableUrl) { - for(let index = 0; index < this.indicatorPaths.length; index++) { - this.indicatorPaths.at(index).get('url').disable(); + for(let index = 0; index < this.chartIndicatorPaths.length; index++) { + this.chartIndicatorPaths.at(index).get('url').disable(); } } else { - for(let index = 0; index < this.indicatorPaths.length; index++) { - this.urlSubscriptions.push(this.indicatorPaths.at(index).get('url').valueChanges.subscribe(value => { - if (this.indicatorPaths.at(index).get('url').valid) { - let indicatorPath: IndicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.statisticsService.getChartSource(value), value, this.indicatorPaths.at(index).get('type').value, this.stakeholder); + 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){ @@ -394,9 +435,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }else { this.urlParameterizedMessage = ""; } - (this.indicatorPaths.at(index) as FormGroup).get('type').setValue(indicatorPath.type); + (this.chartIndicatorPaths.at(index) as FormGroup).get('type').setValue(indicatorPath.type); let parameters = this.getParametersAsFormArray(indicatorPath); - (this.indicatorPaths.at(index) as FormGroup).setControl('parameters', parameters); + (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); @@ -411,6 +452,16 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV } } + 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) { @@ -433,6 +484,53 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV return parameters; } + public editNumberIndicatorOpen(section: Section, id = null) { + 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), + description: this.fb.control(this.indicator.description), + isPublic: this.fb.control(this.indicator.isPublic), + isActive: this.fb.control(this.indicator.isActive), + 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(indicatorPath.url, indicatorPath.source, this.getJsonPathAsFormArray(indicatorPath)); + }); + } else { + this.indicator = new Indicator('', '', 'number', 'small', false, false, []); + this.numberIndicatorFb = this.fb.group({ + _id: this.fb.control(this.indicator._id), + name: this.fb.control(this.indicator.name), + description: this.fb.control(this.indicator.description), + isPublic: this.fb.control(this.indicator.isPublic), + isActive: this.fb.control(this.indicator.isActive), + 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(); + } + 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 => { @@ -444,9 +542,9 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV 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.indicatorFb = this.fb.group({ - id: this.fb.control(this.indicator._id), - name: this.fb.control(this.indicator.name/*, Validators.required*/), + 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), isPublic: this.fb.control(this.indicator.isPublic), isActive: this.fb.control(this.indicator.isActive), @@ -455,14 +553,14 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV defaultId: this.fb.control(this.indicator.defaultId) }); this.indicator.indicatorPaths.forEach(indicatorPath => { - this.addIndicatorPath(this.getUrlByStakeHolder(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', 'small', false, false, []); - this.indicatorFb = this.fb.group({ - id: this.fb.control(null), + this.chartIndicatorFb = this.fb.group({ + _id: this.fb.control(null), name: this.fb.control(''), description: this.fb.control(''), isPublic: this.fb.control(false), @@ -471,25 +569,27 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV width: this.fb.control('small', Validators.required), defaultId: this.fb.control(null) }); - this.addIndicatorPath(); + this.addChartIndicatorPath(); } - this.editModal.cancelButtonText = 'Cancel'; - this.editModal.okButtonLeft = false; - this.editModal.alertMessage = false; + this.editChartModal.cancelButtonText = 'Cancel'; + this.editChartModal.okButtonLeft = false; + this.editChartModal.alertMessage = false; if (this.index === -1) { - this.editModal.alertTitle = 'Create a new chart indicator'; - this.editModal.okButtonText = 'Save'; + this.editChartModal.alertTitle = 'Create a new chart indicator'; + this.editChartModal.okButtonText = 'Save'; } else { - this.editModal.alertTitle = 'Edit chart indicator\'s information'; - this.editModal.okButtonText = 'Save Changes'; + this.editChartModal.alertTitle = 'Edit chart indicator\'s information'; + this.editChartModal.okButtonText = 'Save Changes'; } - this.editModal.open(); + this.editChartModal.open(); } saveIndicator() { if (this.indicator.type === 'chart') { - this.indicator = this.indicatorUtils.generateIndicatorByForm(this.indicatorFb.value, this.indicator.indicatorPaths); + this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths); this.section = this.charts.find(section => section._id === this.section._id); + } else { + this.indicator = this.numberIndicatorFb.value; } let path = [ this.stakeholder._id, @@ -505,14 +605,14 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.section.indicators.push(indicator); } this.filterCharts(); - this.indicatorFb = null; + this.chartIndicatorFb = null; UIkit.notification('Indicator has been successfully saved', { status: 'success', timeout: 3000, pos: 'top-left' }); }, error => { - this.indicatorFb = null; + this.chartIndicatorFb = null; UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, @@ -542,7 +642,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV hasDifference(index: number): boolean { let hasDifference = false; - this.indicatorPaths.at(index).value.parameters.forEach((parameter) => { + this.chartIndicatorPaths.at(index).value.parameters.forEach((parameter) => { if (parameter.value !== this.indicator.indicatorPaths[index].parameters[parameter.key]) { hasDifference = true; return; @@ -552,8 +652,12 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV this.getSecureUrlByStakeHolder(this.indicator.indicatorPaths[index]).toString(); } + public get isAdministrator(): boolean { + return Session.isPortalAdministrator(this.user) || Session.isMonitorCurator(this.user) || Session.isCommunityCurator(this.user) + } + refreshIndicator() { - this.indicator = this.indicatorUtils.generateIndicatorByForm(this.indicatorFb.value, this.indicator.indicatorPaths); + this.indicator = this.indicatorUtils.generateIndicatorByForm(this.chartIndicatorFb.value, this.indicator.indicatorPaths); this.indicator.indicatorPaths.forEach(indicatorPath => { indicatorPath.safeResourceUrl = this.getSecureUrlByStakeHolder(indicatorPath); }); @@ -723,6 +827,15 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV }); } + 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; diff --git a/src/app/utils/indicator-utils.ts b/src/app/utils/indicator-utils.ts index a9015d7..44492f2 100644 --- a/src/app/utils/indicator-utils.ts +++ b/src/app/utils/indicator-utils.ts @@ -158,12 +158,18 @@ export class IndicatorUtils { ]; basicChartTypes:IndicatorPathType[] =["pie", "line", "column", "bar"]; defaultChartType:IndicatorPathType = "other"; - chartSizes: Option[] = [ + indicatorSizes: Option[] = [ {value: 'small', label: 'Small'}, {value: 'medium', label: 'Medium'}, {value: 'large', label: 'Large'} ]; + sourceTypes: Option[] = [ + {value: 'search', label: 'Search'}, + {value: 'statistics', label: 'Statistics'}, + {value: 'metrics', label: 'Metrics'} + ] + isPublic: Option[] = [ {icon: 'public', value: true, label: 'Public'}, {icon: 'lock', value: false, label: 'Private'},