From 7dac0dc01c227daf725d762cb4639df86f6d65a9 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 13 Mar 2026 13:10:51 -0500 Subject: [PATCH 01/49] add chart Target vs Actual - Benefits - Column Chart --- src/models/ProjectDashboard.ts | 40 ++++- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 167 ++++++++++++++++-- 3 files changed, 187 insertions(+), 22 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 2decb8d2..c9cc8dfe 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -34,7 +34,11 @@ export default class ProjectDashboard { dataElements: ProjectsListDashboard["dataElements"]; categoryOnlyNew: { id: Id; categoryOptions: Ref[] }; - constructor(private config: Config, private projectsListDashboard: ProjectsListDashboard) { + constructor( + private config: Config, + private projectsListDashboard: ProjectsListDashboard, + private dashboardType: "project" | "awardNumber" + ) { this.dataElements = this.projectsListDashboard.dataElements; this.categoryOnlyNew = { @@ -53,7 +57,7 @@ export default class ProjectDashboard { ): Promise { const condition: Condition = { type: "project", id: project.id, initialMetadata }; const projectsListDashboard = await getProjectsListDashboard(api, config, condition); - return new ProjectDashboard(config, projectsListDashboard); + return new ProjectDashboard(config, projectsListDashboard, "project"); } static async buildForAwardNumber( @@ -64,7 +68,7 @@ export default class ProjectDashboard { ): Promise { const condition: Condition = { type: "awardNumber", value: awardNumber, initialMetadata }; const projectsListDashboard = await getProjectsListDashboard(api, config, condition); - return new ProjectDashboard(config, projectsListDashboard); + return new ProjectDashboard(config, projectsListDashboard, "awardNumber"); } generate(options: { minimumOrgUnits?: number } = {}) { @@ -74,6 +78,12 @@ export default class ProjectDashboard { if (!_.isNil(minimumOrgUnits) && projectsListDashboard.orgUnits.length < minimumOrgUnits) return { dashboards: [], visualizations: [] }; + // Note: I think this.dashboardType === "project" is the same as the condition for minimumOrgUnits = 2 + // I'll need to check that before doing the PR + + const targetVsActualBenefitsChart_ = + this.dashboardType === "project" ? this.targetVsActualBenefitsChart() : undefined; + const reportTables: Array> = _.compact([ // General Data View this.targetVsActualBenefitsTable(), @@ -99,10 +109,15 @@ export default class ProjectDashboard { const achievedMonthlyChart_ = this.achievedMonthlyChart(); const favorites = { - visualizations: _.concat(reportTables, _.compact([achievedMonthlyChart_, ...charts])), + visualizations: _.concat( + _.compact([targetVsActualBenefitsChart_]), + reportTables, + _.compact([achievedMonthlyChart_, ...charts]) + ), }; const items: Array> = _.compact([ + getChartDashboardItem(targetVsActualBenefitsChart_), ...reportTables.map(reportTable => getReportTableItem(reportTable)), getChartDashboardItem(achievedMonthlyChart_, { width: toItemWidth(100) }), ...charts.map(chart => getChartDashboardItem(chart)), @@ -141,6 +156,23 @@ export default class ProjectDashboard { }); } + targetVsActualBenefitsChart(): MaybeD2Visualization { + const { config, dataElements } = this; + const dataElementsNoDisaggregated = dataElements.benefit.filter( + de => !de.categories.includes("newRecurring") + ); + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-target-actual-benefits", + name: i18n.t("Target vs Actual - Benefits - Column Chart"), + items: dataElementItems(dataElementsNoDisaggregated), + filters: [dimensions.data, dimensions.orgUnit], + columns: [config.categories.targetActual], + rows: [dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 2ac1d18c..d67899c7 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,i07AWJAND8a,iqqgnCj9DQj,GycLEG8dPPO,iOk52Z42bjp,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ayOoqqk9Rnb,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,i07AWJAND8a,iqqgnCj9DQj,GycLEG8dPPO,iOk52Z42bjp,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ayOoqqk9Rnb,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 188f4f34..a300e16d 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -995,6 +995,17 @@ "id": "WgOMVlwSV2i", "name": "12345en - MyProject", "dashboardItems": [ + { + "id": "uOsjh5OmILO", + "type": "CHART", + "visualization": { + "id": "ywQZlYBN4nN" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 0 + }, { "id": "Ka4yijY2Vhl", "type": "REPORT_TABLE", @@ -1003,7 +1014,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 0 }, { @@ -1014,8 +1025,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 0 + "x": 0, + "y": 20 }, { "id": "y2G8oh7xQBm", @@ -1025,7 +1036,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 20 }, { @@ -1036,8 +1047,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 20 + "x": 0, + "y": 40 }, { "id": "ywvTGMsKdwL", @@ -1047,7 +1058,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 40 }, { @@ -1058,8 +1069,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 40 + "x": 0, + "y": 60 }, { "id": "uyoJujQVRjE", @@ -1069,7 +1080,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 60 }, { @@ -1080,8 +1091,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 60 + "x": 0, + "y": 80 }, { "id": "ys0CVedHirZ", @@ -1092,7 +1103,7 @@ "width": 58, "height": 20, "x": 0, - "y": 80 + "y": 100 }, { "id": "KI0C90Ol10x", @@ -1103,7 +1114,7 @@ "width": 29, "height": 20, "x": 0, - "y": 100 + "y": 120 }, { "id": "uYY7v977Ubm", @@ -1114,7 +1125,7 @@ "width": 29, "height": 20, "x": 29, - "y": 100 + "y": 120 }, { "id": "qUqsDmtiBLF", @@ -1125,7 +1136,7 @@ "width": 29, "height": 20, "x": 0, - "y": 120 + "y": 140 }, { "id": "mwMpIdPdu8H", @@ -1136,7 +1147,7 @@ "width": 29, "height": 20, "x": 29, - "y": 120 + "y": 140 } ], "publicAccess": "--------", @@ -1384,6 +1395,128 @@ } ], "visualizations": [ + { + "id": "ywQZlYBN4nN", + "type": "COLUMN", + "name": "12345en - MyProject - Target vs Actual - Benefits - Column Chart", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WS8XV4WWPE7" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": ["GIIHAr9BzzO"], + "filters": [ + { + "id": "dx" + }, + { + "id": "ou" + } + ], + "filterDimensions": ["dx", "ou"], + "rows": [ + { + "id": "pe" + } + ], + "rowDimensions": ["pe"], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "i07AWJAND8a", "type": "PIVOT_TABLE", From ac2d481a983c8134d339766f62e247f4c9ca0d95 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 13 Mar 2026 14:44:43 -0500 Subject: [PATCH 02/49] add visualization Target vs Actual - People - Column Chart --- src/models/ProjectDashboard.ts | 24 +- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 219 +++++++++++++++++- 3 files changed, 231 insertions(+), 14 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index c9cc8dfe..ff247837 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -83,6 +83,8 @@ export default class ProjectDashboard { const targetVsActualBenefitsChart_ = this.dashboardType === "project" ? this.targetVsActualBenefitsChart() : undefined; + const targetVsActualPeopleChart_ = + this.dashboardType === "project" ? this.targetVsActualPeopleChart() : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -110,7 +112,7 @@ export default class ProjectDashboard { const achievedMonthlyChart_ = this.achievedMonthlyChart(); const favorites = { visualizations: _.concat( - _.compact([targetVsActualBenefitsChart_]), + _.compact([targetVsActualBenefitsChart_, targetVsActualPeopleChart_]), reportTables, _.compact([achievedMonthlyChart_, ...charts]) ), @@ -118,6 +120,7 @@ export default class ProjectDashboard { const items: Array> = _.compact([ getChartDashboardItem(targetVsActualBenefitsChart_), + getChartDashboardItem(targetVsActualPeopleChart_), ...reportTables.map(reportTable => getReportTableItem(reportTable)), getChartDashboardItem(achievedMonthlyChart_, { width: toItemWidth(100) }), ...charts.map(chart => getChartDashboardItem(chart)), @@ -173,6 +176,25 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleChart(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-target-actual-people", + name: i18n.t("Target vs Actual - People - Column Chart"), + items: dataElementItems(dataElements.people), + filters: [ + dimensions.data, + dimensions.orgUnit, + config.categories.gender, + config.categories.newRecurring, + ], + columns: [config.categories.targetActual], + rows: [dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index d67899c7..fba400bd 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,i07AWJAND8a,iqqgnCj9DQj,GycLEG8dPPO,iOk52Z42bjp,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ayOoqqk9Rnb,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,i07AWJAND8a,iqqgnCj9DQj,GycLEG8dPPO,iOk52Z42bjp,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ayOoqqk9Rnb,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index a300e16d..40bbfd3d 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1006,6 +1006,17 @@ "x": 0, "y": 0 }, + { + "id": "mouU4wUzbJ3", + "type": "CHART", + "visualization": { + "id": "q0Arl96SxH5" + }, + "width": 29, + "height": 20, + "x": 29, + "y": 0 + }, { "id": "Ka4yijY2Vhl", "type": "REPORT_TABLE", @@ -1014,8 +1025,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 0 + "x": 0, + "y": 20 }, { "id": "yWGKgz9vaOh", @@ -1025,7 +1036,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 20 }, { @@ -1036,8 +1047,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 20 + "x": 0, + "y": 40 }, { "id": "m4LaU9HizHi", @@ -1047,7 +1058,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 40 }, { @@ -1058,8 +1069,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 40 + "x": 0, + "y": 60 }, { "id": "qMSWdZHPjyN", @@ -1069,7 +1080,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 60 }, { @@ -1080,8 +1091,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 60 + "x": 0, + "y": 80 }, { "id": "mgwFIMjbsdw", @@ -1091,7 +1102,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 80 }, { @@ -1517,6 +1528,190 @@ } ] }, + { + "id": "q0Arl96SxH5", + "type": "COLUMN", + "name": "12345en - MyProject - Target vs Actual - People - Column Chart", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": ["GIIHAr9BzzO"], + "filters": [ + { + "id": "dx" + }, + { + "id": "ou" + }, + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "rows": [ + { + "id": "pe" + } + ], + "rowDimensions": ["pe"], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "i07AWJAND8a", "type": "PIVOT_TABLE", From 642e97e3722cccf058207043c48531e3c13c1ea6 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 13 Mar 2026 15:53:53 -0500 Subject: [PATCH 03/49] add chart MER - Target vs Actual - Benefits - Column Chart --- src/models/ProjectDashboard.ts | 41 ++++- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 158 ++++++++++++++++-- 3 files changed, 179 insertions(+), 22 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index ff247837..2022802c 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -32,15 +32,27 @@ import { filterPeriods } from "./Period"; export default class ProjectDashboard { dataElements: ProjectsListDashboard["dataElements"]; + merDataElements: Record<"all" | "people" | "benefit", Ref[]>; categoryOnlyNew: { id: Id; categoryOptions: Ref[] }; constructor( private config: Config, private projectsListDashboard: ProjectsListDashboard, - private dashboardType: "project" | "awardNumber" + private dashboardType: "project" | "awardNumber", + project?: Project ) { this.dataElements = this.projectsListDashboard.dataElements; + const projectMerDataElements = _(project?.dataElementsMER.getAllSelected()) + .uniqBy(de => de.id) + .value(); + + this.merDataElements = { + all: projectMerDataElements, + people: projectMerDataElements.filter(de => de.peopleOrBenefit === "people"), + benefit: projectMerDataElements.filter(de => de.peopleOrBenefit === "benefit"), + }; + this.categoryOnlyNew = { id: config.categories.newRecurring.id, categoryOptions: [{ id: config.categoryOptions.new.id }], @@ -52,12 +64,12 @@ export default class ProjectDashboard { static async buildForProject( api: D2Api, config: Config, - project: Ref, + project: Project, initialMetadata?: DashboardSourceMetadata ): Promise { const condition: Condition = { type: "project", id: project.id, initialMetadata }; const projectsListDashboard = await getProjectsListDashboard(api, config, condition); - return new ProjectDashboard(config, projectsListDashboard, "project"); + return new ProjectDashboard(config, projectsListDashboard, "project", project); } static async buildForAwardNumber( @@ -85,6 +97,8 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualBenefitsChart() : undefined; const targetVsActualPeopleChart_ = this.dashboardType === "project" ? this.targetVsActualPeopleChart() : undefined; + const merTargetVsActualBenefitsChart_ = + this.dashboardType === "project" ? this.merTargetVsActualBenefitsChart() : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -112,7 +126,11 @@ export default class ProjectDashboard { const achievedMonthlyChart_ = this.achievedMonthlyChart(); const favorites = { visualizations: _.concat( - _.compact([targetVsActualBenefitsChart_, targetVsActualPeopleChart_]), + _.compact([ + targetVsActualBenefitsChart_, + targetVsActualPeopleChart_, + merTargetVsActualBenefitsChart_, + ]), reportTables, _.compact([achievedMonthlyChart_, ...charts]) ), @@ -121,6 +139,7 @@ export default class ProjectDashboard { const items: Array> = _.compact([ getChartDashboardItem(targetVsActualBenefitsChart_), getChartDashboardItem(targetVsActualPeopleChart_), + getChartDashboardItem(merTargetVsActualBenefitsChart_), ...reportTables.map(reportTable => getReportTableItem(reportTable)), getChartDashboardItem(achievedMonthlyChart_, { width: toItemWidth(100) }), ...charts.map(chart => getChartDashboardItem(chart)), @@ -195,6 +214,20 @@ export default class ProjectDashboard { }); } + merTargetVsActualBenefitsChart(): MaybeD2Visualization { + const { config, merDataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-mer-target-actual-benefits", + name: i18n.t("MER - Target vs Actual - Benefits - Column Chart"), + items: dataElementItems(merDataElements.benefit), + filters: [dimensions.orgUnit], + columns: [config.categories.targetActual], + rows: [dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index fba400bd..13ea5b6f 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,i07AWJAND8a,iqqgnCj9DQj,GycLEG8dPPO,iOk52Z42bjp,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ayOoqqk9Rnb,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iqqgnCj9DQj,GycLEG8dPPO,iOk52Z42bjp,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ayOoqqk9Rnb,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 40bbfd3d..d0529816 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1017,6 +1017,17 @@ "x": 29, "y": 0 }, + { + "id": "WQwlyfCElo8", + "type": "CHART", + "visualization": { + "id": "yWq2ZBWiK8T" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 20 + }, { "id": "Ka4yijY2Vhl", "type": "REPORT_TABLE", @@ -1025,7 +1036,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 20 }, { @@ -1036,8 +1047,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 20 + "x": 0, + "y": 40 }, { "id": "y2G8oh7xQBm", @@ -1047,7 +1058,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 40 }, { @@ -1058,8 +1069,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 40 + "x": 0, + "y": 60 }, { "id": "ywvTGMsKdwL", @@ -1069,7 +1080,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 60 }, { @@ -1080,8 +1091,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 60 + "x": 0, + "y": 80 }, { "id": "uyoJujQVRjE", @@ -1091,7 +1102,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 80 }, { @@ -1102,8 +1113,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 80 + "x": 0, + "y": 100 }, { "id": "ys0CVedHirZ", @@ -1114,7 +1125,7 @@ "width": 58, "height": 20, "x": 0, - "y": 100 + "y": 120 }, { "id": "KI0C90Ol10x", @@ -1125,7 +1136,7 @@ "width": 29, "height": 20, "x": 0, - "y": 120 + "y": 140 }, { "id": "uYY7v977Ubm", @@ -1136,7 +1147,7 @@ "width": 29, "height": 20, "x": 29, - "y": 120 + "y": 140 }, { "id": "qUqsDmtiBLF", @@ -1147,7 +1158,7 @@ "width": 29, "height": 20, "x": 0, - "y": 140 + "y": 160 }, { "id": "mwMpIdPdu8H", @@ -1158,7 +1169,7 @@ "width": 29, "height": 20, "x": 29, - "y": 140 + "y": 160 } ], "publicAccess": "--------", @@ -1712,6 +1723,119 @@ } ] }, + { + "id": "yWq2ZBWiK8T", + "type": "COLUMN", + "name": "12345en - MyProject - MER - Target vs Actual - Benefits - Column Chart", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": ["GIIHAr9BzzO"], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": ["ou"], + "rows": [ + { + "id": "pe" + } + ], + "rowDimensions": ["pe"], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "i07AWJAND8a", "type": "PIVOT_TABLE", From c633a610731fbd3ac818e7768a61041f5d302d68 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 13 Mar 2026 16:39:54 -0500 Subject: [PATCH 04/49] add chart MER - Target vs Actual - People - Column Chart --- src/models/ProjectDashboard.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 2022802c..ad74e709 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -99,6 +99,8 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualPeopleChart() : undefined; const merTargetVsActualBenefitsChart_ = this.dashboardType === "project" ? this.merTargetVsActualBenefitsChart() : undefined; + const merTargetVsActualPeopleChart_ = + this.dashboardType === "project" ? this.merTargetVsActualPeopleChart() : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -130,6 +132,7 @@ export default class ProjectDashboard { targetVsActualBenefitsChart_, targetVsActualPeopleChart_, merTargetVsActualBenefitsChart_, + merTargetVsActualPeopleChart_, ]), reportTables, _.compact([achievedMonthlyChart_, ...charts]) @@ -140,6 +143,7 @@ export default class ProjectDashboard { getChartDashboardItem(targetVsActualBenefitsChart_), getChartDashboardItem(targetVsActualPeopleChart_), getChartDashboardItem(merTargetVsActualBenefitsChart_), + getChartDashboardItem(merTargetVsActualPeopleChart_), ...reportTables.map(reportTable => getReportTableItem(reportTable)), getChartDashboardItem(achievedMonthlyChart_, { width: toItemWidth(100) }), ...charts.map(chart => getChartDashboardItem(chart)), @@ -228,6 +232,25 @@ export default class ProjectDashboard { }); } + merTargetVsActualPeopleChart(): MaybeD2Visualization { + const { config, merDataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-mer-target-actual-people", + name: i18n.t("MER - Target vs Actual - People - Column Chart"), + items: dataElementItems(merDataElements.people), + filters: [ + dimensions.data, + dimensions.orgUnit, + config.categories.gender, + config.categories.newRecurring, + ], + columns: [config.categories.targetActual], + rows: [dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => From d85ab954dcf39e1224432ce0f4fdd9cf64780884 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 13 Mar 2026 16:45:29 -0500 Subject: [PATCH 05/49] remove chart Target vs Actual - Unique People --- src/models/ProjectDashboard.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index ad74e709..9bcd899e 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -107,7 +107,6 @@ export default class ProjectDashboard { this.targetVsActualBenefitsTable(), this.targetVsActualBenefitsWithDisaggregationTable(), this.targetVsActualPeopleTable(), - this.targetVsActualUniquePeopleTable(), // Percent achieved (to date) this.achievedBenefitsTable({ toDate: true }), this.achievedBenefitsTotalToDateTable(), From c83c0d6b437aa3549fb4347cd71521ca658ed03f Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 12:49:19 -0500 Subject: [PATCH 06/49] add chart Column Chart Disaggregated By Indicator --- src/models/ProjectDashboard.ts | 80 ++- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 660 +++++------------- 3 files changed, 222 insertions(+), 520 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 9bcd899e..fa120930 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -101,6 +101,10 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.merTargetVsActualBenefitsChart() : undefined; const merTargetVsActualPeopleChart_ = this.dashboardType === "project" ? this.merTargetVsActualPeopleChart() : undefined; + const targetVsActualBenefitsDisaggregatedByIndicatorChart_ = + this.dashboardType === "project" + ? this.targetVsActualBenefitsDisaggregatedByIndicatorChart() + : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -125,25 +129,54 @@ export default class ProjectDashboard { ]); const achievedMonthlyChart_ = this.achievedMonthlyChart(); + const [ + targetVsActualBenefitsTable_, + targetVsActualBenefitsWithDisaggregationTable_, + targetVsActualPeopleTable_, + ] = reportTables; + const otherReportTables = reportTables.slice(3); + + const projectVisualizations = _.compact([ + targetVsActualBenefitsChart_, + targetVsActualPeopleChart_, + merTargetVsActualBenefitsChart_, + merTargetVsActualPeopleChart_, + targetVsActualBenefitsTable_, + targetVsActualPeopleTable_, + targetVsActualBenefitsDisaggregatedByIndicatorChart_, + targetVsActualBenefitsWithDisaggregationTable_, + ]); + const defaultVisualizations = _.concat( + reportTables, + _.compact([achievedMonthlyChart_, ...charts]) + ); const favorites = { - visualizations: _.concat( - _.compact([ - targetVsActualBenefitsChart_, - targetVsActualPeopleChart_, - merTargetVsActualBenefitsChart_, - merTargetVsActualPeopleChart_, - ]), - reportTables, - _.compact([achievedMonthlyChart_, ...charts]) - ), + visualizations: + this.dashboardType === "project" + ? _.concat( + projectVisualizations, + otherReportTables, + _.compact([achievedMonthlyChart_, ...charts]) + ) + : defaultVisualizations, }; const items: Array> = _.compact([ - getChartDashboardItem(targetVsActualBenefitsChart_), - getChartDashboardItem(targetVsActualPeopleChart_), - getChartDashboardItem(merTargetVsActualBenefitsChart_), - getChartDashboardItem(merTargetVsActualPeopleChart_), - ...reportTables.map(reportTable => getReportTableItem(reportTable)), + ...(this.dashboardType === "project" + ? _.compact([ + getChartDashboardItem(targetVsActualBenefitsChart_), + getChartDashboardItem(targetVsActualPeopleChart_), + getChartDashboardItem(merTargetVsActualBenefitsChart_), + getChartDashboardItem(merTargetVsActualPeopleChart_), + getReportTableItem(targetVsActualBenefitsTable_), + getReportTableItem(targetVsActualPeopleTable_), + getChartDashboardItem(targetVsActualBenefitsDisaggregatedByIndicatorChart_), + getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), + ]) + : reportTables.map(reportTable => getReportTableItem(reportTable))), + ...(this.dashboardType === "project" + ? otherReportTables.map(reportTable => getReportTableItem(reportTable)) + : []), getChartDashboardItem(achievedMonthlyChart_, { width: toItemWidth(100) }), ...charts.map(chart => getChartDashboardItem(chart)), ]); @@ -250,6 +283,23 @@ export default class ProjectDashboard { }); } + targetVsActualBenefitsDisaggregatedByIndicatorChart(): MaybeD2Visualization { + const { config, dataElements } = this; + const dataElementsNoDisaggregated = dataElements.benefit.filter( + de => !de.categories.includes("newRecurring") + ); + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-target-actual-benefits-disaggregated-by-indicator", + name: i18n.t("Target vs Actual - Benefits - Column Chart Disaggregated By Indicator"), + items: dataElementItems(dataElementsNoDisaggregated), + filters: [dimensions.orgUnit], + columns: [dimensions.data], + rows: [dimensions.period, config.categories.targetActual], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 13ea5b6f..e163b486 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iqqgnCj9DQj,GycLEG8dPPO,iOk52Z42bjp,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ayOoqqk9Rnb,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index d0529816..fc74e9f6 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1040,10 +1040,10 @@ "y": 20 }, { - "id": "yWGKgz9vaOh", + "id": "m4LaU9HizHi", "type": "REPORT_TABLE", "visualization": { - "id": "iqqgnCj9DQj" + "id": "iOk52Z42bjp" }, "width": 29, "height": 20, @@ -1051,10 +1051,10 @@ "y": 40 }, { - "id": "y2G8oh7xQBm", - "type": "REPORT_TABLE", + "id": "i66m5HwnH6v", + "type": "CHART", "visualization": { - "id": "GycLEG8dPPO" + "id": "a46jcQ65Axt" }, "width": 29, "height": 20, @@ -1062,10 +1062,10 @@ "y": 40 }, { - "id": "m4LaU9HizHi", + "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", "visualization": { - "id": "iOk52Z42bjp" + "id": "iqqgnCj9DQj" }, "width": 29, "height": 20, @@ -1271,17 +1271,6 @@ "x": 29, "y": 0 }, - { - "id": "K0YRx2HGCs5", - "type": "REPORT_TABLE", - "visualization": { - "id": "ayOoqqk9Rnb" - }, - "width": 29, - "height": 20, - "x": 0, - "y": 20 - }, { "id": "O0uabsxLqGS", "type": "REPORT_TABLE", @@ -1290,7 +1279,7 @@ }, "width": 29, "height": 20, - "x": 29, + "x": 0, "y": 20 }, { @@ -1301,8 +1290,8 @@ }, "width": 29, "height": 20, - "x": 0, - "y": 40 + "x": 29, + "y": 20 }, { "id": "iIyADNFfXEV", @@ -1312,7 +1301,7 @@ }, "width": 29, "height": 20, - "x": 29, + "x": 0, "y": 40 }, { @@ -1323,8 +1312,8 @@ }, "width": 29, "height": 20, - "x": 0, - "y": 60 + "x": 29, + "y": 40 }, { "id": "yseGHIbXcNQ", @@ -1334,7 +1323,7 @@ }, "width": 29, "height": 20, - "x": 29, + "x": 0, "y": 60 }, { @@ -1959,9 +1948,9 @@ ] }, { - "id": "iqqgnCj9DQj", + "id": "iOk52Z42bjp", "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Target vs Actual - People", + "name": "12345en - MyProject - Achieved to date (%) - Benefits", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -1973,21 +1962,112 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "K6mAC5SiO29" + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "eCufXa6RkTm" + } + }, + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "i01veyO4Cuw" } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "id": "pe" + } + ], + "columnDimensions": ["pe"], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": ["ou"], + "rows": [ + { + "id": "dx" + } + ], + "rowDimensions": ["dx"], + "categoryDimensions": [], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ], + "legendSet": { + "code": "ACTUAL_TARGET_ACHIEVED", + "id": "yoAt108kUFm" + } + }, + { + "id": "a46jcQ65Axt", + "type": "COLUMN", + "name": "12345en - MyProject - Target vs Actual - Benefits - Column Chart Disaggregated By Indicator", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "ik0ICagvIjm" + "id": "WS8XV4WWPE7" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "GQyudNlGzkI" + "id": "yMqK9DKbA3X" } } ], @@ -2018,25 +2098,10 @@ ], "columns": [ { - "id": "pe" - }, - { - "code": "GENDER", - "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "MALE", - "id": "qk2FihwV6IL" - }, - { - "code": "FEMALE", - "id": "yW2hYVS3S4u" - } - ] + "id": "dx" } ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -2045,7 +2110,7 @@ "filterDimensions": ["ou"], "rows": [ { - "id": "dx" + "id": "pe" }, { "code": "ACTUAL_TARGET", @@ -2061,38 +2126,10 @@ "id": "eWeQoOlAcxV" } ] - }, - { - "code": "NEW_RETURNING", - "id": "uSMHdwhxFSV", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "NEW", - "id": "KiK0FMExoqh" - }, - { - "code": "RETURNING", - "id": "a6AJLXQy8vO" - } - ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ - { - "category": { - "id": "Kyg1O6YEGa9" - }, - "categoryOptions": [ - { - "id": "qk2FihwV6IL" - }, - { - "id": "yW2hYVS3S4u" - } - ] - }, { "category": { "id": "GIIHAr9BzzO" @@ -2105,19 +2142,6 @@ "id": "eWeQoOlAcxV" } ] - }, - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - }, - { - "id": "a6AJLXQy8vO" - } - ] } ], "publicAccess": "--------", @@ -2143,9 +2167,9 @@ ] }, { - "id": "GycLEG8dPPO", + "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Target vs Actual - Unique People", + "name": "12345en - MyProject - Target vs Actual - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2224,17 +2248,9 @@ "filters": [ { "id": "ou" - }, - { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] } ], - "filterDimensions": ["ou", "uSMHdwhxFSV"], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2253,9 +2269,24 @@ "id": "eWeQoOlAcxV" } ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -2290,6 +2321,9 @@ "categoryOptions": [ { "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" } ] } @@ -2317,9 +2351,9 @@ ] }, { - "id": "iOk52Z42bjp", + "id": "SQSYgZjfA3z", "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Achieved to date (%) - Benefits", + "name": "12345en - MyProject - Achieved total to date (%) - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2327,19 +2361,25 @@ "showData": true, "aggregationType": "DEFAULT", "legendDisplayStrategy": "FIXED", - "rowTotals": true, + "rowTotals": false, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "eCufXa6RkTm" + "id": "eYmeRzhBFV4" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "i01veyO4Cuw" + "id": "u404ICrBKj3" + } + }, + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "K4sH0aQDdeL" } } ], @@ -2370,118 +2410,15 @@ ], "columns": [ { - "id": "pe" + "id": "uSMHdwhxFSV", + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] } ], - "columnDimensions": ["pe"], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "dx" - } - ], - "rowDimensions": ["dx"], - "categoryDimensions": [], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } - }, - { - "id": "SQSYgZjfA3z", - "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Achieved total to date (%) - People", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": false, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - } - ], - "columns": [ - { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } - ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" @@ -4460,291 +4397,6 @@ } ] }, - { - "id": "ayOoqqk9Rnb", - "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Target vs Actual - Unique People", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": true, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "SQy5q6kCYI1" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "iYEDR850FFL" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "qkyeCTJHU2d" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "eAkVLI8mKBa" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "Kg29718LQHl" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "KKmUWsn19fq" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "iCKxYSFIlcu" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "qAM1NbCbS9G" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "K6mAC5SiO29" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "ik0ICagvIjm" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "GQyudNlGzkI" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - }, - { - "id": "TvSmIyYcRnd" - }, - { - "id": "cqZ9zQfePzQ" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - }, - { - "id": "201904" - }, - { - "id": "201905" - }, - { - "id": "201906" - }, - { - "id": "201907" - }, - { - "id": "201908" - }, - { - "id": "201909" - }, - { - "id": "201910" - }, - { - "id": "201911" - }, - { - "id": "201912" - }, - { - "id": "202001" - }, - { - "id": "202002" - }, - { - "id": "202003" - }, - { - "id": "202004" - }, - { - "id": "202005" - }, - { - "id": "202006" - }, - { - "id": "202007" - }, - { - "id": "202008" - }, - { - "id": "202009" - }, - { - "id": "202010" - } - ], - "columns": [ - { - "id": "pe" - }, - { - "code": "GENDER", - "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "MALE", - "id": "qk2FihwV6IL" - }, - { - "code": "FEMALE", - "id": "yW2hYVS3S4u" - } - ] - } - ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], - "filters": [ - { - "id": "ou" - }, - { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } - ], - "filterDimensions": ["ou", "uSMHdwhxFSV"], - "rows": [ - { - "id": "dx" - }, - { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", - "categoryOptions": [ - { - "code": "TARGET", - "id": "imyqCWQ229K" - }, - { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" - } - ] - } - ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], - "categoryDimensions": [ - { - "category": { - "id": "Kyg1O6YEGa9" - }, - "categoryOptions": [ - { - "id": "qk2FihwV6IL" - }, - { - "id": "yW2hYVS3S4u" - } - ] - }, - { - "category": { - "id": "GIIHAr9BzzO" - }, - "categoryOptions": [ - { - "id": "imyqCWQ229K" - }, - { - "id": "eWeQoOlAcxV" - } - ] - }, - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } - ], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ] - }, { "id": "ew6e1j5HwkE", "type": "PIVOT_TABLE", From 5f07094eb59a77dd7e25cbc935e4cb1d50adda0b Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 14:38:51 -0500 Subject: [PATCH 07/49] add chart Column Chart Disaggregated By Indicator --- src/models/ProjectDashboard.ts | 20 + src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 633 +++++++++++++++--- 3 files changed, 550 insertions(+), 105 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index fa120930..3cec9474 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -105,6 +105,10 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualBenefitsDisaggregatedByIndicatorChart() : undefined; + const targetVsActualPeopleDisaggregatedByIndicatorChart_ = + this.dashboardType === "project" + ? this.targetVsActualPeopleDisaggregatedByIndicatorChart() + : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -144,6 +148,7 @@ export default class ProjectDashboard { targetVsActualBenefitsTable_, targetVsActualPeopleTable_, targetVsActualBenefitsDisaggregatedByIndicatorChart_, + targetVsActualPeopleDisaggregatedByIndicatorChart_, targetVsActualBenefitsWithDisaggregationTable_, ]); const defaultVisualizations = _.concat( @@ -171,6 +176,7 @@ export default class ProjectDashboard { getReportTableItem(targetVsActualBenefitsTable_), getReportTableItem(targetVsActualPeopleTable_), getChartDashboardItem(targetVsActualBenefitsDisaggregatedByIndicatorChart_), + getChartDashboardItem(targetVsActualPeopleDisaggregatedByIndicatorChart_), getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), ]) : reportTables.map(reportTable => getReportTableItem(reportTable))), @@ -300,6 +306,20 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleDisaggregatedByIndicatorChart(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-target-actual-people-disaggregated-by-indicator", + name: i18n.t("Target vs Actual - People - Column Chart Disaggregated By Indicator"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, config.categories.gender, config.categories.newRecurring], + columns: [dimensions.data], + rows: [dimensions.period, config.categories.targetActual], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index e163b486..d19791c5 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index fc74e9f6..5b728c07 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1061,6 +1061,17 @@ "x": 29, "y": 40 }, + { + "id": "a4GacNVWHLX", + "type": "CHART", + "visualization": { + "id": "GA87u7JwgSK" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 60 + }, { "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", @@ -1069,7 +1080,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 60 }, { @@ -1080,8 +1091,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 60 + "x": 0, + "y": 80 }, { "id": "qMSWdZHPjyN", @@ -1091,7 +1102,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 80 }, { @@ -1102,8 +1113,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 80 + "x": 0, + "y": 100 }, { "id": "mgwFIMjbsdw", @@ -1113,7 +1124,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 100 }, { @@ -1475,7 +1486,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "dx" @@ -1484,13 +1497,18 @@ "id": "ou" } ], - "filterDimensions": ["dx", "ou"], + "filterDimensions": [ + "dx", + "ou" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -1603,7 +1621,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "dx" @@ -1642,13 +1662,20 @@ ] } ], - "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "dx", + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -1775,19 +1802,25 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -1882,13 +1915,17 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -1909,7 +1946,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -2004,19 +2044,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -2101,13 +2147,17 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "pe" @@ -2128,7 +2178,10 @@ ] } ], - "rowDimensions": ["pe", "GIIHAr9BzzO"], + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -2166,6 +2219,199 @@ } ] }, + { + "id": "GA87u7JwgSK", + "type": "COLUMN", + "name": "12345en - MyProject - Target vs Actual - People - Column Chart Disaggregated By Indicator", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "id": "dx" + } + ], + "columnDimensions": [ + "dx" + ], + "filters": [ + { + "id": "ou" + }, + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "pe" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", @@ -2244,13 +2490,18 @@ ] } ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], + "columnDimensions": [ + "pe", + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -2286,7 +2537,11 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" + ], "categoryDimensions": [ { "category": { @@ -2418,7 +2673,9 @@ ] } ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": [ + "uSMHdwhxFSV" + ], "filters": [ { "id": "ou" @@ -2427,13 +2684,18 @@ "id": "pe" } ], - "filterDimensions": ["ou", "pe"], + "filterDimensions": [ + "ou", + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -2529,19 +2791,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -2632,19 +2900,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -2740,7 +3014,9 @@ ] } ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": [ + "uSMHdwhxFSV" + ], "filters": [ { "id": "ou" @@ -2749,13 +3025,18 @@ "id": "pe" } ], - "filterDimensions": ["ou", "pe"], + "filterDimensions": [ + "ou", + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -2869,19 +3150,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -2962,19 +3249,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3061,7 +3354,9 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" @@ -3075,13 +3370,18 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -3191,7 +3491,9 @@ ] } ], - "columnDimensions": ["Kyg1O6YEGa9"], + "columnDimensions": [ + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" @@ -3208,13 +3510,19 @@ ] } ], - "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -3313,19 +3621,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3450,7 +3764,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "pe" @@ -3472,13 +3788,19 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV", "GIIHAr9BzzO"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV", + "GIIHAr9BzzO" + ], "rows": [ { "id": "ou" } ], - "rowDimensions": ["ou"], + "rowDimensions": [ + "ou" + ], "categoryDimensions": [ { "category": { @@ -3586,7 +3908,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "pe" @@ -3600,13 +3924,18 @@ ] } ], - "filterDimensions": ["pe", "GIIHAr9BzzO"], + "filterDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "rows": [ { "id": "ou" } ], - "rowDimensions": ["ou"], + "rowDimensions": [ + "ou" + ], "categoryDimensions": [ { "category": { @@ -3716,7 +4045,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -3738,13 +4069,19 @@ ] } ], - "filterDimensions": ["ou", "uSMHdwhxFSV", "GIIHAr9BzzO"], + "filterDimensions": [ + "ou", + "uSMHdwhxFSV", + "GIIHAr9BzzO" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -3846,7 +4183,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -3860,13 +4199,18 @@ ] } ], - "filterDimensions": ["ou", "GIIHAr9BzzO"], + "filterDimensions": [ + "ou", + "GIIHAr9BzzO" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -4037,13 +4381,17 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -4064,7 +4412,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -4291,13 +4642,18 @@ ] } ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], + "columnDimensions": [ + "pe", + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -4333,7 +4689,11 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" + ], "categoryDimensions": [ { "category": { @@ -4553,19 +4913,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4772,7 +5138,9 @@ ] } ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": [ + "uSMHdwhxFSV" + ], "filters": [ { "id": "ou" @@ -4781,13 +5149,18 @@ "id": "pe" } ], - "filterDimensions": ["ou", "pe"], + "filterDimensions": [ + "ou", + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -4982,19 +5355,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -5196,19 +5575,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -5415,7 +5800,9 @@ ] } ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": [ + "uSMHdwhxFSV" + ], "filters": [ { "id": "ou" @@ -5424,13 +5811,18 @@ "id": "pe" } ], - "filterDimensions": ["ou", "pe"], + "filterDimensions": [ + "ou", + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -5691,19 +6083,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -5883,19 +6281,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6093,7 +6497,9 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" @@ -6107,13 +6513,18 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -6334,7 +6745,9 @@ ] } ], - "columnDimensions": ["Kyg1O6YEGa9"], + "columnDimensions": [ + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" @@ -6351,13 +6764,19 @@ ] } ], - "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -6519,19 +6938,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6556,4 +6981,4 @@ ] } ] -} +} \ No newline at end of file From 4354b7f4c3bbead654d6c5078457243bcbaa617d Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 15:08:39 -0500 Subject: [PATCH 08/49] add chart Target vs Actual - Benefits - Line Chart --- src/models/Dashboard.ts | 5 +- src/models/ProjectDashboard.ts | 22 +++ src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 166 ++++++++++++++++-- 4 files changed, 180 insertions(+), 15 deletions(-) diff --git a/src/models/Dashboard.ts b/src/models/Dashboard.ts index 1af05985..627633f4 100644 --- a/src/models/Dashboard.ts +++ b/src/models/Dashboard.ts @@ -29,6 +29,9 @@ interface Item { export interface VisualizationDefinition { type: "chart" | "table"; + // TODO: validate if having undefined for the other visualizations + // modify somehow the functionality + chartType?: Exclude; key: string; name: string; items: Item[]; @@ -84,7 +87,7 @@ export function getD2Visualization(visualization: Visualization): MaybeD2Visuali const d2Table: PartialPersistedModel = { id: getUid(visualization.key, ""), - type: visualization.type === "table" ? "PIVOT_TABLE" : "COLUMN", + type: visualization.type === "table" ? "PIVOT_TABLE" : visualization.chartType || "COLUMN", name: visualization.name, numberType: "VALUE", legendDisplayStyle: "FILL", diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 3cec9474..184b93e5 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -109,6 +109,8 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualPeopleDisaggregatedByIndicatorChart() : undefined; + const targetVsActualBenefitsLineChart_ = + this.dashboardType === "project" ? this.targetVsActualBenefitsLineChart() : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -149,6 +151,7 @@ export default class ProjectDashboard { targetVsActualPeopleTable_, targetVsActualBenefitsDisaggregatedByIndicatorChart_, targetVsActualPeopleDisaggregatedByIndicatorChart_, + targetVsActualBenefitsLineChart_, targetVsActualBenefitsWithDisaggregationTable_, ]); const defaultVisualizations = _.concat( @@ -177,6 +180,7 @@ export default class ProjectDashboard { getReportTableItem(targetVsActualPeopleTable_), getChartDashboardItem(targetVsActualBenefitsDisaggregatedByIndicatorChart_), getChartDashboardItem(targetVsActualPeopleDisaggregatedByIndicatorChart_), + getChartDashboardItem(targetVsActualBenefitsLineChart_), getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), ]) : reportTables.map(reportTable => getReportTableItem(reportTable))), @@ -320,6 +324,24 @@ export default class ProjectDashboard { }); } + targetVsActualBenefitsLineChart(): MaybeD2Visualization { + const { config, dataElements } = this; + const dataElementsNoDisaggregated = dataElements.benefit.filter( + de => !de.categories.includes("newRecurring") + ); + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-benefits-line", + name: i18n.t("Target vs Actual - Benefits - Line Chart"), + items: dataElementItems(dataElementsNoDisaggregated), + filters: [dimensions.orgUnit], + columns: [config.categories.targetActual], + rows: [dimensions.data, dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index d19791c5..b705a906 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 5b728c07..9f72bfc1 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1072,6 +1072,17 @@ "x": 0, "y": 60 }, + { + "id": "KYcDaXAZa1q", + "type": "CHART", + "visualization": { + "id": "KiUTxsMMYde" + }, + "width": 29, + "height": 20, + "x": 29, + "y": 60 + }, { "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", @@ -1080,8 +1091,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 60 + "x": 0, + "y": 80 }, { "id": "ywvTGMsKdwL", @@ -1091,7 +1102,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 80 }, { @@ -1102,8 +1113,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 80 + "x": 0, + "y": 100 }, { "id": "uyoJujQVRjE", @@ -1113,7 +1124,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 100 }, { @@ -1124,8 +1135,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 100 + "x": 0, + "y": 120 }, { "id": "ys0CVedHirZ", @@ -1136,7 +1147,7 @@ "width": 58, "height": 20, "x": 0, - "y": 120 + "y": 140 }, { "id": "KI0C90Ol10x", @@ -1147,7 +1158,7 @@ "width": 29, "height": 20, "x": 0, - "y": 140 + "y": 160 }, { "id": "uYY7v977Ubm", @@ -1158,7 +1169,7 @@ "width": 29, "height": 20, "x": 29, - "y": 140 + "y": 160 }, { "id": "qUqsDmtiBLF", @@ -1169,7 +1180,7 @@ "width": 29, "height": 20, "x": 0, - "y": 160 + "y": 180 }, { "id": "mwMpIdPdu8H", @@ -1180,7 +1191,7 @@ "width": 29, "height": 20, "x": 29, - "y": 160 + "y": 180 } ], "publicAccess": "--------", @@ -2412,6 +2423,135 @@ } ] }, + { + "id": "KiUTxsMMYde", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - Benefits - Line Chart", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WS8XV4WWPE7" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": [ + "GIIHAr9BzzO" + ], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": [ + "ou" + ], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": [ + "dx", + "pe" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", From e97d3957e4ead4021264139a922fc87861724d3e Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 15:53:27 -0500 Subject: [PATCH 09/49] add chart Target vs Actual - People - Line Chart --- src/models/ProjectDashboard.ts | 19 ++ src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 218 +++++++++++++++++- 3 files changed, 231 insertions(+), 8 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 184b93e5..e50ffa85 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -111,6 +111,8 @@ export default class ProjectDashboard { : undefined; const targetVsActualBenefitsLineChart_ = this.dashboardType === "project" ? this.targetVsActualBenefitsLineChart() : undefined; + const targetVsActualPeopleLineChart_ = + this.dashboardType === "project" ? this.targetVsActualPeopleLineChart() : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -152,6 +154,7 @@ export default class ProjectDashboard { targetVsActualBenefitsDisaggregatedByIndicatorChart_, targetVsActualPeopleDisaggregatedByIndicatorChart_, targetVsActualBenefitsLineChart_, + targetVsActualPeopleLineChart_, targetVsActualBenefitsWithDisaggregationTable_, ]); const defaultVisualizations = _.concat( @@ -181,6 +184,7 @@ export default class ProjectDashboard { getChartDashboardItem(targetVsActualBenefitsDisaggregatedByIndicatorChart_), getChartDashboardItem(targetVsActualPeopleDisaggregatedByIndicatorChart_), getChartDashboardItem(targetVsActualBenefitsLineChart_), + getChartDashboardItem(targetVsActualPeopleLineChart_), getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), ]) : reportTables.map(reportTable => getReportTableItem(reportTable))), @@ -342,6 +346,21 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleLineChart(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-people-line", + name: i18n.t("Target vs Actual - People - Line Chart"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, config.categories.gender, config.categories.newRecurring], + columns: [config.categories.targetActual], + rows: [dimensions.data, dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index b705a906..798cb804 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 9f72bfc1..9e8a9f8d 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1083,6 +1083,17 @@ "x": 29, "y": 60 }, + { + "id": "a6cSVlR6bSj", + "type": "CHART", + "visualization": { + "id": "GkoTRBEmIQt" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 80 + }, { "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", @@ -1091,7 +1102,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 80 }, { @@ -1102,8 +1113,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 80 + "x": 0, + "y": 100 }, { "id": "qMSWdZHPjyN", @@ -1113,7 +1124,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 100 }, { @@ -1124,8 +1135,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 100 + "x": 0, + "y": 120 }, { "id": "mgwFIMjbsdw", @@ -1135,7 +1146,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 120 }, { @@ -2552,6 +2563,199 @@ } ] }, + { + "id": "GkoTRBEmIQt", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": [ + "GIIHAr9BzzO" + ], + "filters": [ + { + "id": "ou" + }, + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": [ + "dx", + "pe" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", From 4e396835b3c37f92e2d3de29a5bc6b86b04e5b15 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 16:03:53 -0500 Subject: [PATCH 10/49] add chart Line Chart - Male Only --- src/models/ProjectDashboard.ts | 27 +++ src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 220 ++++++++++++++++-- 3 files changed, 235 insertions(+), 14 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index e50ffa85..9be7aeba 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -34,6 +34,7 @@ export default class ProjectDashboard { dataElements: ProjectsListDashboard["dataElements"]; merDataElements: Record<"all" | "people" | "benefit", Ref[]>; categoryOnlyNew: { id: Id; categoryOptions: Ref[] }; + categoryOnlyMale: { id: Id; categoryOptions: Ref[] }; constructor( private config: Config, @@ -58,6 +59,11 @@ export default class ProjectDashboard { categoryOptions: [{ id: config.categoryOptions.new.id }], }; + this.categoryOnlyMale = { + id: config.categories.gender.id, + categoryOptions: [{ id: config.categoryOptions.male.id }], + }; + this.config = config; } @@ -113,6 +119,10 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualBenefitsLineChart() : undefined; const targetVsActualPeopleLineChart_ = this.dashboardType === "project" ? this.targetVsActualPeopleLineChart() : undefined; + const targetVsActualPeopleLineChartMaleOnly_ = + this.dashboardType === "project" + ? this.targetVsActualPeopleLineChartMaleOnly() + : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -155,6 +165,7 @@ export default class ProjectDashboard { targetVsActualPeopleDisaggregatedByIndicatorChart_, targetVsActualBenefitsLineChart_, targetVsActualPeopleLineChart_, + targetVsActualPeopleLineChartMaleOnly_, targetVsActualBenefitsWithDisaggregationTable_, ]); const defaultVisualizations = _.concat( @@ -185,6 +196,7 @@ export default class ProjectDashboard { getChartDashboardItem(targetVsActualPeopleDisaggregatedByIndicatorChart_), getChartDashboardItem(targetVsActualBenefitsLineChart_), getChartDashboardItem(targetVsActualPeopleLineChart_), + getChartDashboardItem(targetVsActualPeopleLineChartMaleOnly_), getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), ]) : reportTables.map(reportTable => getReportTableItem(reportTable))), @@ -361,6 +373,21 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleLineChartMaleOnly(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-people-line-male-only", + name: i18n.t("Target vs Actual - People - Line Chart - Male Only"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, this.categoryOnlyMale, config.categories.newRecurring], + columns: [config.categories.targetActual], + rows: [dimensions.data, dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 798cb804..579371a9 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 9e8a9f8d..d6e0be20 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1094,6 +1094,17 @@ "x": 0, "y": 80 }, + { + "id": "W4DOghdXUmp", + "type": "CHART", + "visualization": { + "id": "S2kJHgM41El" + }, + "width": 29, + "height": 20, + "x": 29, + "y": 80 + }, { "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", @@ -1102,8 +1113,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 80 + "x": 0, + "y": 100 }, { "id": "ywvTGMsKdwL", @@ -1113,7 +1124,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 100 }, { @@ -1124,8 +1135,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 100 + "x": 0, + "y": 120 }, { "id": "uyoJujQVRjE", @@ -1135,7 +1146,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 120 }, { @@ -1146,8 +1157,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 120 + "x": 0, + "y": 140 }, { "id": "ys0CVedHirZ", @@ -1158,7 +1169,7 @@ "width": 58, "height": 20, "x": 0, - "y": 140 + "y": 160 }, { "id": "KI0C90Ol10x", @@ -1169,7 +1180,7 @@ "width": 29, "height": 20, "x": 0, - "y": 160 + "y": 180 }, { "id": "uYY7v977Ubm", @@ -1180,7 +1191,7 @@ "width": 29, "height": 20, "x": 29, - "y": 160 + "y": 180 }, { "id": "qUqsDmtiBLF", @@ -1191,7 +1202,7 @@ "width": 29, "height": 20, "x": 0, - "y": 180 + "y": 200 }, { "id": "mwMpIdPdu8H", @@ -1202,7 +1213,7 @@ "width": 29, "height": 20, "x": 29, - "y": 180 + "y": 200 } ], "publicAccess": "--------", @@ -2756,6 +2767,189 @@ } ] }, + { + "id": "S2kJHgM41El", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Male Only", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": [ + "GIIHAr9BzzO" + ], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": [ + "dx", + "pe" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", From f9301808f78676b8145d790b18415c3ccee6de07 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 16:08:21 -0500 Subject: [PATCH 11/49] add chart female only --- src/models/ProjectDashboard.ts | 26 +++ src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 208 +++++++++++++++++- 3 files changed, 228 insertions(+), 8 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 9be7aeba..75e78c09 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -35,6 +35,7 @@ export default class ProjectDashboard { merDataElements: Record<"all" | "people" | "benefit", Ref[]>; categoryOnlyNew: { id: Id; categoryOptions: Ref[] }; categoryOnlyMale: { id: Id; categoryOptions: Ref[] }; + categoryOnlyFemale: { id: Id; categoryOptions: Ref[] }; constructor( private config: Config, @@ -63,6 +64,10 @@ export default class ProjectDashboard { id: config.categories.gender.id, categoryOptions: [{ id: config.categoryOptions.male.id }], }; + this.categoryOnlyFemale = { + id: config.categories.gender.id, + categoryOptions: [{ id: config.categoryOptions.female.id }], + }; this.config = config; } @@ -123,6 +128,10 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualPeopleLineChartMaleOnly() : undefined; + const targetVsActualPeopleLineChartFemaleOnly_ = + this.dashboardType === "project" + ? this.targetVsActualPeopleLineChartFemaleOnly() + : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -166,6 +175,7 @@ export default class ProjectDashboard { targetVsActualBenefitsLineChart_, targetVsActualPeopleLineChart_, targetVsActualPeopleLineChartMaleOnly_, + targetVsActualPeopleLineChartFemaleOnly_, targetVsActualBenefitsWithDisaggregationTable_, ]); const defaultVisualizations = _.concat( @@ -197,6 +207,7 @@ export default class ProjectDashboard { getChartDashboardItem(targetVsActualBenefitsLineChart_), getChartDashboardItem(targetVsActualPeopleLineChart_), getChartDashboardItem(targetVsActualPeopleLineChartMaleOnly_), + getChartDashboardItem(targetVsActualPeopleLineChartFemaleOnly_), getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), ]) : reportTables.map(reportTable => getReportTableItem(reportTable))), @@ -388,6 +399,21 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleLineChartFemaleOnly(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-people-line-female-only", + name: i18n.t("Target vs Actual - People - Line Chart - Female Only"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, this.categoryOnlyFemale, config.categories.newRecurring], + columns: [config.categories.targetActual], + rows: [dimensions.data, dimensions.period], + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 579371a9..4b9f629d 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index d6e0be20..325d0b9a 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1105,6 +1105,17 @@ "x": 29, "y": 80 }, + { + "id": "OgO4mL6ovvU", + "type": "CHART", + "visualization": { + "id": "KasxZ8vT1n0" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 100 + }, { "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", @@ -1113,7 +1124,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 100 }, { @@ -1124,8 +1135,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 100 + "x": 0, + "y": 120 }, { "id": "qMSWdZHPjyN", @@ -1135,7 +1146,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 120 }, { @@ -1146,8 +1157,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 120 + "x": 0, + "y": 140 }, { "id": "mgwFIMjbsdw", @@ -1157,7 +1168,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 140 }, { @@ -2950,6 +2961,189 @@ } ] }, + { + "id": "KasxZ8vT1n0", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Female Only", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": [ + "GIIHAr9BzzO" + ], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": [ + "dx", + "pe" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, { "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", From e2a463d7fc4b3051574a5810a5e36a70eae754a1 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 16:21:00 -0500 Subject: [PATCH 12/49] add chart Target vs Actual - People - Line/Column Chart - Male Only --- src/models/ProjectDashboard.ts | 31 +++ src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 231 +++++++++++++++++- 3 files changed, 250 insertions(+), 14 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 75e78c09..c43f65d0 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -132,6 +132,10 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualPeopleLineChartFemaleOnly() : undefined; + const targetVsActualPeopleLineColumnChartMaleOnly_ = + this.dashboardType === "project" + ? this.targetVsActualPeopleLineColumnChartMaleOnly() + : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -176,6 +180,7 @@ export default class ProjectDashboard { targetVsActualPeopleLineChart_, targetVsActualPeopleLineChartMaleOnly_, targetVsActualPeopleLineChartFemaleOnly_, + targetVsActualPeopleLineColumnChartMaleOnly_, targetVsActualBenefitsWithDisaggregationTable_, ]); const defaultVisualizations = _.concat( @@ -208,6 +213,7 @@ export default class ProjectDashboard { getChartDashboardItem(targetVsActualPeopleLineChart_), getChartDashboardItem(targetVsActualPeopleLineChartMaleOnly_), getChartDashboardItem(targetVsActualPeopleLineChartFemaleOnly_), + getChartDashboardItem(targetVsActualPeopleLineColumnChartMaleOnly_), getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), ]) : reportTables.map(reportTable => getReportTableItem(reportTable))), @@ -414,6 +420,31 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleLineColumnChartMaleOnly(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-people-line-column-male-only", + name: i18n.t("Target vs Actual - People - Line/Column Chart - Male Only"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, this.categoryOnlyMale, config.categories.newRecurring], + columns: [config.categories.targetActual], + rows: [dimensions.data, dimensions.period], + extra: { + series: [ + { dimensionItem: config.categoryOptions.target.id, axis: 0 }, + { + dimensionItem: config.categoryOptions.actual.id, + axis: 0, + type: "COLUMN", + }, + ], + }, + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 4b9f629d..4e9cd9eb 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 325d0b9a..abdc71c7 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1116,6 +1116,17 @@ "x": 0, "y": 100 }, + { + "id": "K2amO1SBZFm", + "type": "CHART", + "visualization": { + "id": "W2SCFrHCiEm" + }, + "width": 29, + "height": 20, + "x": 29, + "y": 100 + }, { "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", @@ -1124,8 +1135,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 100 + "x": 0, + "y": 120 }, { "id": "ywvTGMsKdwL", @@ -1135,7 +1146,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 120 }, { @@ -1146,8 +1157,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 120 + "x": 0, + "y": 140 }, { "id": "uyoJujQVRjE", @@ -1157,7 +1168,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 140 }, { @@ -1168,8 +1179,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 140 + "x": 0, + "y": 160 }, { "id": "ys0CVedHirZ", @@ -1180,7 +1191,7 @@ "width": 58, "height": 20, "x": 0, - "y": 160 + "y": 180 }, { "id": "KI0C90Ol10x", @@ -1191,7 +1202,7 @@ "width": 29, "height": 20, "x": 0, - "y": 180 + "y": 200 }, { "id": "uYY7v977Ubm", @@ -1202,7 +1213,7 @@ "width": 29, "height": 20, "x": 29, - "y": 180 + "y": 200 }, { "id": "qUqsDmtiBLF", @@ -1213,7 +1224,7 @@ "width": 29, "height": 20, "x": 0, - "y": 200 + "y": 220 }, { "id": "mwMpIdPdu8H", @@ -1224,7 +1235,7 @@ "width": 29, "height": 20, "x": 29, - "y": 200 + "y": 220 } ], "publicAccess": "--------", @@ -3144,6 +3155,200 @@ } ] }, + { + "id": "W2SCFrHCiEm", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line/Column Chart - Male Only", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": [ + "GIIHAr9BzzO" + ], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": [ + "dx", + "pe" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ], + "series": [ + { + "dimensionItem": "imyqCWQ229K", + "axis": 0 + }, + { + "dimensionItem": "eWeQoOlAcxV", + "axis": 0, + "type": "COLUMN" + } + ] + }, { "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", From 4192374fce7a9b1d5e27acc1a2c0a10c94fcf468 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 16:43:48 -0500 Subject: [PATCH 13/49] add chart People - Line/Column Chart - Female Only --- src/models/ProjectDashboard.ts | 33 +- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 717 ++++++++---------- 3 files changed, 353 insertions(+), 399 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index c43f65d0..5b99f25e 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -136,6 +136,10 @@ export default class ProjectDashboard { this.dashboardType === "project" ? this.targetVsActualPeopleLineColumnChartMaleOnly() : undefined; + const targetVsActualPeopleLineColumnChartFemaleOnly_ = + this.dashboardType === "project" + ? this.targetVsActualPeopleLineColumnChartFemaleOnly() + : undefined; const reportTables: Array> = _.compact([ // General Data View @@ -181,6 +185,7 @@ export default class ProjectDashboard { targetVsActualPeopleLineChartMaleOnly_, targetVsActualPeopleLineChartFemaleOnly_, targetVsActualPeopleLineColumnChartMaleOnly_, + targetVsActualPeopleLineColumnChartFemaleOnly_, targetVsActualBenefitsWithDisaggregationTable_, ]); const defaultVisualizations = _.concat( @@ -214,6 +219,7 @@ export default class ProjectDashboard { getChartDashboardItem(targetVsActualPeopleLineChartMaleOnly_), getChartDashboardItem(targetVsActualPeopleLineChartFemaleOnly_), getChartDashboardItem(targetVsActualPeopleLineColumnChartMaleOnly_), + getChartDashboardItem(targetVsActualPeopleLineColumnChartFemaleOnly_), getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), ]) : reportTables.map(reportTable => getReportTableItem(reportTable))), @@ -445,6 +451,31 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleLineColumnChartFemaleOnly(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-people-line-column-female-only", + name: i18n.t("Target vs Actual - People - Line/Column Chart - Female Only"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, this.categoryOnlyFemale, config.categories.newRecurring], + columns: [config.categories.targetActual], + rows: [dimensions.data, dimensions.period], + extra: { + series: [ + { dimensionItem: config.categoryOptions.target.id, axis: 0 }, + { + dimensionItem: config.categoryOptions.actual.id, + axis: 0, + type: "COLUMN", + }, + ], + }, + }); + } + targetVsActualBenefitsWithDisaggregationTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsDisaggregated = dataElements.benefit.filter(de => @@ -516,7 +547,7 @@ export default class ProjectDashboard { return this.getD2VisualizationFromDefinition({ type: "table", key: "reportTable-indicators-people", - name: i18n.t("Achieved (%) - People"), + name: i18n.t("Achieved to date (%) - People"), items: indicatorItems(indicators), filters: [dimensions.orgUnit], columns: [dimensions.period], diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 4e9cd9eb..d3fda2c6 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -140,7 +140,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,OuKm5zK7l53,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index abdc71c7..94e907a2 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1127,6 +1127,17 @@ "x": 29, "y": 100 }, + { + "id": "GW6MALzFIVR", + "type": "CHART", + "visualization": { + "id": "OuKm5zK7l53" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 120 + }, { "id": "yWGKgz9vaOh", "type": "REPORT_TABLE", @@ -1135,7 +1146,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 120 }, { @@ -1146,8 +1157,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 120 + "x": 0, + "y": 140 }, { "id": "qMSWdZHPjyN", @@ -1157,7 +1168,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 140 }, { @@ -1168,8 +1179,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 140 + "x": 0, + "y": 160 }, { "id": "mgwFIMjbsdw", @@ -1179,7 +1190,7 @@ }, "width": 29, "height": 20, - "x": 0, + "x": 29, "y": 160 }, { @@ -1541,9 +1552,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "dx" @@ -1552,18 +1561,13 @@ "id": "ou" } ], - "filterDimensions": [ - "dx", - "ou" - ], + "filterDimensions": ["dx", "ou"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1676,9 +1680,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "dx" @@ -1717,20 +1719,13 @@ ] } ], - "filterDimensions": [ - "dx", - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1857,25 +1852,19 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1970,17 +1959,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2001,10 +1986,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2099,25 +2081,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -2202,17 +2178,13 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "pe" @@ -2233,10 +2205,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2337,9 +2306,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -2375,11 +2342,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "pe" @@ -2400,10 +2363,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2536,17 +2496,13 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2555,10 +2511,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -2671,9 +2624,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -2709,11 +2660,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -2722,10 +2669,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -2864,9 +2808,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -2895,11 +2837,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -2908,10 +2846,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3047,9 +2982,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3078,11 +3011,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3091,10 +3020,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3230,9 +3156,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3261,11 +3185,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3274,10 +3194,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3349,6 +3266,191 @@ } ] }, + { + "id": "OuKm5zK7l53", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line/Column Chart - Female Only", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": ["GIIHAr9BzzO"], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": ["dx", "pe"], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ], + "series": [ + { + "dimensionItem": "imyqCWQ229K", + "axis": 0 + }, + { + "dimensionItem": "eWeQoOlAcxV", + "axis": 0, + "type": "COLUMN" + } + ] + }, { "id": "iqqgnCj9DQj", "type": "PIVOT_TABLE", @@ -3427,18 +3529,13 @@ ] } ], - "columnDimensions": [ - "pe", - "Kyg1O6YEGa9" - ], + "columnDimensions": ["pe", "Kyg1O6YEGa9"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -3474,11 +3571,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -3610,9 +3703,7 @@ ] } ], - "columnDimensions": [ - "uSMHdwhxFSV" - ], + "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" @@ -3621,18 +3712,13 @@ "id": "pe" } ], - "filterDimensions": [ - "ou", - "pe" - ], + "filterDimensions": ["ou", "pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -3728,25 +3814,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3777,7 +3857,7 @@ { "id": "GM6SxObVwI3", "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Achieved (%) - People", + "name": "12345en - MyProject - Achieved to date (%) - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -3837,25 +3917,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3951,9 +4025,7 @@ ] } ], - "columnDimensions": [ - "uSMHdwhxFSV" - ], + "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" @@ -3962,18 +4034,13 @@ "id": "pe" } ], - "filterDimensions": [ - "ou", - "pe" - ], + "filterDimensions": ["ou", "pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -4087,25 +4154,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4186,25 +4247,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4291,9 +4346,7 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" @@ -4307,18 +4360,13 @@ ] } ], - "filterDimensions": [ - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -4428,9 +4476,7 @@ ] } ], - "columnDimensions": [ - "Kyg1O6YEGa9" - ], + "columnDimensions": ["Kyg1O6YEGa9"], "filters": [ { "id": "ou" @@ -4447,19 +4493,13 @@ ] } ], - "filterDimensions": [ - "ou", - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -4558,25 +4598,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4701,9 +4735,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "pe" @@ -4725,19 +4757,13 @@ ] } ], - "filterDimensions": [ - "pe", - "uSMHdwhxFSV", - "GIIHAr9BzzO" - ], + "filterDimensions": ["pe", "uSMHdwhxFSV", "GIIHAr9BzzO"], "rows": [ { "id": "ou" } ], - "rowDimensions": [ - "ou" - ], + "rowDimensions": ["ou"], "categoryDimensions": [ { "category": { @@ -4845,9 +4871,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "pe" @@ -4861,18 +4885,13 @@ ] } ], - "filterDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "filterDimensions": ["pe", "GIIHAr9BzzO"], "rows": [ { "id": "ou" } ], - "rowDimensions": [ - "ou" - ], + "rowDimensions": ["ou"], "categoryDimensions": [ { "category": { @@ -4982,9 +5001,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -5006,19 +5023,13 @@ ] } ], - "filterDimensions": [ - "ou", - "uSMHdwhxFSV", - "GIIHAr9BzzO" - ], + "filterDimensions": ["ou", "uSMHdwhxFSV", "GIIHAr9BzzO"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -5120,9 +5131,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -5136,18 +5145,13 @@ ] } ], - "filterDimensions": [ - "ou", - "GIIHAr9BzzO" - ], + "filterDimensions": ["ou", "GIIHAr9BzzO"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -5318,17 +5322,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -5349,10 +5349,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -5579,18 +5576,13 @@ ] } ], - "columnDimensions": [ - "pe", - "Kyg1O6YEGa9" - ], + "columnDimensions": ["pe", "Kyg1O6YEGa9"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -5626,11 +5618,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -5850,25 +5838,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6075,9 +6057,7 @@ ] } ], - "columnDimensions": [ - "uSMHdwhxFSV" - ], + "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" @@ -6086,18 +6066,13 @@ "id": "pe" } ], - "filterDimensions": [ - "ou", - "pe" - ], + "filterDimensions": ["ou", "pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -6292,25 +6267,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6341,7 +6310,7 @@ { "id": "i6CWRJp61Hp", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved (%) - People", + "name": "Award Number 12345 - Achieved to date (%) - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6512,25 +6481,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6737,9 +6700,7 @@ ] } ], - "columnDimensions": [ - "uSMHdwhxFSV" - ], + "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" @@ -6748,18 +6709,13 @@ "id": "pe" } ], - "filterDimensions": [ - "ou", - "pe" - ], + "filterDimensions": ["ou", "pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -7020,25 +6976,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -7218,25 +7168,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -7434,9 +7378,7 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" @@ -7450,18 +7392,13 @@ ] } ], - "filterDimensions": [ - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -7682,9 +7619,7 @@ ] } ], - "columnDimensions": [ - "Kyg1O6YEGa9" - ], + "columnDimensions": ["Kyg1O6YEGa9"], "filters": [ { "id": "ou" @@ -7701,19 +7636,13 @@ ] } ], - "filterDimensions": [ - "ou", - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -7875,25 +7804,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -7918,4 +7841,4 @@ ] } ] -} \ No newline at end of file +} From 9466a4d636e44ddab2b139274af354d19cf436d1 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 17:05:42 -0500 Subject: [PATCH 14/49] remove chart achieved monthly --- i18n/en.pot | 2 +- src/models/ProjectDashboard.ts | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index 3a47a310..ea145b57 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -609,7 +609,7 @@ msgstr "" msgid "Achieved (%) - Benefits" msgstr "" -msgid "Achieved (%) - People" +msgid "Achieved to date (%) - People" msgstr "" msgid "Achieved total to date (%) - People" diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 5b99f25e..77259979 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -163,7 +163,6 @@ export default class ProjectDashboard { this.costBenefitTable(), ]); - const achievedMonthlyChart_ = this.achievedMonthlyChart(); const [ targetVsActualBenefitsTable_, targetVsActualBenefitsWithDisaggregationTable_, @@ -188,18 +187,11 @@ export default class ProjectDashboard { targetVsActualPeopleLineColumnChartFemaleOnly_, targetVsActualBenefitsWithDisaggregationTable_, ]); - const defaultVisualizations = _.concat( - reportTables, - _.compact([achievedMonthlyChart_, ...charts]) - ); + const defaultVisualizations = _.concat(reportTables, _.compact(charts)); const favorites = { visualizations: this.dashboardType === "project" - ? _.concat( - projectVisualizations, - otherReportTables, - _.compact([achievedMonthlyChart_, ...charts]) - ) + ? _.concat(projectVisualizations, otherReportTables, _.compact(charts)) : defaultVisualizations, }; @@ -226,7 +218,6 @@ export default class ProjectDashboard { ...(this.dashboardType === "project" ? otherReportTables.map(reportTable => getReportTableItem(reportTable)) : []), - getChartDashboardItem(achievedMonthlyChart_, { width: toItemWidth(100) }), ...charts.map(chart => getChartDashboardItem(chart)), ]); From 1f2f653450eb887f4a0cdbd6f13f240b9892d214 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Sat, 14 Mar 2026 17:33:49 -0500 Subject: [PATCH 15/49] fix visualizations order --- src/models/ProjectDashboard.ts | 99 +- src/models/__tests__/ProjectDb.spec.ts | 9 +- .../__tests__/data/project-db-metadata.json | 1957 +++++++---------- 3 files changed, 870 insertions(+), 1195 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 77259979..a6aadc03 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -101,59 +101,78 @@ export default class ProjectDashboard { if (!_.isNil(minimumOrgUnits) && projectsListDashboard.orgUnits.length < minimumOrgUnits) return { dashboards: [], visualizations: [] }; - // Note: I think this.dashboardType === "project" is the same as the condition for minimumOrgUnits = 2 - // I'll need to check that before doing the PR - const targetVsActualBenefitsChart_ = this.dashboardType === "project" ? this.targetVsActualBenefitsChart() : undefined; + const targetVsActualPeopleChart_ = this.dashboardType === "project" ? this.targetVsActualPeopleChart() : undefined; + const merTargetVsActualBenefitsChart_ = this.dashboardType === "project" ? this.merTargetVsActualBenefitsChart() : undefined; + const merTargetVsActualPeopleChart_ = this.dashboardType === "project" ? this.merTargetVsActualPeopleChart() : undefined; + const targetVsActualBenefitsDisaggregatedByIndicatorChart_ = this.dashboardType === "project" ? this.targetVsActualBenefitsDisaggregatedByIndicatorChart() : undefined; + const targetVsActualPeopleDisaggregatedByIndicatorChart_ = this.dashboardType === "project" ? this.targetVsActualPeopleDisaggregatedByIndicatorChart() : undefined; + const targetVsActualBenefitsLineChart_ = this.dashboardType === "project" ? this.targetVsActualBenefitsLineChart() : undefined; + const targetVsActualPeopleLineChart_ = this.dashboardType === "project" ? this.targetVsActualPeopleLineChart() : undefined; + const targetVsActualPeopleLineChartMaleOnly_ = this.dashboardType === "project" ? this.targetVsActualPeopleLineChartMaleOnly() : undefined; + const targetVsActualPeopleLineChartFemaleOnly_ = this.dashboardType === "project" ? this.targetVsActualPeopleLineChartFemaleOnly() : undefined; + const targetVsActualPeopleLineColumnChartMaleOnly_ = this.dashboardType === "project" ? this.targetVsActualPeopleLineColumnChartMaleOnly() : undefined; + const targetVsActualPeopleLineColumnChartFemaleOnly_ = this.dashboardType === "project" ? this.targetVsActualPeopleLineColumnChartFemaleOnly() : undefined; + const targetVsActualBenefitsTable_ = this.targetVsActualBenefitsTable(); + const targetVsActualBenefitsWithDisaggregationTable_ = + this.targetVsActualBenefitsWithDisaggregationTable(); + const targetVsActualPeopleTable_ = this.targetVsActualPeopleTable(); + const achievedBenefitsToDateTable_ = this.achievedBenefitsTable({ toDate: true }); + const achievedBenefitsTotalToDateTable_ = this.achievedBenefitsTotalToDateTable(); + const achievedPeopleTotalToDateTable_ = this.achievedPeopleTotalTable({ toDate: true }); + const achievedBenefitsTable_ = this.achievedBenefitsTable(); + const achievedPeopleToDateTable_ = this.achievedPeopleTable(); + const achievedPeopleTotalTable_ = this.achievedPeopleTotalTable(); + const reportTables: Array> = _.compact([ // General Data View - this.targetVsActualBenefitsTable(), - this.targetVsActualBenefitsWithDisaggregationTable(), - this.targetVsActualPeopleTable(), + targetVsActualBenefitsTable_, + targetVsActualBenefitsWithDisaggregationTable_, + targetVsActualPeopleTable_, // Percent achieved (to date) - this.achievedBenefitsTable({ toDate: true }), - this.achievedBenefitsTotalToDateTable(), - this.achievedPeopleTotalTable({ toDate: true }), + achievedBenefitsToDateTable_, + achievedBenefitsTotalToDateTable_, + achievedPeopleTotalToDateTable_, // Percent achieved - this.achievedBenefitsTable(), - this.achievedPeopleTable(), - this.achievedPeopleTotalTable(), + achievedBenefitsTable_, + achievedPeopleToDateTable_, + achievedPeopleTotalTable_, ]); const charts: Array> = _.compact([ @@ -163,13 +182,6 @@ export default class ProjectDashboard { this.costBenefitTable(), ]); - const [ - targetVsActualBenefitsTable_, - targetVsActualBenefitsWithDisaggregationTable_, - targetVsActualPeopleTable_, - ] = reportTables; - const otherReportTables = reportTables.slice(3); - const projectVisualizations = _.compact([ targetVsActualBenefitsChart_, targetVsActualPeopleChart_, @@ -185,41 +197,24 @@ export default class ProjectDashboard { targetVsActualPeopleLineChartFemaleOnly_, targetVsActualPeopleLineColumnChartMaleOnly_, targetVsActualPeopleLineColumnChartFemaleOnly_, - targetVsActualBenefitsWithDisaggregationTable_, + achievedBenefitsToDateTable_, + achievedPeopleToDateTable_, + ...charts, ]); + const defaultVisualizations = _.concat(reportTables, _.compact(charts)); - const favorites = { - visualizations: - this.dashboardType === "project" - ? _.concat(projectVisualizations, otherReportTables, _.compact(charts)) - : defaultVisualizations, - }; - const items: Array> = _.compact([ - ...(this.dashboardType === "project" - ? _.compact([ - getChartDashboardItem(targetVsActualBenefitsChart_), - getChartDashboardItem(targetVsActualPeopleChart_), - getChartDashboardItem(merTargetVsActualBenefitsChart_), - getChartDashboardItem(merTargetVsActualPeopleChart_), - getReportTableItem(targetVsActualBenefitsTable_), - getReportTableItem(targetVsActualPeopleTable_), - getChartDashboardItem(targetVsActualBenefitsDisaggregatedByIndicatorChart_), - getChartDashboardItem(targetVsActualPeopleDisaggregatedByIndicatorChart_), - getChartDashboardItem(targetVsActualBenefitsLineChart_), - getChartDashboardItem(targetVsActualPeopleLineChart_), - getChartDashboardItem(targetVsActualPeopleLineChartMaleOnly_), - getChartDashboardItem(targetVsActualPeopleLineChartFemaleOnly_), - getChartDashboardItem(targetVsActualPeopleLineColumnChartMaleOnly_), - getChartDashboardItem(targetVsActualPeopleLineColumnChartFemaleOnly_), - getReportTableItem(targetVsActualBenefitsWithDisaggregationTable_), - ]) - : reportTables.map(reportTable => getReportTableItem(reportTable))), - ...(this.dashboardType === "project" - ? otherReportTables.map(reportTable => getReportTableItem(reportTable)) - : []), - ...charts.map(chart => getChartDashboardItem(chart)), - ]); + const visualizations = + this.dashboardType === "project" ? projectVisualizations : defaultVisualizations; + + const items: Array> = _(visualizations) + .map(visualization => + visualization.type === "PIVOT_TABLE" + ? getReportTableItem(visualization) + : getChartDashboardItem(visualization) + ) + .compact() + .value(); const positionItemsOptions: PositionItemsOptions = { maxWidth: toItemWidth(100), @@ -234,7 +229,7 @@ export default class ProjectDashboard { ...new ProjectSharing(config, projectsListDashboard).getSharingAttributesForDashboard(), }; - return { dashboards: [dashboard], ...favorites }; + return { dashboards: [dashboard], visualizations }; } targetVsActualBenefitsTable(): MaybeD2Visualization { diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index d3fda2c6..44cf81a1 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -21,7 +21,10 @@ const dataStoreUpdateResponse = { describe("ProjectDb", () => { describe("save", () => { it("posts metadata", async () => { - const project = await getProject(api, { orgUnit: undefined }); + const project = (await getProject(api, { orgUnit: undefined })).updateDataElementsMERSelection( + "ieyBABjYyHO", + ["ik0ICagvIjm"] + ).project; // Validation mock.onGet("/metadata", { @@ -140,7 +143,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,i07AWJAND8a,iOk52Z42bjp,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,OuKm5zK7l53,iqqgnCj9DQj,SQSYgZjfA3z,aeGIpbJkZAX,GM6SxObVwI3,GEe8ZzUkVwG,uG9C9z46CNK,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,CYYNLjxd96q,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,uYWdSMZQ1LH,i07AWJAND8a,iqqgnCj9DQj,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,OuKm5zK7l53,iOk52Z42bjp,GM6SxObVwI3,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", fields: "id,created", }, }).replyOnce(200, {}); @@ -226,7 +229,7 @@ const orgUnitsMetadata = { }; const expectedDataStoreMer = { - merDataElementIds: ["yMqK9DKbA3X"], + merDataElementIds: ["ik0ICagvIjm", "yMqK9DKbA3X"], documents: [], uniqueBeneficiaries: { periods: [], indicatorsIds: [] }, }; diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 94e907a2..507f2999 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1029,10 +1029,10 @@ "y": 20 }, { - "id": "Ka4yijY2Vhl", - "type": "REPORT_TABLE", + "id": "imK8xQLwwYX", + "type": "CHART", "visualization": { - "id": "i07AWJAND8a" + "id": "uYWdSMZQ1LH" }, "width": 29, "height": 20, @@ -1040,10 +1040,10 @@ "y": 20 }, { - "id": "m4LaU9HizHi", + "id": "Ka4yijY2Vhl", "type": "REPORT_TABLE", "visualization": { - "id": "iOk52Z42bjp" + "id": "i07AWJAND8a" }, "width": 29, "height": 20, @@ -1051,10 +1051,10 @@ "y": 40 }, { - "id": "i66m5HwnH6v", - "type": "CHART", + "id": "yWGKgz9vaOh", + "type": "REPORT_TABLE", "visualization": { - "id": "a46jcQ65Axt" + "id": "iqqgnCj9DQj" }, "width": 29, "height": 20, @@ -1062,10 +1062,10 @@ "y": 40 }, { - "id": "a4GacNVWHLX", + "id": "i66m5HwnH6v", "type": "CHART", "visualization": { - "id": "GA87u7JwgSK" + "id": "a46jcQ65Axt" }, "width": 29, "height": 20, @@ -1073,10 +1073,10 @@ "y": 60 }, { - "id": "KYcDaXAZa1q", + "id": "a4GacNVWHLX", "type": "CHART", "visualization": { - "id": "KiUTxsMMYde" + "id": "GA87u7JwgSK" }, "width": 29, "height": 20, @@ -1084,10 +1084,10 @@ "y": 60 }, { - "id": "a6cSVlR6bSj", + "id": "KYcDaXAZa1q", "type": "CHART", "visualization": { - "id": "GkoTRBEmIQt" + "id": "KiUTxsMMYde" }, "width": 29, "height": 20, @@ -1095,10 +1095,10 @@ "y": 80 }, { - "id": "W4DOghdXUmp", + "id": "a6cSVlR6bSj", "type": "CHART", "visualization": { - "id": "S2kJHgM41El" + "id": "GkoTRBEmIQt" }, "width": 29, "height": 20, @@ -1106,10 +1106,10 @@ "y": 80 }, { - "id": "OgO4mL6ovvU", + "id": "W4DOghdXUmp", "type": "CHART", "visualization": { - "id": "KasxZ8vT1n0" + "id": "S2kJHgM41El" }, "width": 29, "height": 20, @@ -1117,10 +1117,10 @@ "y": 100 }, { - "id": "K2amO1SBZFm", + "id": "OgO4mL6ovvU", "type": "CHART", "visualization": { - "id": "W2SCFrHCiEm" + "id": "KasxZ8vT1n0" }, "width": 29, "height": 20, @@ -1128,10 +1128,10 @@ "y": 100 }, { - "id": "GW6MALzFIVR", + "id": "K2amO1SBZFm", "type": "CHART", "visualization": { - "id": "OuKm5zK7l53" + "id": "W2SCFrHCiEm" }, "width": 29, "height": 20, @@ -1139,10 +1139,10 @@ "y": 120 }, { - "id": "yWGKgz9vaOh", - "type": "REPORT_TABLE", + "id": "GW6MALzFIVR", + "type": "CHART", "visualization": { - "id": "iqqgnCj9DQj" + "id": "OuKm5zK7l53" }, "width": 29, "height": 20, @@ -1150,27 +1150,16 @@ "y": 120 }, { - "id": "ywvTGMsKdwL", + "id": "m4LaU9HizHi", "type": "REPORT_TABLE", "visualization": { - "id": "SQSYgZjfA3z" + "id": "iOk52Z42bjp" }, "width": 29, "height": 20, "x": 0, "y": 140 }, - { - "id": "qMSWdZHPjyN", - "type": "REPORT_TABLE", - "visualization": { - "id": "aeGIpbJkZAX" - }, - "width": 29, - "height": 20, - "x": 29, - "y": 140 - }, { "id": "uyoJujQVRjE", "type": "REPORT_TABLE", @@ -1179,30 +1168,8 @@ }, "width": 29, "height": 20, - "x": 0, - "y": 160 - }, - { - "id": "mgwFIMjbsdw", - "type": "REPORT_TABLE", - "visualization": { - "id": "GEe8ZzUkVwG" - }, - "width": 29, - "height": 20, "x": 29, - "y": 160 - }, - { - "id": "ys0CVedHirZ", - "type": "CHART", - "visualization": { - "id": "uG9C9z46CNK" - }, - "width": 58, - "height": 20, - "x": 0, - "y": 180 + "y": 140 }, { "id": "KI0C90Ol10x", @@ -1213,7 +1180,7 @@ "width": 29, "height": 20, "x": 0, - "y": 200 + "y": 160 }, { "id": "uYY7v977Ubm", @@ -1224,7 +1191,7 @@ "width": 29, "height": 20, "x": 29, - "y": 200 + "y": 160 }, { "id": "qUqsDmtiBLF", @@ -1235,7 +1202,7 @@ "width": 29, "height": 20, "x": 0, - "y": 220 + "y": 180 }, { "id": "mwMpIdPdu8H", @@ -1246,7 +1213,7 @@ "width": 29, "height": 20, "x": 29, - "y": 220 + "y": 180 } ], "publicAccess": "--------", @@ -1403,17 +1370,6 @@ "x": 0, "y": 60 }, - { - "id": "CkcoElgGMuu", - "type": "CHART", - "visualization": { - "id": "CYYNLjxd96q" - }, - "width": 58, - "height": 20, - "x": 0, - "y": 80 - }, { "id": "GqqyIiwIxog", "type": "CHART", @@ -1422,8 +1378,8 @@ }, "width": 29, "height": 20, - "x": 0, - "y": 100 + "x": 29, + "y": 60 }, { "id": "mCeCHYX6DOG", @@ -1433,8 +1389,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 100 + "x": 0, + "y": 80 }, { "id": "O8EPBVIg4zK", @@ -1444,8 +1400,8 @@ }, "width": 29, "height": 20, - "x": 0, - "y": 120 + "x": 29, + "y": 80 }, { "id": "OI8TXjJJwfS", @@ -1455,8 +1411,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 120 + "x": 0, + "y": 100 } ], "publicAccess": "--------", @@ -1552,7 +1508,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "dx" @@ -1561,13 +1519,18 @@ "id": "ou" } ], - "filterDimensions": ["dx", "ou"], + "filterDimensions": [ + "dx", + "ou" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -1680,7 +1643,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "dx" @@ -1719,13 +1684,20 @@ ] } ], - "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "dx", + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -1852,19 +1824,25 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -1903,9 +1881,9 @@ ] }, { - "id": "i07AWJAND8a", - "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Target vs Actual - Benefits", + "id": "uYWdSMZQ1LH", + "type": "COLUMN", + "name": "12345en - MyProject - MER - Target vs Actual - People - Column Chart", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -1919,13 +1897,7 @@ { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "WS8XV4WWPE7" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "yMqK9DKbA3X" + "id": "ik0ICagvIjm" } } ], @@ -1956,37 +1928,76 @@ ], "columns": [ { - "id": "pe" + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ + { + "id": "dx" + }, { "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ + }, { - "id": "dx" + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] }, { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", "categoryOptions": [ { - "code": "TARGET", - "id": "imyqCWQ229K" + "code": "NEW", + "id": "KiK0FMExoqh" }, { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" + "code": "RETURNING", + "id": "a6AJLXQy8vO" } ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "filterDimensions": [ + "dx", + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "pe" + } + ], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -2000,6 +2011,32 @@ "id": "eWeQoOlAcxV" } ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] } ], "publicAccess": "--------", @@ -2025,9 +2062,9 @@ ] }, { - "id": "iOk52Z42bjp", + "id": "i07AWJAND8a", "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Achieved to date (%) - Benefits", + "name": "12345en - MyProject - Target vs Actual - Benefits", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2039,15 +2076,15 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eCufXa6RkTm" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WS8XV4WWPE7" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "i01veyO4Cuw" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" } } ], @@ -2081,30 +2118,66 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" - } - ], - "rowDimensions": ["dx"], - "categoryDimensions": [], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ + }, { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], - "userGroupAccesses": [ + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ { "id": "ywuI2WspUUG", "displayName": "System Admin", @@ -2115,11 +2188,200 @@ "displayName": "Data Management Admin", "access": "rw------" } + ] + }, + { + "id": "iqqgnCj9DQj", + "type": "PIVOT_TABLE", + "name": "12345en - MyProject - Target vs Actual - People", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "id": "pe" + }, + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] + } + ], + "columnDimensions": [ + "pe", + "Kyg1O6YEGa9" + ], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": [ + "ou" + ], + "rows": [ + { + "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" + ], + "categoryDimensions": [ + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] }, { "id": "a46jcQ65Axt", @@ -2178,13 +2440,17 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "pe" @@ -2205,7 +2471,10 @@ ] } ], - "rowDimensions": ["pe", "GIIHAr9BzzO"], + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -2306,7 +2575,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -2342,7 +2613,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "pe" @@ -2363,7 +2638,10 @@ ] } ], - "rowDimensions": ["pe", "GIIHAr9BzzO"], + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -2496,13 +2774,17 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -2511,7 +2793,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -2624,7 +2909,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" @@ -2660,7 +2947,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -2669,7 +2960,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -2808,7 +3102,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" @@ -2837,7 +3133,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -2846,7 +3146,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -2982,7 +3285,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" @@ -3011,7 +3316,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -3020,7 +3329,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -3156,7 +3468,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" @@ -3185,7 +3499,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -3194,7 +3512,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -3341,7 +3662,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" @@ -3370,7 +3693,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -3379,7 +3706,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -3452,9 +3782,9 @@ ] }, { - "id": "iqqgnCj9DQj", + "id": "iOk52Z42bjp", "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Target vs Actual - People", + "name": "12345en - MyProject - Achieved to date (%) - Benefits", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -3466,325 +3796,19 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "K6mAC5SiO29" + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "eCufXa6RkTm" } }, { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "ik0ICagvIjm" + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "i01veyO4Cuw" } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "GQyudNlGzkI" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - } - ], - "columns": [ - { - "id": "pe" - }, - { - "code": "GENDER", - "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "MALE", - "id": "qk2FihwV6IL" - }, - { - "code": "FEMALE", - "id": "yW2hYVS3S4u" - } - ] - } - ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "dx" - }, - { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", - "categoryOptions": [ - { - "code": "TARGET", - "id": "imyqCWQ229K" - }, - { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" - } - ] - }, - { - "code": "NEW_RETURNING", - "id": "uSMHdwhxFSV", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "NEW", - "id": "KiK0FMExoqh" - }, - { - "code": "RETURNING", - "id": "a6AJLXQy8vO" - } - ] - } - ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], - "categoryDimensions": [ - { - "category": { - "id": "Kyg1O6YEGa9" - }, - "categoryOptions": [ - { - "id": "qk2FihwV6IL" - }, - { - "id": "yW2hYVS3S4u" - } - ] - }, - { - "category": { - "id": "GIIHAr9BzzO" - }, - "categoryOptions": [ - { - "id": "imyqCWQ229K" - }, - { - "id": "eWeQoOlAcxV" - } - ] - }, - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - }, - { - "id": "a6AJLXQy8vO" - } - ] - } - ], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ] - }, - { - "id": "SQSYgZjfA3z", - "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Achieved total to date (%) - People", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": false, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - } - ], - "columns": [ - { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } - ], - "columnDimensions": ["uSMHdwhxFSV"], - "filters": [ - { - "id": "ou" - }, - { - "id": "pe" - } - ], - "filterDimensions": ["ou", "pe"], - "rows": [ - { - "id": "dx" - } - ], - "rowDimensions": ["dx"], - "categoryDimensions": [ - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } - ], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } - }, - { - "id": "aeGIpbJkZAX", - "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Achieved (%) - Benefits", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": true, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eCufXa6RkTm" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "i01veyO4Cuw" - } - } - ], - "organisationUnits": [ + } + ], + "organisationUnits": [ { "id": "WGC0DJ0YSis" } @@ -3814,19 +3838,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3917,256 +3947,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "dx" - } - ], - "rowDimensions": ["dx"], - "categoryDimensions": [], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } - }, - { - "id": "GEe8ZzUkVwG", - "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Achieved total (%) - People", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": false, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - } - ], - "columns": [ - { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } + "columnDimensions": [ + "pe" ], - "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" - }, - { - "id": "pe" - } - ], - "filterDimensions": ["ou", "pe"], - "rows": [ - { - "id": "dx" - } - ], - "rowDimensions": ["dx"], - "categoryDimensions": [ - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } - ], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } - }, - { - "id": "uG9C9z46CNK", - "type": "COLUMN", - "name": "12345en - MyProject - Achieved monthly (%)", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": true, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eCufXa6RkTm" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "i01veyO4Cuw" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - } - ], - "columns": [ - { - "id": "pe" } ], - "columnDimensions": ["pe"], - "filters": [ - { - "id": "ou" - } + "filterDimensions": [ + "ou" ], - "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4188,7 +3987,11 @@ "displayName": "Data Management Admin", "access": "rw------" } - ] + ], + "legendSet": { + "code": "ACTUAL_TARGET_ACHIEVED", + "id": "yoAt108kUFm" + } }, { "id": "qmsj4FqnVPX", @@ -4247,19 +4050,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4346,7 +4155,9 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" @@ -4360,13 +4171,18 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -4476,7 +4292,9 @@ ] } ], - "columnDimensions": ["Kyg1O6YEGa9"], + "columnDimensions": [ + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" @@ -4493,13 +4311,19 @@ ] } ], - "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -4598,19 +4422,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4735,7 +4565,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "pe" @@ -4757,13 +4589,19 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV", "GIIHAr9BzzO"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV", + "GIIHAr9BzzO" + ], "rows": [ { "id": "ou" } ], - "rowDimensions": ["ou"], + "rowDimensions": [ + "ou" + ], "categoryDimensions": [ { "category": { @@ -4871,7 +4709,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "pe" @@ -4885,13 +4725,18 @@ ] } ], - "filterDimensions": ["pe", "GIIHAr9BzzO"], + "filterDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "rows": [ { "id": "ou" } ], - "rowDimensions": ["ou"], + "rowDimensions": [ + "ou" + ], "categoryDimensions": [ { "category": { @@ -5001,7 +4846,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -5023,13 +4870,19 @@ ] } ], - "filterDimensions": ["ou", "uSMHdwhxFSV", "GIIHAr9BzzO"], + "filterDimensions": [ + "ou", + "uSMHdwhxFSV", + "GIIHAr9BzzO" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -5131,7 +4984,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -5145,13 +5000,18 @@ ] } ], - "filterDimensions": ["ou", "GIIHAr9BzzO"], + "filterDimensions": [ + "ou", + "GIIHAr9BzzO" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -5322,13 +5182,17 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -5349,7 +5213,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -5576,13 +5443,18 @@ ] } ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], + "columnDimensions": [ + "pe", + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -5618,7 +5490,11 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" + ], "categoryDimensions": [ { "category": { @@ -5832,259 +5708,32 @@ { "id": "202010" } - ], - "columns": [ - { - "id": "pe" - } - ], - "columnDimensions": ["pe"], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "dx" - } - ], - "rowDimensions": ["dx"], - "categoryDimensions": [], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } - }, - { - "id": "mUCwcWSsa9T", - "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved total to date (%) - People", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": false, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "CqURW24bmHJ" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "iewd6jLYV4H" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K6ipXoSOmt2" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qgGwMTqEq4d" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "aOALuHaoaEQ" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "yeQN47GFqwM" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K2ADN2EmEmr" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qW6b6ZRfXA5" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - }, - { - "id": "TvSmIyYcRnd" - }, - { - "id": "cqZ9zQfePzQ" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - }, - { - "id": "201904" - }, - { - "id": "201905" - }, - { - "id": "201906" - }, - { - "id": "201907" - }, - { - "id": "201908" - }, - { - "id": "201909" - }, - { - "id": "201910" - }, - { - "id": "201911" - }, - { - "id": "201912" - }, - { - "id": "202001" - }, - { - "id": "202002" - }, - { - "id": "202003" - }, - { - "id": "202004" - }, - { - "id": "202005" - }, - { - "id": "202006" - }, - { - "id": "202007" - }, - { - "id": "202008" - }, - { - "id": "202009" - }, - { - "id": "202010" - } - ], - "columns": [ - { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] + ], + "columns": [ + { + "id": "pe" } ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" - }, - { - "id": "pe" } ], - "filterDimensions": ["ou", "pe"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], - "categoryDimensions": [ - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } + "rowDimensions": [ + "dx" ], + "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, "userAccesses": [ @@ -6112,9 +5761,9 @@ } }, { - "id": "KeWVSa2rbYm", + "id": "mUCwcWSsa9T", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved (%) - Benefits", + "name": "Award Number 12345 - Achieved total to date (%) - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6122,55 +5771,73 @@ "showData": true, "aggregationType": "DEFAULT", "legendDisplayStrategy": "FIXED", - "rowTotals": true, + "rowTotals": false, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "qu0x94utOgv" + "id": "CqURW24bmHJ" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "qQsafE8eZQt" + "id": "iewd6jLYV4H" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "isKcihOpMrF" + "id": "K6ipXoSOmt2" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "OOIDqW7eQqr" + "id": "qgGwMTqEq4d" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "m68LzR6ho7V" + "id": "aOALuHaoaEQ" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "KOKIhtZYDOh" + "id": "yeQN47GFqwM" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "eCufXa6RkTm" + "id": "K2ADN2EmEmr" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "i01veyO4Cuw" + "id": "qW6b6ZRfXA5" + } + }, + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "eYmeRzhBFV4" + } + }, + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "u404ICrBKj3" + } + }, + { + "dataDimensionItemType": "INDICATOR", + "indicator": { + "id": "K4sH0aQDdeL" } } ], @@ -6264,23 +5931,49 @@ ], "columns": [ { - "id": "pe" + "id": "uSMHdwhxFSV", + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "uSMHdwhxFSV" + ], "filters": [ { "id": "ou" + }, + { + "id": "pe" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou", + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], - "categoryDimensions": [], + "rowDimensions": [ + "dx" + ], + "categoryDimensions": [ + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] + } + ], "publicAccess": "--------", "externalAccess": false, "userAccesses": [ @@ -6308,9 +6001,9 @@ } }, { - "id": "i6CWRJp61Hp", + "id": "KeWVSa2rbYm", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved to date (%) - People", + "name": "Award Number 12345 - Achieved (%) - Benefits", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6318,73 +6011,55 @@ "showData": true, "aggregationType": "DEFAULT", "legendDisplayStrategy": "FIXED", - "rowTotals": false, + "rowTotals": true, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "CqURW24bmHJ" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "iewd6jLYV4H" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K6ipXoSOmt2" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qgGwMTqEq4d" + "id": "qu0x94utOgv" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "aOALuHaoaEQ" + "id": "qQsafE8eZQt" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "yeQN47GFqwM" + "id": "isKcihOpMrF" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "K2ADN2EmEmr" + "id": "OOIDqW7eQqr" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "qW6b6ZRfXA5" + "id": "m68LzR6ho7V" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "eYmeRzhBFV4" + "id": "KOKIhtZYDOh" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "u404ICrBKj3" + "id": "eCufXa6RkTm" } }, { "dataDimensionItemType": "INDICATOR", "indicator": { - "id": "K4sH0aQDdeL" + "id": "i01veyO4Cuw" } } ], @@ -6481,19 +6156,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6522,9 +6203,9 @@ } }, { - "id": "eYaYrZfbJT1", + "id": "i6CWRJp61Hp", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved total (%) - People", + "name": "Award Number 12345 - Achieved to date (%) - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6692,42 +6373,29 @@ ], "columns": [ { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] + "id": "pe" } ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" - }, - { - "id": "pe" } ], - "filterDimensions": ["ou", "pe"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], - "categoryDimensions": [ - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] - } + "rowDimensions": [ + "dx" ], + "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, "userAccesses": [ @@ -6755,9 +6423,9 @@ } }, { - "id": "CYYNLjxd96q", - "type": "COLUMN", - "name": "Award Number 12345 - Achieved monthly (%)", + "id": "eYaYrZfbJT1", + "type": "PIVOT_TABLE", + "name": "Award Number 12345 - Achieved total (%) - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6765,33 +6433,9 @@ "showData": true, "aggregationType": "DEFAULT", "legendDisplayStrategy": "FIXED", - "rowTotals": true, + "rowTotals": false, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qu0x94utOgv" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qQsafE8eZQt" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "isKcihOpMrF" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "OOIDqW7eQqr" - } - }, { "dataDimensionItemType": "INDICATOR", "indicator": { @@ -6840,30 +6484,6 @@ "id": "qW6b6ZRfXA5" } }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "m68LzR6ho7V" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "KOKIhtZYDOh" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eCufXa6RkTm" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "i01veyO4Cuw" - } - }, { "dataDimensionItemType": "INDICATOR", "indicator": { @@ -6973,23 +6593,49 @@ ], "columns": [ { - "id": "pe" + "id": "uSMHdwhxFSV", + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "uSMHdwhxFSV" + ], "filters": [ { "id": "ou" + }, + { + "id": "pe" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou", + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], - "categoryDimensions": [], + "rowDimensions": [ + "dx" + ], + "categoryDimensions": [ + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] + } + ], "publicAccess": "--------", "externalAccess": false, "userAccesses": [ @@ -7010,7 +6656,11 @@ "displayName": "Data Management Admin", "access": "rw------" } - ] + ], + "legendSet": { + "code": "ACTUAL_TARGET_ACHIEVED", + "id": "yoAt108kUFm" + } }, { "id": "Gi2PegQJhbu", @@ -7168,19 +6818,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -7378,7 +7034,9 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" @@ -7392,13 +7050,18 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -7619,7 +7282,9 @@ ] } ], - "columnDimensions": ["Kyg1O6YEGa9"], + "columnDimensions": [ + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" @@ -7636,13 +7301,19 @@ ] } ], - "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -7804,19 +7475,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -7841,4 +7518,4 @@ ] } ] -} +} \ No newline at end of file From 6bd60638a8810a1b4ed68d9d8715a0f6e308d745 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 27 Mar 2026 12:31:37 -0500 Subject: [PATCH 16/49] add script to update dashboards --- i18n/en.pot | 64 +- src/models/Dashboard.ts | 2 + src/models/Period.ts | 32 + src/models/Project.ts | 3 +- src/models/ProjectDashboard.ts | 334 ++- src/models/ProjectsList.ts | 6 +- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 2283 +++++++++++------ .../unique-periods/UniquePeriodsForm.tsx | 16 +- src/utils/date.ts | 17 +- 10 files changed, 1835 insertions(+), 924 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index f1aee1b5..ed20a6f7 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2026-03-16T13:43:15.193Z\n" -"PO-Revision-Date: 2026-03-16T13:43:15.193Z\n" +"POT-Creation-Date: 2026-03-27T15:30:46.362Z\n" +"PO-Revision-Date: 2026-03-27T15:30:46.362Z\n" msgid "Validating Project" msgstr "" @@ -594,12 +594,72 @@ msgstr "" msgid "Target vs Actual - Benefits" msgstr "" +msgid "Target vs Actual - Benefits - Pivot Table" +msgstr "" + +msgid "Target vs Actual - Benefits - Column Chart" +msgstr "" + +msgid "Target vs Actual - People - Column Chart" +msgstr "" + +msgid "MER - Target vs Actual - Benefits - Column Chart" +msgstr "" + +msgid "MER - Target vs Actual - People - Column Chart" +msgstr "" + +msgid "Target vs Actual - Benefits - Column Chart Disaggregated By Indicator" +msgstr "" + +msgid "Target vs Actual - People - Column Chart Disaggregated By Indicator" +msgstr "" + +msgid "Target vs Actual - Benefits - Line Chart" +msgstr "" + +msgid "Target vs Actual - People - Line Chart" +msgstr "" + +msgid "Target vs Actual - People - Line Chart - Male Only" +msgstr "" + +msgid "Target vs Actual - People - Line Chart - Female Only" +msgstr "" + +msgid "Target vs Actual - People - Line/Column Chart - Male Only" +msgstr "" + +msgid "Target vs Actual - People - Line/Column Chart - Female Only" +msgstr "" + msgid "Target vs Actual - Benefits (Disaggregated)" msgstr "" msgid "Target vs Actual - People" msgstr "" +msgid "Target vs Actual - People - Pivot Table" +msgstr "" + +msgid "Target vs Actual - People - Month by Month" +msgstr "" + +msgid "Target vs Actual - Benefits - Month by Month" +msgstr "" + +msgid "Target vs Actual - People - Male Only - Pivot Table" +msgstr "" + +msgid "Target vs Actual - People - Female Only - Pivot Table" +msgstr "" + +msgid "Target vs Actual - People - Male Only - Column Chart" +msgstr "" + +msgid "Target vs Actual - People - Female Only - Column Chart" +msgstr "" + msgid "Target vs Actual - Unique People" msgstr "" diff --git a/src/models/Dashboard.ts b/src/models/Dashboard.ts index 627633f4..b8a36a06 100644 --- a/src/models/Dashboard.ts +++ b/src/models/Dashboard.ts @@ -10,6 +10,7 @@ import { import { Maybe } from "../types/utils"; import { getUid, getRefs } from "../utils/dhis2"; import { D2Sharing } from "./Sharing"; +import { PeriodStrategy } from "./Period"; export const dimensions = { period: { id: "pe" }, @@ -32,6 +33,7 @@ export interface VisualizationDefinition { // TODO: validate if having undefined for the other visualizations // modify somehow the functionality chartType?: Exclude; + periodStrategy?: PeriodStrategy; key: string; name: string; items: Item[]; diff --git a/src/models/Period.ts b/src/models/Period.ts index daca521a..9385f36f 100644 --- a/src/models/Period.ts +++ b/src/models/Period.ts @@ -1,10 +1,13 @@ import moment from "moment"; +import _ from "lodash"; import { Maybe } from "../types/utils"; import { getMonthsRange } from "../utils/date"; export type Period = string; +export type PeriodStrategy = "monthly" | "yearly" | "monthly_interleaved_by_month"; export const monthPeriod = "YYYYMM"; +export const yearPeriod = "YYYY"; export function getPeriodsFromRange(start: Maybe, end: Maybe): Period[] { if (!start || !end) return []; @@ -16,3 +19,32 @@ export function filterPeriods(periods: Period[], options: { toDate?: boolean } = const now = moment(); return !options.toDate ? periods : periods.filter(period => moment(period, monthPeriod) <= now); } + +export function getVisualizationPeriods( + periods: Period[], + options: { toDate?: boolean; periodStrategy?: PeriodStrategy } = {} +): Period[] { + const { toDate, periodStrategy = "monthly" } = options; + + const transformedPeriods = + periodStrategy === "yearly" + ? _.uniq(periods.map(period => moment(period, monthPeriod).format(yearPeriod))).sort() + : periodStrategy === "monthly_interleaved_by_month" + ? _(periods) + .groupBy(period => moment(period, monthPeriod).format("MM")) + .toPairs() + .sortBy(([month]) => month) + .flatMap(([_month, monthPeriods]) => _.sortBy(monthPeriods)) + .value() + : periods; + + if (!toDate) return transformedPeriods; + + const now = moment(); + + return transformedPeriods.filter(period => + periodStrategy === "yearly" + ? moment(period, yearPeriod).year() <= now.year() + : moment(period, monthPeriod) <= now + ); +} diff --git a/src/models/Project.ts b/src/models/Project.ts index 7ca5043d..61c373f8 100644 --- a/src/models/Project.ts +++ b/src/models/Project.ts @@ -4,14 +4,13 @@ import _ from "lodash"; import { D2Api, Id, Ref } from "../types/d2-api"; // @ts-ignore import { generateUid } from "d2/uid"; -import { TableSorting } from "@eyeseetea/d2-ui-components"; import i18n from "../locales"; import DataElementsSet, { PeopleOrBenefit, DataElement, SelectionInfo } from "./dataElementsSet"; import ProjectDb from "./ProjectDb"; import { toISOString, getMonthsRange } from "../utils/date"; import ProjectDownload from "./ProjectDownload"; -import ProjectList, { ProjectForList, FiltersForList } from "./ProjectsList"; +import ProjectList, { ProjectForList, FiltersForList, TableSorting } from "./ProjectsList"; import ProjectDataSet from "./ProjectDataSet"; import ProjectDelete from "./ProjectDelete"; import { diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index a6aadc03..8dff4270 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -28,7 +28,7 @@ import { DashboardSourceMetadata, Condition, } from "./ProjectsListDashboard"; -import { filterPeriods } from "./Period"; +import { getVisualizationPeriods } from "./Period"; export default class ProjectDashboard { dataElements: ProjectsListDashboard["dataElements"]; @@ -101,111 +101,10 @@ export default class ProjectDashboard { if (!_.isNil(minimumOrgUnits) && projectsListDashboard.orgUnits.length < minimumOrgUnits) return { dashboards: [], visualizations: [] }; - const targetVsActualBenefitsChart_ = - this.dashboardType === "project" ? this.targetVsActualBenefitsChart() : undefined; - - const targetVsActualPeopleChart_ = - this.dashboardType === "project" ? this.targetVsActualPeopleChart() : undefined; - - const merTargetVsActualBenefitsChart_ = - this.dashboardType === "project" ? this.merTargetVsActualBenefitsChart() : undefined; - - const merTargetVsActualPeopleChart_ = - this.dashboardType === "project" ? this.merTargetVsActualPeopleChart() : undefined; - - const targetVsActualBenefitsDisaggregatedByIndicatorChart_ = - this.dashboardType === "project" - ? this.targetVsActualBenefitsDisaggregatedByIndicatorChart() - : undefined; - - const targetVsActualPeopleDisaggregatedByIndicatorChart_ = - this.dashboardType === "project" - ? this.targetVsActualPeopleDisaggregatedByIndicatorChart() - : undefined; - - const targetVsActualBenefitsLineChart_ = - this.dashboardType === "project" ? this.targetVsActualBenefitsLineChart() : undefined; - - const targetVsActualPeopleLineChart_ = - this.dashboardType === "project" ? this.targetVsActualPeopleLineChart() : undefined; - - const targetVsActualPeopleLineChartMaleOnly_ = - this.dashboardType === "project" - ? this.targetVsActualPeopleLineChartMaleOnly() - : undefined; - - const targetVsActualPeopleLineChartFemaleOnly_ = - this.dashboardType === "project" - ? this.targetVsActualPeopleLineChartFemaleOnly() - : undefined; - - const targetVsActualPeopleLineColumnChartMaleOnly_ = - this.dashboardType === "project" - ? this.targetVsActualPeopleLineColumnChartMaleOnly() - : undefined; - - const targetVsActualPeopleLineColumnChartFemaleOnly_ = - this.dashboardType === "project" - ? this.targetVsActualPeopleLineColumnChartFemaleOnly() - : undefined; - - const targetVsActualBenefitsTable_ = this.targetVsActualBenefitsTable(); - const targetVsActualBenefitsWithDisaggregationTable_ = - this.targetVsActualBenefitsWithDisaggregationTable(); - const targetVsActualPeopleTable_ = this.targetVsActualPeopleTable(); - const achievedBenefitsToDateTable_ = this.achievedBenefitsTable({ toDate: true }); - const achievedBenefitsTotalToDateTable_ = this.achievedBenefitsTotalToDateTable(); - const achievedPeopleTotalToDateTable_ = this.achievedPeopleTotalTable({ toDate: true }); - const achievedBenefitsTable_ = this.achievedBenefitsTable(); - const achievedPeopleToDateTable_ = this.achievedPeopleTable(); - const achievedPeopleTotalTable_ = this.achievedPeopleTotalTable(); - - const reportTables: Array> = _.compact([ - // General Data View - targetVsActualBenefitsTable_, - targetVsActualBenefitsWithDisaggregationTable_, - targetVsActualPeopleTable_, - // Percent achieved (to date) - achievedBenefitsToDateTable_, - achievedBenefitsTotalToDateTable_, - achievedPeopleTotalToDateTable_, - // Percent achieved - achievedBenefitsTable_, - achievedPeopleToDateTable_, - achievedPeopleTotalTable_, - ]); - - const charts: Array> = _.compact([ - this.achievedBenefitChart(), - this.achievedPeopleChart(), - this.genderChart(), - this.costBenefitTable(), - ]); - - const projectVisualizations = _.compact([ - targetVsActualBenefitsChart_, - targetVsActualPeopleChart_, - merTargetVsActualBenefitsChart_, - merTargetVsActualPeopleChart_, - targetVsActualBenefitsTable_, - targetVsActualPeopleTable_, - targetVsActualBenefitsDisaggregatedByIndicatorChart_, - targetVsActualPeopleDisaggregatedByIndicatorChart_, - targetVsActualBenefitsLineChart_, - targetVsActualPeopleLineChart_, - targetVsActualPeopleLineChartMaleOnly_, - targetVsActualPeopleLineChartFemaleOnly_, - targetVsActualPeopleLineColumnChartMaleOnly_, - targetVsActualPeopleLineColumnChartFemaleOnly_, - achievedBenefitsToDateTable_, - achievedPeopleToDateTable_, - ...charts, - ]); - - const defaultVisualizations = _.concat(reportTables, _.compact(charts)); - const visualizations = - this.dashboardType === "project" ? projectVisualizations : defaultVisualizations; + this.dashboardType === "project" + ? this.getProjectVisualizations() + : this.getAwardNumberVisualizations(); const items: Array> = _(visualizations) .map(visualization => @@ -232,6 +131,58 @@ export default class ProjectDashboard { return { dashboards: [dashboard], visualizations }; } + getProjectVisualizations(): PartialPersistedModel[] { + const targetVsActualBenefitsTable_ = this.targetVsActualBenefitsTable(); + const targetVsActualPeopleTable_ = this.targetVsActualPeopleTable(); + const achievedBenefitsToDateTable_ = this.achievedBenefitsTable({ toDate: true }); + const achievedPeopleToDateTable_ = this.achievedPeopleTable(); + const charts: Array> = _.compact([ + this.achievedBenefitChart(), + this.achievedPeopleChart(), + this.genderChart(), + this.costBenefitTable(), + ]); + + return _.compact([ + this.targetVsActualBenefitsChart(), + this.targetVsActualPeopleChart(), + this.merTargetVsActualBenefitsChart(), + this.merTargetVsActualPeopleChart(), + targetVsActualBenefitsTable_, + targetVsActualPeopleTable_, + this.targetVsActualBenefitsDisaggregatedByIndicatorChart(), + this.targetVsActualPeopleDisaggregatedByIndicatorChart(), + this.targetVsActualBenefitsLineChart(), + this.targetVsActualPeopleLineChart(), + this.targetVsActualPeopleLineChartMaleOnly(), + this.targetVsActualPeopleLineChartFemaleOnly(), + this.targetVsActualPeopleLineColumnChartMaleOnly(), + this.targetVsActualPeopleLineColumnChartFemaleOnly(), + achievedBenefitsToDateTable_, + achievedPeopleToDateTable_, + ...charts, + ]); + } + + getAwardNumberVisualizations(): PartialPersistedModel[] { + return _.compact([ + this.awardNumberTargetVsActualPeoplePivotTable(), + this.awardNumberTargetVsActualPeopleColumnChart(), + this.awardNumberTargetVsActualBenefitsPivotTable(), + this.awardNumberTargetVsActualBenefitsColumnChart(), + this.achievedPeopleTotalTable({ toDate: true }), + this.achievedBenefitsTable({ toDate: true }), + this.targetVsActualPeopleTable(), + this.targetVsActualBenefitsTable(), + this.awardNumberTargetVsActualPeopleMonthByMonthTable(), + this.awardNumberTargetVsActualBenefitsMonthByMonthTable(), + this.awardNumberTargetVsActualPeopleMaleOnlyPivotTable(), + this.awardNumberTargetVsActualPeopleMaleOnlyColumnChart(), + this.awardNumberTargetVsActualPeopleFemaleOnlyPivotTable(), + this.awardNumberTargetVsActualPeopleFemaleOnlyColumnChart(), + ]); + } + targetVsActualBenefitsTable(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsNoDisaggregated = dataElements.benefit.filter( @@ -249,6 +200,24 @@ export default class ProjectDashboard { }); } + awardNumberTargetVsActualBenefitsPivotTable(): MaybeD2Visualization { + const { config, dataElements } = this; + const dataElementsNoDisaggregated = dataElements.benefit.filter( + de => !de.categories.includes("newRecurring") + ); + + return this.getD2VisualizationFromDefinition({ + type: "table", + key: "reportTable-target-actual-benefits-pivot-table", + name: i18n.t("Target vs Actual - Benefits - Pivot Table"), + periodStrategy: "yearly", + items: dataElementItems(dataElementsNoDisaggregated), + filters: [dimensions.orgUnit], + columns: [dimensions.period], + rows: [dimensions.data, config.categories.targetActual], + }); + } + targetVsActualBenefitsChart(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsNoDisaggregated = dataElements.benefit.filter( @@ -266,6 +235,24 @@ export default class ProjectDashboard { }); } + awardNumberTargetVsActualBenefitsColumnChart(): MaybeD2Visualization { + const { config, dataElements } = this; + const dataElementsNoDisaggregated = dataElements.benefit.filter( + de => !de.categories.includes("newRecurring") + ); + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-target-actual-benefits-award-number", + name: i18n.t("Target vs Actual - Benefits - Column Chart"), + periodStrategy: "yearly", + items: dataElementItems(dataElementsNoDisaggregated), + filters: [dimensions.orgUnit], + columns: [dimensions.data], + rows: [config.categories.targetActual, dimensions.period], + }); + } + targetVsActualPeopleChart(): MaybeD2Visualization { const { config, dataElements } = this; @@ -285,6 +272,21 @@ export default class ProjectDashboard { }); } + awardNumberTargetVsActualPeopleColumnChart(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key: "chart-target-actual-people-award-number", + name: i18n.t("Target vs Actual - People - Column Chart"), + periodStrategy: "yearly", + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, config.categories.gender, config.categories.newRecurring], + columns: [dimensions.data], + rows: [config.categories.targetActual, dimensions.period], + }); + } + merTargetVsActualBenefitsChart(): MaybeD2Visualization { const { config, merDataElements } = this; @@ -493,6 +495,126 @@ export default class ProjectDashboard { }); } + awardNumberTargetVsActualPeoplePivotTable(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "table", + key: "reportTable-target-actual-people-pivot-table", + name: i18n.t("Target vs Actual - People - Pivot Table"), + periodStrategy: "yearly", + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit], + columns: [dimensions.period], + rows: [dimensions.data, config.categories.targetActual, config.categories.newRecurring], + }); + } + + awardNumberTargetVsActualPeopleMonthByMonthTable(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "table", + key: "reportTable-target-actual-people-month-by-month", + name: i18n.t("Target vs Actual - People - Month by Month"), + periodStrategy: "monthly_interleaved_by_month", + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, config.categories.gender, config.categories.newRecurring], + columns: [dimensions.period], + rows: [dimensions.data, config.categories.targetActual], + }); + } + + awardNumberTargetVsActualBenefitsMonthByMonthTable(): MaybeD2Visualization { + const { config, dataElements } = this; + const dataElementsNoDisaggregated = dataElements.benefit.filter( + de => !de.categories.includes("newRecurring") + ); + + return this.getD2VisualizationFromDefinition({ + type: "table", + key: "reportTable-target-actual-benefits-month-by-month", + name: i18n.t("Target vs Actual - Benefits - Month by Month"), + periodStrategy: "monthly_interleaved_by_month", + items: dataElementItems(dataElementsNoDisaggregated), + filters: [dimensions.orgUnit], + columns: [dimensions.period], + rows: [dimensions.data, config.categories.targetActual], + }); + } + + awardNumberTargetVsActualPeopleMaleOnlyPivotTable(): MaybeD2Visualization { + return this.awardNumberTargetVsActualPeopleGenderPivotTable({ + key: "reportTable-target-actual-people-male-only-pivot-table", + name: i18n.t("Target vs Actual - People - Male Only - Pivot Table"), + genderFilter: this.categoryOnlyMale, + }); + } + + awardNumberTargetVsActualPeopleFemaleOnlyPivotTable(): MaybeD2Visualization { + return this.awardNumberTargetVsActualPeopleGenderPivotTable({ + key: "reportTable-target-actual-people-female-only-pivot-table", + name: i18n.t("Target vs Actual - People - Female Only - Pivot Table"), + genderFilter: this.categoryOnlyFemale, + }); + } + + awardNumberTargetVsActualPeopleMaleOnlyColumnChart(): MaybeD2Visualization { + return this.awardNumberTargetVsActualPeopleGenderColumnChart({ + key: "chart-target-actual-people-male-only-award-number", + name: i18n.t("Target vs Actual - People - Male Only - Column Chart"), + genderFilter: this.categoryOnlyMale, + }); + } + + awardNumberTargetVsActualPeopleFemaleOnlyColumnChart(): MaybeD2Visualization { + return this.awardNumberTargetVsActualPeopleGenderColumnChart({ + key: "chart-target-actual-people-female-only-award-number", + name: i18n.t("Target vs Actual - People - Female Only - Column Chart"), + genderFilter: this.categoryOnlyFemale, + }); + } + + awardNumberTargetVsActualPeopleGenderPivotTable(options: { + key: string; + name: string; + genderFilter: { id: Id; categoryOptions: Ref[] }; + }): MaybeD2Visualization { + const { config, dataElements } = this; + const { key, name, genderFilter } = options; + + return this.getD2VisualizationFromDefinition({ + type: "table", + key, + name, + periodStrategy: "yearly", + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, genderFilter, this.categoryOnlyNew], + columns: [dimensions.period], + rows: [dimensions.data, config.categories.targetActual], + }); + } + + awardNumberTargetVsActualPeopleGenderColumnChart(options: { + key: string; + name: string; + genderFilter: { id: Id; categoryOptions: Ref[] }; + }): MaybeD2Visualization { + const { config, dataElements } = this; + const { key, name, genderFilter } = options; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + key, + name, + periodStrategy: "yearly", + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, genderFilter, this.categoryOnlyNew], + columns: [dimensions.period], + rows: [dimensions.data, config.categories.targetActual], + }); + } + targetVsActualUniquePeopleTable(): MaybeD2Visualization { const { config, dataElements } = this; @@ -664,7 +786,7 @@ export default class ProjectDashboard { key: definition.key + projectsListDashboard.id, name: `${projectsListDashboard.name} - ${definition.name}`, organisationUnits: projectsListDashboard.orgUnits, - periods: filterPeriods(projectsListDashboard.periods, definition), + periods: getVisualizationPeriods(projectsListDashboard.periods, definition), sharing: new ProjectSharing( config, projectsListDashboard diff --git a/src/models/ProjectsList.ts b/src/models/ProjectsList.ts index a3cff1cc..2a7d5466 100644 --- a/src/models/ProjectsList.ts +++ b/src/models/ProjectsList.ts @@ -1,5 +1,4 @@ import _ from "lodash"; -import { TableSorting } from "@eyeseetea/d2-ui-components"; import { D2Api, D2OrganisationUnitSchema, SelectedPick, Id, Pager, Ref } from "../types/d2-api"; import { Config } from "./Config"; import moment, { Moment } from "moment"; @@ -399,3 +398,8 @@ function getOrgUnitsFilter(filters: FiltersForList, currentUser: User) { : userCountryIds; return filterCountryIds ? { "parent.id": { in: filterCountryIds } } : {}; } + +export type TableSorting = { + field: keyof T; + order: "asc" | "desc"; +}; diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 44cf81a1..a51d2587 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -143,7 +143,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,uYWdSMZQ1LH,i07AWJAND8a,iqqgnCj9DQj,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,OuKm5zK7l53,iOk52Z42bjp,GM6SxObVwI3,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,uqMTlezGj0I,OS2K2s8VIIq,ew6e1j5HwkE,mUCwcWSsa9T,KeWVSa2rbYm,i6CWRJp61Hp,eYaYrZfbJT1,Gi2PegQJhbu,Ww2X5s48uQx,CMqisHj7sP9,WGWGaYtwJzp]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,uYWdSMZQ1LH,i07AWJAND8a,iqqgnCj9DQj,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,OuKm5zK7l53,iOk52Z42bjp,GM6SxObVwI3,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,CAEdMM5XM5T,GiUz1pZI2Rq,uwoFl2upiOM,ui6nUS98GBM,mUCwcWSsa9T,ew6e1j5HwkE,OS2K2s8VIIq,uqMTlezGj0I,i8TrzIkXGrG,aGYruOfBtaD,KoIzyX81ZVL,WikhmLU9agJ,yamOXKh6Vok,yaQ772dtmLb]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 507f2999..ffb1dc69 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1294,10 +1294,10 @@ "name": "Award Number 12345", "dashboardItems": [ { - "id": "W4EN8esNyGQ", + "id": "CSL3EN6eJwx", "type": "REPORT_TABLE", "visualization": { - "id": "uqMTlezGj0I" + "id": "CAEdMM5XM5T" }, "width": 29, "height": 20, @@ -1305,10 +1305,10 @@ "y": 0 }, { - "id": "GCm9PNnLAgP", - "type": "REPORT_TABLE", + "id": "iYkPSnM7m4E", + "type": "CHART", "visualization": { - "id": "OS2K2s8VIIq" + "id": "GiUz1pZI2Rq" }, "width": 29, "height": 20, @@ -1316,10 +1316,10 @@ "y": 0 }, { - "id": "O0uabsxLqGS", + "id": "yI8WlxGRfXU", "type": "REPORT_TABLE", "visualization": { - "id": "ew6e1j5HwkE" + "id": "uwoFl2upiOM" }, "width": 29, "height": 20, @@ -1327,10 +1327,10 @@ "y": 20 }, { - "id": "KEy2fuNrALy", - "type": "REPORT_TABLE", + "id": "aCiqCXWYZ9P", + "type": "CHART", "visualization": { - "id": "mUCwcWSsa9T" + "id": "ui6nUS98GBM" }, "width": 29, "height": 20, @@ -1338,10 +1338,10 @@ "y": 20 }, { - "id": "iIyADNFfXEV", + "id": "KEy2fuNrALy", "type": "REPORT_TABLE", "visualization": { - "id": "KeWVSa2rbYm" + "id": "mUCwcWSsa9T" }, "width": 29, "height": 20, @@ -1349,10 +1349,10 @@ "y": 40 }, { - "id": "eU2Bs4XsX6J", + "id": "O0uabsxLqGS", "type": "REPORT_TABLE", "visualization": { - "id": "i6CWRJp61Hp" + "id": "ew6e1j5HwkE" }, "width": 29, "height": 20, @@ -1360,10 +1360,10 @@ "y": 40 }, { - "id": "yseGHIbXcNQ", + "id": "GCm9PNnLAgP", "type": "REPORT_TABLE", "visualization": { - "id": "eYaYrZfbJT1" + "id": "OS2K2s8VIIq" }, "width": 29, "height": 20, @@ -1371,10 +1371,10 @@ "y": 60 }, { - "id": "GqqyIiwIxog", - "type": "CHART", + "id": "W4EN8esNyGQ", + "type": "REPORT_TABLE", "visualization": { - "id": "Gi2PegQJhbu" + "id": "uqMTlezGj0I" }, "width": 29, "height": 20, @@ -1382,10 +1382,10 @@ "y": 60 }, { - "id": "mCeCHYX6DOG", - "type": "CHART", + "id": "OuQLaEe9G9v", + "type": "REPORT_TABLE", "visualization": { - "id": "Ww2X5s48uQx" + "id": "i8TrzIkXGrG" }, "width": 29, "height": 20, @@ -1393,10 +1393,10 @@ "y": 80 }, { - "id": "O8EPBVIg4zK", - "type": "CHART", + "id": "i60k7CBbyJZ", + "type": "REPORT_TABLE", "visualization": { - "id": "CMqisHj7sP9" + "id": "aGYruOfBtaD" }, "width": 29, "height": 20, @@ -1404,15 +1404,48 @@ "y": 80 }, { - "id": "OI8TXjJJwfS", - "type": "CHART", + "id": "qeWaohT6Mgt", + "type": "REPORT_TABLE", "visualization": { - "id": "WGWGaYtwJzp" + "id": "KoIzyX81ZVL" }, "width": 29, "height": 20, "x": 0, "y": 100 + }, + { + "id": "y84WQGCtWxT", + "type": "CHART", + "visualization": { + "id": "WikhmLU9agJ" + }, + "width": 29, + "height": 20, + "x": 29, + "y": 100 + }, + { + "id": "eCWMTNjreWb", + "type": "REPORT_TABLE", + "visualization": { + "id": "yamOXKh6Vok" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 120 + }, + { + "id": "eUcnQVKRn34", + "type": "CHART", + "visualization": { + "id": "yaQ772dtmLb" + }, + "width": 29, + "height": 20, + "x": 29, + "y": 120 } ], "publicAccess": "--------", @@ -5027,9 +5060,9 @@ "publicAccess": "rw------" }, { - "id": "uqMTlezGj0I", + "id": "CAEdMM5XM5T", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Target vs Actual - Benefits", + "name": "Award Number 12345 - Target vs Actual - People - Pivot Table", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -5043,49 +5076,67 @@ { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "aYk5MgSCLXP" + "id": "SQy5q6kCYI1" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "CI8NCm34d7D" + "id": "iYEDR850FFL" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "mu2b9Ivde6J" + "id": "qkyeCTJHU2d" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "WUMjtbgofs2" + "id": "eAkVLI8mKBa" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "umkL2sEVSNR" + "id": "Kg29718LQHl" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "SCY3TdhSz1K" + "id": "KKmUWsn19fq" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "WS8XV4WWPE7" + "id": "iCKxYSFIlcu" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "yMqK9DKbA3X" + "id": "qAM1NbCbS9G" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" } } ], @@ -5102,79 +5153,13 @@ ], "periods": [ { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - }, - { - "id": "201904" - }, - { - "id": "201905" - }, - { - "id": "201906" - }, - { - "id": "201907" - }, - { - "id": "201908" - }, - { - "id": "201909" - }, - { - "id": "201910" - }, - { - "id": "201911" - }, - { - "id": "201912" - }, - { - "id": "202001" - }, - { - "id": "202002" - }, - { - "id": "202003" - }, - { - "id": "202004" - }, - { - "id": "202005" - }, - { - "id": "202006" - }, - { - "id": "202007" - }, - { - "id": "202008" + "id": "2018" }, { - "id": "202009" + "id": "2019" }, { - "id": "202010" + "id": "2020" } ], "columns": [ @@ -5211,11 +5196,27 @@ "id": "eWeQoOlAcxV" } ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] } ], "rowDimensions": [ "dx", - "GIIHAr9BzzO" + "GIIHAr9BzzO", + "uSMHdwhxFSV" ], "categoryDimensions": [ { @@ -5230,6 +5231,19 @@ "id": "eWeQoOlAcxV" } ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] } ], "publicAccess": "--------", @@ -5255,9 +5269,9 @@ ] }, { - "id": "OS2K2s8VIIq", - "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Target vs Actual - People", + "id": "GiUz1pZI2Rq", + "type": "COLUMN", + "name": "Award Number 12345 - Target vs Actual - People - Column Chart", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -5348,117 +5362,64 @@ ], "periods": [ { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" + "id": "2018" }, { - "id": "201901" + "id": "2019" }, { - "id": "201902" - }, + "id": "2020" + } + ], + "columns": [ { - "id": "201903" - }, + "id": "dx" + } + ], + "columnDimensions": [ + "dx" + ], + "filters": [ { - "id": "201904" + "id": "ou" }, { - "id": "201905" + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] }, { - "id": "201906" - }, - { - "id": "201907" - }, - { - "id": "201908" - }, - { - "id": "201909" - }, - { - "id": "201910" - }, - { - "id": "201911" - }, - { - "id": "201912" - }, - { - "id": "202001" - }, - { - "id": "202002" - }, - { - "id": "202003" - }, - { - "id": "202004" - }, - { - "id": "202005" - }, - { - "id": "202006" - }, - { - "id": "202007" - }, - { - "id": "202008" - }, - { - "id": "202009" - }, - { - "id": "202010" - } - ], - "columns": [ - { - "id": "pe" - }, - { - "code": "GENDER", - "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "MALE", - "id": "qk2FihwV6IL" - }, - { - "code": "FEMALE", - "id": "yW2hYVS3S4u" - } - ] - } - ], - "columnDimensions": [ - "pe", - "Kyg1O6YEGa9" - ], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": [ - "ou" - ], - "rows": [ - { - "id": "dx" - }, + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ { "code": "ACTUAL_TARGET", "id": "GIIHAr9BzzO", @@ -5475,50 +5436,37 @@ ] }, { - "code": "NEW_RETURNING", - "id": "uSMHdwhxFSV", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "NEW", - "id": "KiK0FMExoqh" - }, - { - "code": "RETURNING", - "id": "a6AJLXQy8vO" - } - ] + "id": "pe" } ], "rowDimensions": [ - "dx", "GIIHAr9BzzO", - "uSMHdwhxFSV" + "pe" ], "categoryDimensions": [ { "category": { - "id": "Kyg1O6YEGa9" + "id": "GIIHAr9BzzO" }, "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "imyqCWQ229K" }, { - "id": "yW2hYVS3S4u" + "id": "eWeQoOlAcxV" } ] }, { "category": { - "id": "GIIHAr9BzzO" + "id": "Kyg1O6YEGa9" }, "categoryOptions": [ { - "id": "imyqCWQ229K" + "id": "qk2FihwV6IL" }, { - "id": "eWeQoOlAcxV" + "id": "yW2hYVS3S4u" } ] }, @@ -5559,9 +5507,9 @@ ] }, { - "id": "ew6e1j5HwkE", + "id": "uwoFl2upiOM", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved to date (%) - Benefits", + "name": "Award Number 12345 - Target vs Actual - Benefits - Pivot Table", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -5573,51 +5521,51 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qu0x94utOgv" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "aYk5MgSCLXP" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qQsafE8eZQt" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "CI8NCm34d7D" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "isKcihOpMrF" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "mu2b9Ivde6J" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "OOIDqW7eQqr" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WUMjtbgofs2" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "m68LzR6ho7V" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "umkL2sEVSNR" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "KOKIhtZYDOh" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SCY3TdhSz1K" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eCufXa6RkTm" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WS8XV4WWPE7" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "i01veyO4Cuw" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" } } ], @@ -5634,79 +5582,13 @@ ], "periods": [ { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - }, - { - "id": "201904" - }, - { - "id": "201905" - }, - { - "id": "201906" - }, - { - "id": "201907" - }, - { - "id": "201908" - }, - { - "id": "201909" - }, - { - "id": "201910" - }, - { - "id": "201911" - }, - { - "id": "201912" - }, - { - "id": "202001" - }, - { - "id": "202002" - }, - { - "id": "202003" - }, - { - "id": "202004" - }, - { - "id": "202005" - }, - { - "id": "202006" - }, - { - "id": "202007" + "id": "2018" }, { - "id": "202008" - }, - { - "id": "202009" + "id": "2019" }, { - "id": "202010" + "id": "2020" } ], "columns": [ @@ -5728,15 +5610,45 @@ "rows": [ { "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], "rowDimensions": [ - "dx" + "dx", + "GIIHAr9BzzO" ], - "categoryDimensions": [], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ { "id": "M5zQapPyTZI", "displayName": "admin admin", @@ -5754,11 +5666,169 @@ "displayName": "Data Management Admin", "access": "rw------" } + ] + }, + { + "id": "ui6nUS98GBM", + "type": "COLUMN", + "name": "Award Number 12345 - Target vs Actual - Benefits - Column Chart", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "aYk5MgSCLXP" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "CI8NCm34d7D" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "mu2b9Ivde6J" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WUMjtbgofs2" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "umkL2sEVSNR" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SCY3TdhSz1K" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WS8XV4WWPE7" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" + } + } ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + }, + { + "id": "TvSmIyYcRnd" + }, + { + "id": "cqZ9zQfePzQ" + } + ], + "periods": [ + { + "id": "2018" + }, + { + "id": "2019" + }, + { + "id": "2020" + } + ], + "columns": [ + { + "id": "dx" + } + ], + "columnDimensions": [ + "dx" + ], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": [ + "ou" + ], + "rows": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + }, + { + "id": "pe" + } + ], + "rowDimensions": [ + "GIIHAr9BzzO", + "pe" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] }, { "id": "mUCwcWSsa9T", @@ -6001,9 +6071,9 @@ } }, { - "id": "KeWVSa2rbYm", + "id": "ew6e1j5HwkE", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved (%) - Benefits", + "name": "Award Number 12345 - Achieved to date (%) - Benefits", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6203,9 +6273,9 @@ } }, { - "id": "i6CWRJp61Hp", + "id": "OS2K2s8VIIq", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved to date (%) - People", + "name": "Award Number 12345 - Target vs Actual - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6213,73 +6283,73 @@ "showData": true, "aggregationType": "DEFAULT", "legendDisplayStrategy": "FIXED", - "rowTotals": false, + "rowTotals": true, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "CqURW24bmHJ" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SQy5q6kCYI1" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "iewd6jLYV4H" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iYEDR850FFL" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K6ipXoSOmt2" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qkyeCTJHU2d" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qgGwMTqEq4d" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "eAkVLI8mKBa" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "aOALuHaoaEQ" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "Kg29718LQHl" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "yeQN47GFqwM" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "KKmUWsn19fq" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K2ADN2EmEmr" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iCKxYSFIlcu" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qW6b6ZRfXA5" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qAM1NbCbS9G" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" } } ], @@ -6374,12 +6444,28 @@ "columns": [ { "id": "pe" - } - ], - "columnDimensions": [ - "pe" - ], - "filters": [ + }, + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] + } + ], + "columnDimensions": [ + "pe", + "Kyg1O6YEGa9" + ], + "filters": [ { "id": "ou" } @@ -6390,12 +6476,84 @@ "rows": [ { "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] } ], "rowDimensions": [ - "dx" + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" + ], + "categoryDimensions": [ + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } ], - "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, "userAccesses": [ @@ -6416,16 +6574,12 @@ "displayName": "Data Management Admin", "access": "rw------" } - ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } + ] }, { - "id": "eYaYrZfbJT1", + "id": "uqMTlezGj0I", "type": "PIVOT_TABLE", - "name": "Award Number 12345 - Achieved total (%) - People", + "name": "Award Number 12345 - Target vs Actual - Benefits", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6433,73 +6587,55 @@ "showData": true, "aggregationType": "DEFAULT", "legendDisplayStrategy": "FIXED", - "rowTotals": false, + "rowTotals": true, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "CqURW24bmHJ" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "iewd6jLYV4H" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K6ipXoSOmt2" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qgGwMTqEq4d" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "aYk5MgSCLXP" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "aOALuHaoaEQ" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "CI8NCm34d7D" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "yeQN47GFqwM" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "mu2b9Ivde6J" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K2ADN2EmEmr" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WUMjtbgofs2" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qW6b6ZRfXA5" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "umkL2sEVSNR" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SCY3TdhSz1K" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WS8XV4WWPE7" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" } } ], @@ -6593,45 +6729,55 @@ ], "columns": [ { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] + "id": "pe" } ], "columnDimensions": [ - "uSMHdwhxFSV" + "pe" ], "filters": [ { "id": "ou" - }, - { - "id": "pe" } ], "filterDimensions": [ - "ou", - "pe" + "ou" ], "rows": [ { "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], "rowDimensions": [ - "dx" + "dx", + "GIIHAr9BzzO" ], "categoryDimensions": [ { "category": { - "id": "uSMHdwhxFSV" + "id": "GIIHAr9BzzO" }, "categoryOptions": [ { - "id": "KiK0FMExoqh" + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" } ] } @@ -6656,16 +6802,12 @@ "displayName": "Data Management Admin", "access": "rw------" } - ], - "legendSet": { - "code": "ACTUAL_TARGET_ACHIEVED", - "id": "yoAt108kUFm" - } + ] }, { - "id": "Gi2PegQJhbu", - "type": "COLUMN", - "name": "Award Number 12345 - Achieved Benefit (%)", + "id": "i8TrzIkXGrG", + "type": "PIVOT_TABLE", + "name": "Award Number 12345 - Target vs Actual - People - Month by Month", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6677,51 +6819,69 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qu0x94utOgv" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SQy5q6kCYI1" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qQsafE8eZQt" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iYEDR850FFL" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "isKcihOpMrF" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qkyeCTJHU2d" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "OOIDqW7eQqr" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "eAkVLI8mKBa" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "m68LzR6ho7V" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "Kg29718LQHl" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "KOKIhtZYDOh" - } + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "KKmUWsn19fq" + } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eCufXa6RkTm" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iCKxYSFIlcu" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "i01veyO4Cuw" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qAM1NbCbS9G" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" } } ], @@ -6738,106 +6898,194 @@ ], "periods": [ { - "id": "201810" + "id": "201901" }, { - "id": "201811" + "id": "202001" }, { - "id": "201812" + "id": "201902" }, { - "id": "201901" + "id": "202002" }, { - "id": "201902" + "id": "201903" }, { - "id": "201903" + "id": "202003" }, { "id": "201904" }, { - "id": "201905" + "id": "202004" }, { - "id": "201906" + "id": "201905" }, { - "id": "201907" + "id": "202005" }, { - "id": "201908" + "id": "201906" }, { - "id": "201909" + "id": "202006" }, { - "id": "201910" + "id": "201907" }, { - "id": "201911" + "id": "202007" }, { - "id": "201912" + "id": "201908" }, { - "id": "202001" + "id": "202008" }, { - "id": "202002" + "id": "201909" }, { - "id": "202003" + "id": "202009" }, { - "id": "202004" + "id": "201810" }, { - "id": "202005" + "id": "201910" }, { - "id": "202006" + "id": "202010" }, { - "id": "202007" + "id": "201811" }, { - "id": "202008" + "id": "201911" }, { - "id": "202009" + "id": "201812" }, { - "id": "202010" + "id": "201912" } ], "columns": [ { - "id": "ou" + "id": "pe" } ], "columnDimensions": [ - "ou" + "pe" ], "filters": [ { - "id": "pe" + "id": "ou" + }, + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", + "id": "yW2hYVS3S4u" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] } ], "filterDimensions": [ - "pe" + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" ], "rows": [ { "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], "rowDimensions": [ - "dx" + "dx", + "GIIHAr9BzzO" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } ], - "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, "userAccesses": [ @@ -6861,9 +7109,9 @@ ] }, { - "id": "Ww2X5s48uQx", - "type": "COLUMN", - "name": "Award Number 12345 - Achieved People (%)", + "id": "aGYruOfBtaD", + "type": "PIVOT_TABLE", + "name": "Award Number 12345 - Target vs Actual - Benefits - Month by Month", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -6875,69 +7123,51 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "CqURW24bmHJ" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "iewd6jLYV4H" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K6ipXoSOmt2" - } - }, - { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qgGwMTqEq4d" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "aYk5MgSCLXP" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "aOALuHaoaEQ" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "CI8NCm34d7D" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "yeQN47GFqwM" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "mu2b9Ivde6J" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K2ADN2EmEmr" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WUMjtbgofs2" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qW6b6ZRfXA5" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "umkL2sEVSNR" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SCY3TdhSz1K" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "WS8XV4WWPE7" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "yMqK9DKbA3X" } } ], @@ -6954,122 +7184,132 @@ ], "periods": [ { - "id": "201810" + "id": "201901" }, { - "id": "201811" + "id": "202001" }, { - "id": "201812" + "id": "201902" }, { - "id": "201901" + "id": "202002" }, { - "id": "201902" + "id": "201903" }, { - "id": "201903" + "id": "202003" }, { "id": "201904" }, { - "id": "201905" + "id": "202004" }, { - "id": "201906" + "id": "201905" }, { - "id": "201907" + "id": "202005" }, { - "id": "201908" + "id": "201906" }, { - "id": "201909" + "id": "202006" }, { - "id": "201910" + "id": "201907" }, { - "id": "201911" + "id": "202007" }, { - "id": "201912" + "id": "201908" }, { - "id": "202001" + "id": "202008" }, { - "id": "202002" + "id": "201909" }, { - "id": "202003" + "id": "202009" }, { - "id": "202004" + "id": "201810" }, { - "id": "202005" + "id": "201910" }, { - "id": "202006" + "id": "202010" }, { - "id": "202007" + "id": "201811" }, { - "id": "202008" + "id": "201911" }, { - "id": "202009" + "id": "201812" }, { - "id": "202010" + "id": "201912" } ], "columns": [ { - "id": "ou" + "id": "pe" } ], "columnDimensions": [ - "ou" + "pe" ], "filters": [ { - "id": "pe" - }, - { - "id": "uSMHdwhxFSV", - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - } - ] + "id": "ou" } ], "filterDimensions": [ - "pe", - "uSMHdwhxFSV" + "ou" ], "rows": [ { "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], "rowDimensions": [ - "dx" + "dx", + "GIIHAr9BzzO" ], "categoryDimensions": [ { "category": { - "id": "uSMHdwhxFSV" + "id": "GIIHAr9BzzO" }, "categoryOptions": [ { - "id": "KiK0FMExoqh" + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" } ] } @@ -7097,9 +7337,9 @@ ] }, { - "id": "CMqisHj7sP9", - "type": "COLUMN", - "name": "Award Number 12345 - Achieved by gender (%)", + "id": "KoIzyX81ZVL", + "type": "PIVOT_TABLE", + "name": "Award Number 12345 - Target vs Actual - People - Male Only - Pivot Table", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -7111,69 +7351,69 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "CqURW24bmHJ" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SQy5q6kCYI1" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "iewd6jLYV4H" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iYEDR850FFL" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K6ipXoSOmt2" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qkyeCTJHU2d" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qgGwMTqEq4d" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "eAkVLI8mKBa" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "aOALuHaoaEQ" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "Kg29718LQHl" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "yeQN47GFqwM" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "KKmUWsn19fq" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K2ADN2EmEmr" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iCKxYSFIlcu" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "qW6b6ZRfXA5" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qAM1NbCbS9G" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "eYmeRzhBFV4" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "u404ICrBKj3" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" } }, { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "K4sH0aQDdeL" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" } } ], @@ -7190,107 +7430,34 @@ ], "periods": [ { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - }, - { - "id": "201904" - }, - { - "id": "201905" - }, - { - "id": "201906" - }, - { - "id": "201907" - }, - { - "id": "201908" - }, - { - "id": "201909" - }, - { - "id": "201910" - }, - { - "id": "201911" - }, - { - "id": "201912" - }, - { - "id": "202001" - }, - { - "id": "202002" - }, - { - "id": "202003" - }, - { - "id": "202004" - }, - { - "id": "202005" - }, - { - "id": "202006" - }, - { - "id": "202007" - }, - { - "id": "202008" + "id": "2018" }, { - "id": "202009" + "id": "2019" }, { - "id": "202010" + "id": "2020" } ], "columns": [ { - "code": "GENDER", - "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "MALE", - "id": "qk2FihwV6IL" - }, - { - "code": "FEMALE", - "id": "yW2hYVS3S4u" - } - ] + "id": "pe" } ], "columnDimensions": [ - "Kyg1O6YEGa9" + "pe" ], "filters": [ { "id": "ou" }, { - "id": "pe" + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] }, { "id": "uSMHdwhxFSV", @@ -7303,26 +7470,488 @@ ], "filterDimensions": [ "ou", - "pe", + "Kyg1O6YEGa9", "uSMHdwhxFSV" ], "rows": [ { "id": "dx" - } - ], - "rowDimensions": [ - "dx" - ], - "categoryDimensions": [ + }, { - "category": { - "id": "Kyg1O6YEGa9" - }, + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, + { + "id": "WikhmLU9agJ", + "type": "COLUMN", + "name": "Award Number 12345 - Target vs Actual - People - Male Only - Column Chart", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SQy5q6kCYI1" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iYEDR850FFL" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qkyeCTJHU2d" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "eAkVLI8mKBa" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "Kg29718LQHl" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "KKmUWsn19fq" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iCKxYSFIlcu" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qAM1NbCbS9G" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + }, + { + "id": "TvSmIyYcRnd" + }, + { + "id": "cqZ9zQfePzQ" + } + ], + "periods": [ + { + "id": "2018" + }, + { + "id": "2019" + }, + { + "id": "2020" + } + ], + "columns": [ + { + "id": "pe" + } + ], + "columnDimensions": [ + "pe" + ], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "id": "uSMHdwhxFSV", + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, + { + "id": "yamOXKh6Vok", + "type": "PIVOT_TABLE", + "name": "Award Number 12345 - Target vs Actual - People - Female Only - Pivot Table", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SQy5q6kCYI1" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iYEDR850FFL" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qkyeCTJHU2d" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "eAkVLI8mKBa" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "Kg29718LQHl" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "KKmUWsn19fq" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iCKxYSFIlcu" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qAM1NbCbS9G" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + }, + { + "id": "TvSmIyYcRnd" + }, + { + "id": "cqZ9zQfePzQ" + } + ], + "periods": [ + { + "id": "2018" + }, + { + "id": "2019" + }, + { + "id": "2020" + } + ], + "columns": [ + { + "id": "pe" + } + ], + "columnDimensions": [ + "pe" + ], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "yW2hYVS3S4u" + } + ] + }, + { + "id": "uSMHdwhxFSV", + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] + } + ], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ { "id": "yW2hYVS3S4u" } @@ -7362,9 +7991,9 @@ ] }, { - "id": "WGWGaYtwJzp", + "id": "yaQ772dtmLb", "type": "COLUMN", - "name": "Award Number 12345 - Benefits Per Person", + "name": "Award Number 12345 - Target vs Actual - People - Female Only - Column Chart", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -7376,125 +8005,187 @@ "digitGroupSeparator": "SPACE", "dataDimensionItems": [ { - "dataDimensionItemType": "INDICATOR", - "indicator": { - "id": "Gob5qHAX60C" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "SQy5q6kCYI1" } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - }, - { - "id": "TvSmIyYcRnd" - }, - { - "id": "cqZ9zQfePzQ" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - }, - { - "id": "201904" - }, - { - "id": "201905" - }, - { - "id": "201906" }, { - "id": "201907" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iYEDR850FFL" + } }, { - "id": "201908" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qkyeCTJHU2d" + } }, { - "id": "201909" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "eAkVLI8mKBa" + } }, { - "id": "201910" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "Kg29718LQHl" + } }, { - "id": "201911" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "KKmUWsn19fq" + } }, { - "id": "201912" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "iCKxYSFIlcu" + } }, { - "id": "202001" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "qAM1NbCbS9G" + } }, { - "id": "202002" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } }, { - "id": "202003" + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } }, { - "id": "202004" - }, + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ { - "id": "202005" + "id": "WGC0DJ0YSis" }, { - "id": "202006" + "id": "TvSmIyYcRnd" }, { - "id": "202007" - }, + "id": "cqZ9zQfePzQ" + } + ], + "periods": [ { - "id": "202008" + "id": "2018" }, { - "id": "202009" + "id": "2019" }, { - "id": "202010" + "id": "2020" } ], "columns": [ { - "id": "ou" + "id": "pe" } ], "columnDimensions": [ - "ou" + "pe" ], "filters": [ { - "id": "pe" + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "id": "uSMHdwhxFSV", + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] } ], "filterDimensions": [ - "pe" + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" ], "rows": [ { "id": "dx" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], "rowDimensions": [ - "dx" + "dx", + "GIIHAr9BzzO" + ], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + } + ] + } ], - "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, "userAccesses": [ diff --git a/src/pages/unique-periods/UniquePeriodsForm.tsx b/src/pages/unique-periods/UniquePeriodsForm.tsx index 198ba202..7717754e 100644 --- a/src/pages/unique-periods/UniquePeriodsForm.tsx +++ b/src/pages/unique-periods/UniquePeriodsForm.tsx @@ -10,6 +10,7 @@ import { import i18n from "../../locales"; import { Maybe } from "../../types/utils"; import { getErrors } from "../../domain/entities/generic/Errors"; +import { months } from "../../utils/date"; export type UniquePeriodsFormProps = { existingPeriod?: UniqueBeneficiariesPeriodsAttrs; @@ -17,21 +18,6 @@ export type UniquePeriodsFormProps = { onSubmit: (uniquePeriods: UniqueBeneficiariesPeriod) => void; }; -export const months = [ - { value: "1", text: i18n.t("January") }, - { value: "2", text: i18n.t("February") }, - { value: "3", text: i18n.t("March") }, - { value: "4", text: i18n.t("April") }, - { value: "5", text: i18n.t("May") }, - { value: "6", text: i18n.t("June") }, - { value: "7", text: i18n.t("July") }, - { value: "8", text: i18n.t("August") }, - { value: "9", text: i18n.t("September") }, - { value: "10", text: i18n.t("October") }, - { value: "11", text: i18n.t("November") }, - { value: "12", text: i18n.t("December") }, -]; - function getValueByAttribute( value: string, attribute: keyof UniqueBeneficiariesPeriod diff --git a/src/utils/date.ts b/src/utils/date.ts index 8180d29c..35bb52d7 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -1,5 +1,5 @@ import moment, { Moment } from "moment"; -import { months } from "../pages/unique-periods/UniquePeriodsForm"; +import i18n from "../locales"; export function toISOString(date: Moment) { return date.format("YYYY-MM-DDTHH:mm:ss"); @@ -58,3 +58,18 @@ export function buildMonthYearFormatDate(dateIsoString: string): string { export function getMonthNameFromNumber(monthNumber: string | number): string { return months.find(month => month.value === monthNumber.toString())?.text || ""; } + +export const months = [ + { value: "1", text: i18n.t("January") }, + { value: "2", text: i18n.t("February") }, + { value: "3", text: i18n.t("March") }, + { value: "4", text: i18n.t("April") }, + { value: "5", text: i18n.t("May") }, + { value: "6", text: i18n.t("June") }, + { value: "7", text: i18n.t("July") }, + { value: "8", text: i18n.t("August") }, + { value: "9", text: i18n.t("September") }, + { value: "10", text: i18n.t("October") }, + { value: "11", text: i18n.t("November") }, + { value: "12", text: i18n.t("December") }, +]; From 738a8859ee90e2f3948cf72e98bad2f4483f0597 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 27 Mar 2026 12:32:41 -0500 Subject: [PATCH 17/49] fix tests --- src/models/__tests__/ProjectDb.spec.ts | 7 +- .../__tests__/data/project-db-metadata.json | 526 ++++-------------- 2 files changed, 118 insertions(+), 415 deletions(-) diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index a51d2587..1aaa1799 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -21,10 +21,9 @@ const dataStoreUpdateResponse = { describe("ProjectDb", () => { describe("save", () => { it("posts metadata", async () => { - const project = (await getProject(api, { orgUnit: undefined })).updateDataElementsMERSelection( - "ieyBABjYyHO", - ["ik0ICagvIjm"] - ).project; + const project = ( + await getProject(api, { orgUnit: undefined }) + ).updateDataElementsMERSelection("ieyBABjYyHO", ["ik0ICagvIjm"]).project; // Validation mock.onGet("/metadata", { diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index ffb1dc69..04872870 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1541,9 +1541,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "dx" @@ -1552,18 +1550,13 @@ "id": "ou" } ], - "filterDimensions": [ - "dx", - "ou" - ], + "filterDimensions": ["dx", "ou"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1676,9 +1669,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "dx" @@ -1717,20 +1708,13 @@ ] } ], - "filterDimensions": [ - "dx", - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1857,25 +1841,19 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1976,9 +1954,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "dx" @@ -2017,20 +1993,13 @@ ] } ], - "filterDimensions": [ - "dx", - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -2151,17 +2120,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2182,10 +2147,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2301,18 +2263,13 @@ ] } ], - "columnDimensions": [ - "pe", - "Kyg1O6YEGa9" - ], + "columnDimensions": ["pe", "Kyg1O6YEGa9"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2348,11 +2305,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -2473,17 +2426,13 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "pe" @@ -2504,10 +2453,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2608,9 +2554,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -2646,11 +2590,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "pe" @@ -2671,10 +2611,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2807,17 +2744,13 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2826,10 +2759,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -2942,9 +2872,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -2980,11 +2908,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -2993,10 +2917,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3135,9 +3056,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3166,11 +3085,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3179,10 +3094,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3318,9 +3230,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3349,11 +3259,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3362,10 +3268,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3501,9 +3404,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3532,11 +3433,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3545,10 +3442,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3695,9 +3589,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3726,11 +3618,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3739,10 +3627,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3871,25 +3756,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3980,25 +3859,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4083,25 +3956,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4188,9 +4055,7 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" @@ -4204,18 +4069,13 @@ ] } ], - "filterDimensions": [ - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -4325,9 +4185,7 @@ ] } ], - "columnDimensions": [ - "Kyg1O6YEGa9" - ], + "columnDimensions": ["Kyg1O6YEGa9"], "filters": [ { "id": "ou" @@ -4344,19 +4202,13 @@ ] } ], - "filterDimensions": [ - "ou", - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -4455,25 +4307,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4598,9 +4444,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "pe" @@ -4622,19 +4466,13 @@ ] } ], - "filterDimensions": [ - "pe", - "uSMHdwhxFSV", - "GIIHAr9BzzO" - ], + "filterDimensions": ["pe", "uSMHdwhxFSV", "GIIHAr9BzzO"], "rows": [ { "id": "ou" } ], - "rowDimensions": [ - "ou" - ], + "rowDimensions": ["ou"], "categoryDimensions": [ { "category": { @@ -4742,9 +4580,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "pe" @@ -4758,18 +4594,13 @@ ] } ], - "filterDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "filterDimensions": ["pe", "GIIHAr9BzzO"], "rows": [ { "id": "ou" } ], - "rowDimensions": [ - "ou" - ], + "rowDimensions": ["ou"], "categoryDimensions": [ { "category": { @@ -4879,9 +4710,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -4903,19 +4732,13 @@ ] } ], - "filterDimensions": [ - "ou", - "uSMHdwhxFSV", - "GIIHAr9BzzO" - ], + "filterDimensions": ["ou", "uSMHdwhxFSV", "GIIHAr9BzzO"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -5017,9 +4840,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -5033,18 +4854,13 @@ ] } ], - "filterDimensions": [ - "ou", - "GIIHAr9BzzO" - ], + "filterDimensions": ["ou", "GIIHAr9BzzO"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -5167,17 +4983,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -5213,11 +5025,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -5376,9 +5184,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -5414,11 +5220,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "code": "ACTUAL_TARGET", @@ -5439,10 +5241,7 @@ "id": "pe" } ], - "rowDimensions": [ - "GIIHAr9BzzO", - "pe" - ], + "rowDimensions": ["GIIHAr9BzzO", "pe"], "categoryDimensions": [ { "category": { @@ -5596,17 +5395,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -5627,10 +5422,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -5758,17 +5550,13 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "code": "ACTUAL_TARGET", @@ -5789,10 +5577,7 @@ "id": "pe" } ], - "rowDimensions": [ - "GIIHAr9BzzO", - "pe" - ], + "rowDimensions": ["GIIHAr9BzzO", "pe"], "categoryDimensions": [ { "category": { @@ -6009,9 +5794,7 @@ ] } ], - "columnDimensions": [ - "uSMHdwhxFSV" - ], + "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" @@ -6020,18 +5803,13 @@ "id": "pe" } ], - "filterDimensions": [ - "ou", - "pe" - ], + "filterDimensions": ["ou", "pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -6226,25 +6004,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6461,18 +6233,13 @@ ] } ], - "columnDimensions": [ - "pe", - "Kyg1O6YEGa9" - ], + "columnDimensions": ["pe", "Kyg1O6YEGa9"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -6508,11 +6275,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -6732,17 +6495,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -6763,10 +6522,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -6978,9 +6734,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7016,11 +6770,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7041,10 +6791,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7264,17 +7011,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -7295,10 +7038,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7444,9 +7184,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7468,11 +7206,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7493,10 +7227,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7662,9 +7393,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7686,11 +7415,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7711,10 +7436,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7880,9 +7602,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7904,11 +7624,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7929,10 +7645,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -8098,9 +7811,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -8122,11 +7833,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -8147,10 +7854,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -8209,4 +7913,4 @@ ] } ] -} \ No newline at end of file +} From d3d25b76720c9f4a30253e2df19046b219b1426e Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 27 Mar 2026 12:38:10 -0500 Subject: [PATCH 18/49] remove comments --- src/models/Dashboard.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/models/Dashboard.ts b/src/models/Dashboard.ts index b8a36a06..87732c97 100644 --- a/src/models/Dashboard.ts +++ b/src/models/Dashboard.ts @@ -30,8 +30,6 @@ interface Item { export interface VisualizationDefinition { type: "chart" | "table"; - // TODO: validate if having undefined for the other visualizations - // modify somehow the functionality chartType?: Exclude; periodStrategy?: PeriodStrategy; key: string; From 6681a08a1e53350b682e6c730ca7fbcd7c14b44d Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Wed, 8 Apr 2026 15:10:11 -0500 Subject: [PATCH 19/49] regenerate award dashboard from action --- src/models/ProjectDashboard.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 8dff4270..f25d9714 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -847,12 +847,10 @@ export async function getAwardNumberDashboard( if (!project) { return { type: "error" as const, message: "No dashboard found" }; - } else if (project.dashboard.awardNumber) { - return { type: "success" as const, data: project.dashboard.awardNumber }; } else { const { awardNumber } = project; const generator = await ProjectDashboard.buildForAwardNumber(api, config, awardNumber); - const metadata = generator.generate(); + const metadata = generator.generate({ minimumOrgUnits: 2 }); const dashboard = metadata.dashboards[0]; if (!dashboard) return { type: "error", message: "Error generating dashboard" }; From ff3c0c0171f6b46c45da71602338cb4070ccd774 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Thu, 9 Apr 2026 22:31:31 -0500 Subject: [PATCH 20/49] add all mer indicators in MER - Target vs Actual - Benefits - Column Chart --- src/models/ProjectDashboard.ts | 4 ++-- src/models/__tests__/data/project-db-metadata.json | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index f25d9714..8b08573d 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -294,8 +294,8 @@ export default class ProjectDashboard { type: "chart", key: "chart-mer-target-actual-benefits", name: i18n.t("MER - Target vs Actual - Benefits - Column Chart"), - items: dataElementItems(merDataElements.benefit), - filters: [dimensions.orgUnit], + items: dataElementItems(merDataElements.all), + filters: [dimensions.data, dimensions.orgUnit], columns: [config.categories.targetActual], rows: [dimensions.period], }); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 04872870..0d959368 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1792,6 +1792,12 @@ "rowTotals": true, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { From 9cbc2af4753432ea8e72a2556caa8857554233eb Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Thu, 9 Apr 2026 22:34:18 -0500 Subject: [PATCH 21/49] update metadata for tests --- src/models/__tests__/data/project-db-metadata.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 0d959368..892244cd 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1849,11 +1849,14 @@ ], "columnDimensions": ["GIIHAr9BzzO"], "filters": [ + { + "id": "dx" + }, { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": ["dx", "ou"], "rows": [ { "id": "pe" From bb68513d73777f0e4200170dc347d5c94b42ad9c Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Tue, 21 Apr 2026 20:28:23 -0500 Subject: [PATCH 22/49] generate script to remove paired dataElements --- src/models/ProjectsList.ts | 6 +- .../unique-periods/UniquePeriodsForm.tsx | 16 +- src/scripts/remove-paired-dataelement.ts | 138 ++++++++++++++++++ src/utils/date.ts | 17 ++- 4 files changed, 160 insertions(+), 17 deletions(-) create mode 100644 src/scripts/remove-paired-dataelement.ts diff --git a/src/models/ProjectsList.ts b/src/models/ProjectsList.ts index a3cff1cc..2a7d5466 100644 --- a/src/models/ProjectsList.ts +++ b/src/models/ProjectsList.ts @@ -1,5 +1,4 @@ import _ from "lodash"; -import { TableSorting } from "@eyeseetea/d2-ui-components"; import { D2Api, D2OrganisationUnitSchema, SelectedPick, Id, Pager, Ref } from "../types/d2-api"; import { Config } from "./Config"; import moment, { Moment } from "moment"; @@ -399,3 +398,8 @@ function getOrgUnitsFilter(filters: FiltersForList, currentUser: User) { : userCountryIds; return filterCountryIds ? { "parent.id": { in: filterCountryIds } } : {}; } + +export type TableSorting = { + field: keyof T; + order: "asc" | "desc"; +}; diff --git a/src/pages/unique-periods/UniquePeriodsForm.tsx b/src/pages/unique-periods/UniquePeriodsForm.tsx index 198ba202..7717754e 100644 --- a/src/pages/unique-periods/UniquePeriodsForm.tsx +++ b/src/pages/unique-periods/UniquePeriodsForm.tsx @@ -10,6 +10,7 @@ import { import i18n from "../../locales"; import { Maybe } from "../../types/utils"; import { getErrors } from "../../domain/entities/generic/Errors"; +import { months } from "../../utils/date"; export type UniquePeriodsFormProps = { existingPeriod?: UniqueBeneficiariesPeriodsAttrs; @@ -17,21 +18,6 @@ export type UniquePeriodsFormProps = { onSubmit: (uniquePeriods: UniqueBeneficiariesPeriod) => void; }; -export const months = [ - { value: "1", text: i18n.t("January") }, - { value: "2", text: i18n.t("February") }, - { value: "3", text: i18n.t("March") }, - { value: "4", text: i18n.t("April") }, - { value: "5", text: i18n.t("May") }, - { value: "6", text: i18n.t("June") }, - { value: "7", text: i18n.t("July") }, - { value: "8", text: i18n.t("August") }, - { value: "9", text: i18n.t("September") }, - { value: "10", text: i18n.t("October") }, - { value: "11", text: i18n.t("November") }, - { value: "12", text: i18n.t("December") }, -]; - function getValueByAttribute( value: string, attribute: keyof UniqueBeneficiariesPeriod diff --git a/src/scripts/remove-paired-dataelement.ts b/src/scripts/remove-paired-dataelement.ts new file mode 100644 index 00000000..bdace879 --- /dev/null +++ b/src/scripts/remove-paired-dataelement.ts @@ -0,0 +1,138 @@ +import _ from "lodash"; +import parse from "parse-typed-args"; +import { promiseMap } from "../migrations/utils"; +import { getConfig } from "../models/Config"; +import { D2Api } from "../types/d2-api"; +import fs from "fs"; + +async function main() { + const parser = parse({ + opts: { + url: {}, + auth: {}, + codes: {}, + persist: { switch: true }, + }, + }); + const { opts } = parser(process.argv); + const { url, auth, codes, persist } = opts; + + const usage = + "npx tsx remove-paired-dataelement --url= [--auth=user:pass] [--codes=deCode1,deCode2] [--persist]"; + if (!url) { + console.error(usage); + process.exit(1); + } + + if (!codes || codes.length === 0) { + console.error(usage); + process.exit(1); + } + + const [username, password] = auth ? auth.split(":") : ["", ""]; + const api = new D2Api({ baseUrl: url, auth: { password, username }, agent: {} }); + const config = await getConfig(api); + + // TODO: request in chunks + const responseDes = await api.models.dataElements + .get({ + fields: { id: true, attributeValues: { attribute: { id: true }, value: true } }, + filter: { code: { in: codes.split(",") } }, + paging: false, + }) + .getData(); + + if (responseDes.objects.length === 0) { + console.debug("No data elements found with the provided codes"); + return; + } + + const dataElements = responseDes.objects.map((de): DataElement => { + return { + id: de.id, + pairedDataElement: de.attributeValues?.find( + av => av.attribute.id === config.attributes.pairedDataElement.id + )?.value, + }; + }); + + const dataElementsWithPaired = dataElements.filter(de => de.pairedDataElement); + + console.debug(`Found ${dataElementsWithPaired.length} dataElements with paired data elements`); + + const allDeIds = dataElementsWithPaired.map(de => de.id); + + const allStats = await promiseMap(_(allDeIds).chunk(100).value(), async dataElementIds => { + const response = await api.models.dataElements + .get({ + fields: { $owner: true }, + filter: { id: { in: dataElementIds } }, + paging: false, + }) + .getData(); + + const dataElementsToUpdate = dataElementIds.map(dataElementId => { + const existingDe = response.objects.find(de => de.id === dataElementId); + + const dataElement = dataElementsWithPaired.find(de => de.id === dataElementId); + if (!dataElement) { + throw Error("Cannot find dataElement"); + } + + const newAttributeValues = existingDe?.attributeValues.map(d2Attribute => { + if (d2Attribute.attribute.id === config.attributes.pairedDataElement.id) { + return { + ...d2Attribute, + value: "", + }; + } + return d2Attribute; + }); + + return { ...(existingDe || {}), attributeValues: newAttributeValues }; + }); + + const persistResponse = await api.metadata + .post( + { dataElements: dataElementsToUpdate }, + { importMode: persist ? "COMMIT" : "VALIDATE", importStrategy: "UPDATE" } + ) + .getData(); + + // @ts-ignore + const stats = persistResponse.response.stats; + return { stats: stats, payload: dataElementsToUpdate }; + }); + + console.debug( + "Stats: ", + allStats.reduce( + (acum, stat) => { + return { + created: (acum.created || 0) + (stat.stats.created || 0), + updated: (acum.updated || 0) + (stat.stats.updated || 0), + deleted: (acum.deleted || 0) + (stat.stats.deleted || 0), + ignored: (acum.ignored || 0) + (stat.stats.ignored || 0), + }; + }, + { created: 0, updated: 0, deleted: 0, ignored: 0 } + ) + ); + + // save payload to disk + fs.writeFileSync( + "data_elements_paired_dataelements.json", + JSON.stringify( + allStats.flatMap(stat => stat.payload), + null, + 2 + ) + ); +} + +type DataElement = { + id: string; + pairedDataElement?: string; +}; + +main(); diff --git a/src/utils/date.ts b/src/utils/date.ts index 8180d29c..35bb52d7 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -1,5 +1,5 @@ import moment, { Moment } from "moment"; -import { months } from "../pages/unique-periods/UniquePeriodsForm"; +import i18n from "../locales"; export function toISOString(date: Moment) { return date.format("YYYY-MM-DDTHH:mm:ss"); @@ -58,3 +58,18 @@ export function buildMonthYearFormatDate(dateIsoString: string): string { export function getMonthNameFromNumber(monthNumber: string | number): string { return months.find(month => month.value === monthNumber.toString())?.text || ""; } + +export const months = [ + { value: "1", text: i18n.t("January") }, + { value: "2", text: i18n.t("February") }, + { value: "3", text: i18n.t("March") }, + { value: "4", text: i18n.t("April") }, + { value: "5", text: i18n.t("May") }, + { value: "6", text: i18n.t("June") }, + { value: "7", text: i18n.t("July") }, + { value: "8", text: i18n.t("August") }, + { value: "9", text: i18n.t("September") }, + { value: "10", text: i18n.t("October") }, + { value: "11", text: i18n.t("November") }, + { value: "12", text: i18n.t("December") }, +]; From 89c68ed16b3068e1179b76adc81f6f94c17e6855 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Tue, 21 Apr 2026 20:30:49 -0500 Subject: [PATCH 23/49] improve error message --- src/scripts/remove-paired-dataelement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripts/remove-paired-dataelement.ts b/src/scripts/remove-paired-dataelement.ts index bdace879..f853febd 100644 --- a/src/scripts/remove-paired-dataelement.ts +++ b/src/scripts/remove-paired-dataelement.ts @@ -18,7 +18,7 @@ async function main() { const { url, auth, codes, persist } = opts; const usage = - "npx tsx remove-paired-dataelement --url= [--auth=user:pass] [--codes=deCode1,deCode2] [--persist]"; + "npx tsx src/scripts/remove-paired-dataelement.ts --url= [--auth=user:pass] [--codes=deCode1,deCode2] [--persist]"; if (!url) { console.error(usage); process.exit(1); From 565fe5afe91768f390fd0f2b2e76c6856155a5b2 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Wed, 29 Apr 2026 12:18:35 -0500 Subject: [PATCH 24/49] remove targetvsactual benefits/people column chart and sort de by code --- src/models/ProjectDashboard.ts | 44 ++++------------------------------ 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 8b08573d..be7cc631 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -144,8 +144,6 @@ export default class ProjectDashboard { ]); return _.compact([ - this.targetVsActualBenefitsChart(), - this.targetVsActualPeopleChart(), this.merTargetVsActualBenefitsChart(), this.merTargetVsActualPeopleChart(), targetVsActualBenefitsTable_, @@ -218,23 +216,6 @@ export default class ProjectDashboard { }); } - targetVsActualBenefitsChart(): MaybeD2Visualization { - const { config, dataElements } = this; - const dataElementsNoDisaggregated = dataElements.benefit.filter( - de => !de.categories.includes("newRecurring") - ); - - return this.getD2VisualizationFromDefinition({ - type: "chart", - key: "chart-target-actual-benefits", - name: i18n.t("Target vs Actual - Benefits - Column Chart"), - items: dataElementItems(dataElementsNoDisaggregated), - filters: [dimensions.data, dimensions.orgUnit], - columns: [config.categories.targetActual], - rows: [dimensions.period], - }); - } - awardNumberTargetVsActualBenefitsColumnChart(): MaybeD2Visualization { const { config, dataElements } = this; const dataElementsNoDisaggregated = dataElements.benefit.filter( @@ -253,25 +234,6 @@ export default class ProjectDashboard { }); } - targetVsActualPeopleChart(): MaybeD2Visualization { - const { config, dataElements } = this; - - return this.getD2VisualizationFromDefinition({ - type: "chart", - key: "chart-target-actual-people", - name: i18n.t("Target vs Actual - People - Column Chart"), - items: dataElementItems(dataElements.people), - filters: [ - dimensions.data, - dimensions.orgUnit, - config.categories.gender, - config.categories.newRecurring, - ], - columns: [config.categories.targetActual], - rows: [dimensions.period], - }); - } - awardNumberTargetVsActualPeopleColumnChart(): MaybeD2Visualization { const { config, dataElements } = this; @@ -340,11 +302,15 @@ export default class ProjectDashboard { targetVsActualPeopleDisaggregatedByIndicatorChart(): MaybeD2Visualization { const { config, dataElements } = this; + const dePeopleSortedByCode = _(dataElements.people) + .sortBy(de => de.code) + .value(); + return this.getD2VisualizationFromDefinition({ type: "chart", key: "chart-target-actual-people-disaggregated-by-indicator", name: i18n.t("Target vs Actual - People - Column Chart Disaggregated By Indicator"), - items: dataElementItems(dataElements.people), + items: dataElementItems(dePeopleSortedByCode), filters: [dimensions.orgUnit, config.categories.gender, config.categories.newRecurring], columns: [dimensions.data], rows: [dimensions.period, config.categories.targetActual], From 6075ec93c754d65e997363720930ca692b8fd9c9 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Wed, 29 Apr 2026 14:22:45 -0500 Subject: [PATCH 25/49] reorder male only vis. and update targetvsactual mer charts --- src/models/ProjectDashboard.ts | 29 +- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 1269 ++++++++--------- 3 files changed, 623 insertions(+), 677 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index be7cc631..520be54e 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -29,10 +29,11 @@ import { Condition, } from "./ProjectsListDashboard"; import { getVisualizationPeriods } from "./Period"; +import { DataElement as MerDataElement } from "./dataElementsSet"; export default class ProjectDashboard { dataElements: ProjectsListDashboard["dataElements"]; - merDataElements: Record<"all" | "people" | "benefit", Ref[]>; + merDataElements: Record<"all" | "people" | "benefit", MerDataElement[]>; categoryOnlyNew: { id: Id; categoryOptions: Ref[] }; categoryOnlyMale: { id: Id; categoryOptions: Ref[] }; categoryOnlyFemale: { id: Id; categoryOptions: Ref[] }; @@ -148,13 +149,13 @@ export default class ProjectDashboard { this.merTargetVsActualPeopleChart(), targetVsActualBenefitsTable_, targetVsActualPeopleTable_, + this.targetVsActualPeopleLineChartMaleOnly(), + this.targetVsActualPeopleLineColumnChartMaleOnly(), this.targetVsActualBenefitsDisaggregatedByIndicatorChart(), this.targetVsActualPeopleDisaggregatedByIndicatorChart(), this.targetVsActualBenefitsLineChart(), this.targetVsActualPeopleLineChart(), - this.targetVsActualPeopleLineChartMaleOnly(), this.targetVsActualPeopleLineChartFemaleOnly(), - this.targetVsActualPeopleLineColumnChartMaleOnly(), this.targetVsActualPeopleLineColumnChartFemaleOnly(), achievedBenefitsToDateTable_, achievedPeopleToDateTable_, @@ -251,15 +252,18 @@ export default class ProjectDashboard { merTargetVsActualBenefitsChart(): MaybeD2Visualization { const { config, merDataElements } = this; + const dataElementsNoDisaggregated = merDataElements.all.filter( + de => !de.categories.includes("newRecurring") + ); return this.getD2VisualizationFromDefinition({ type: "chart", key: "chart-mer-target-actual-benefits", name: i18n.t("MER - Target vs Actual - Benefits - Column Chart"), - items: dataElementItems(merDataElements.all), - filters: [dimensions.data, dimensions.orgUnit], - columns: [config.categories.targetActual], - rows: [dimensions.period], + items: dataElementItems(dataElementsNoDisaggregated), + filters: [dimensions.orgUnit], + columns: [dimensions.data], + rows: [dimensions.period, config.categories.targetActual], }); } @@ -271,14 +275,9 @@ export default class ProjectDashboard { key: "chart-mer-target-actual-people", name: i18n.t("MER - Target vs Actual - People - Column Chart"), items: dataElementItems(merDataElements.people), - filters: [ - dimensions.data, - dimensions.orgUnit, - config.categories.gender, - config.categories.newRecurring, - ], - columns: [config.categories.targetActual], - rows: [dimensions.period], + filters: [dimensions.orgUnit, config.categories.gender, config.categories.newRecurring], + columns: [dimensions.data], + rows: [dimensions.period, config.categories.targetActual], }); } diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 1aaa1799..97c38125 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -142,7 +142,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,ywQZlYBN4nN,q0Arl96SxH5,yWq2ZBWiK8T,uYWdSMZQ1LH,i07AWJAND8a,iqqgnCj9DQj,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,OuKm5zK7l53,iOk52Z42bjp,GM6SxObVwI3,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,CAEdMM5XM5T,GiUz1pZI2Rq,uwoFl2upiOM,ui6nUS98GBM,mUCwcWSsa9T,ew6e1j5HwkE,OS2K2s8VIIq,uqMTlezGj0I,i8TrzIkXGrG,aGYruOfBtaD,KoIzyX81ZVL,WikhmLU9agJ,yamOXKh6Vok,yaQ772dtmLb]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,yWq2ZBWiK8T,uYWdSMZQ1LH,i07AWJAND8a,iqqgnCj9DQj,S2kJHgM41El,W2SCFrHCiEm,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,KasxZ8vT1n0,OuKm5zK7l53,iOk52Z42bjp,GM6SxObVwI3,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,CAEdMM5XM5T,GiUz1pZI2Rq,uwoFl2upiOM,ui6nUS98GBM,mUCwcWSsa9T,ew6e1j5HwkE,OS2K2s8VIIq,uqMTlezGj0I,i8TrzIkXGrG,aGYruOfBtaD,KoIzyX81ZVL,WikhmLU9agJ,yamOXKh6Vok,yaQ772dtmLb]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 892244cd..cf821c0c 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -996,10 +996,10 @@ "name": "12345en - MyProject", "dashboardItems": [ { - "id": "uOsjh5OmILO", + "id": "WQwlyfCElo8", "type": "CHART", "visualization": { - "id": "ywQZlYBN4nN" + "id": "yWq2ZBWiK8T" }, "width": 29, "height": 20, @@ -1007,10 +1007,10 @@ "y": 0 }, { - "id": "mouU4wUzbJ3", + "id": "imK8xQLwwYX", "type": "CHART", "visualization": { - "id": "q0Arl96SxH5" + "id": "uYWdSMZQ1LH" }, "width": 29, "height": 20, @@ -1018,10 +1018,10 @@ "y": 0 }, { - "id": "WQwlyfCElo8", - "type": "CHART", + "id": "Ka4yijY2Vhl", + "type": "REPORT_TABLE", "visualization": { - "id": "yWq2ZBWiK8T" + "id": "i07AWJAND8a" }, "width": 29, "height": 20, @@ -1029,10 +1029,10 @@ "y": 20 }, { - "id": "imK8xQLwwYX", - "type": "CHART", + "id": "yWGKgz9vaOh", + "type": "REPORT_TABLE", "visualization": { - "id": "uYWdSMZQ1LH" + "id": "iqqgnCj9DQj" }, "width": 29, "height": 20, @@ -1040,10 +1040,10 @@ "y": 20 }, { - "id": "Ka4yijY2Vhl", - "type": "REPORT_TABLE", + "id": "W4DOghdXUmp", + "type": "CHART", "visualization": { - "id": "i07AWJAND8a" + "id": "S2kJHgM41El" }, "width": 29, "height": 20, @@ -1051,10 +1051,10 @@ "y": 40 }, { - "id": "yWGKgz9vaOh", - "type": "REPORT_TABLE", + "id": "K2amO1SBZFm", + "type": "CHART", "visualization": { - "id": "iqqgnCj9DQj" + "id": "W2SCFrHCiEm" }, "width": 29, "height": 20, @@ -1105,17 +1105,6 @@ "x": 29, "y": 80 }, - { - "id": "W4DOghdXUmp", - "type": "CHART", - "visualization": { - "id": "S2kJHgM41El" - }, - "width": 29, - "height": 20, - "x": 0, - "y": 100 - }, { "id": "OgO4mL6ovvU", "type": "CHART", @@ -1124,19 +1113,8 @@ }, "width": 29, "height": 20, - "x": 29, - "y": 100 - }, - { - "id": "K2amO1SBZFm", - "type": "CHART", - "visualization": { - "id": "W2SCFrHCiEm" - }, - "width": 29, - "height": 20, "x": 0, - "y": 120 + "y": 100 }, { "id": "GW6MALzFIVR", @@ -1147,7 +1125,7 @@ "width": 29, "height": 20, "x": 29, - "y": 120 + "y": 100 }, { "id": "m4LaU9HizHi", @@ -1158,7 +1136,7 @@ "width": 29, "height": 20, "x": 0, - "y": 140 + "y": 120 }, { "id": "uyoJujQVRjE", @@ -1169,7 +1147,7 @@ "width": 29, "height": 20, "x": 29, - "y": 140 + "y": 120 }, { "id": "KI0C90Ol10x", @@ -1180,7 +1158,7 @@ "width": 29, "height": 20, "x": 0, - "y": 160 + "y": 140 }, { "id": "uYY7v977Ubm", @@ -1191,7 +1169,7 @@ "width": 29, "height": 20, "x": 29, - "y": 160 + "y": 140 }, { "id": "qUqsDmtiBLF", @@ -1202,7 +1180,7 @@ "width": 29, "height": 20, "x": 0, - "y": 180 + "y": 160 }, { "id": "mwMpIdPdu8H", @@ -1213,7 +1191,7 @@ "width": 29, "height": 20, "x": 29, - "y": 180 + "y": 160 } ], "publicAccess": "--------", @@ -1473,9 +1451,9 @@ ], "visualizations": [ { - "id": "ywQZlYBN4nN", + "id": "yWq2ZBWiK8T", "type": "COLUMN", - "name": "12345en - MyProject - Target vs Actual - Benefits - Column Chart", + "name": "12345en - MyProject - MER - Target vs Actual - Benefits - Column Chart", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -1486,12 +1464,6 @@ "rowTotals": true, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "WS8XV4WWPE7" - } - }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { @@ -1525,6 +1497,25 @@ } ], "columns": [ + { + "id": "dx" + } + ], + "columnDimensions": [ + "dx" + ], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": [ + "ou" + ], + "rows": [ + { + "id": "pe" + }, { "code": "ACTUAL_TARGET", "id": "GIIHAr9BzzO", @@ -1541,22 +1532,10 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], - "filters": [ - { - "id": "dx" - }, - { - "id": "ou" - } - ], - "filterDimensions": ["dx", "ou"], - "rows": [ - { - "id": "pe" - } + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" ], - "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1595,9 +1574,9 @@ ] }, { - "id": "q0Arl96SxH5", + "id": "uYWdSMZQ1LH", "type": "COLUMN", - "name": "12345en - MyProject - Target vs Actual - People - Column Chart", + "name": "12345en - MyProject - MER - Target vs Actual - People - Column Chart", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -1608,23 +1587,11 @@ "rowTotals": true, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "K6mAC5SiO29" - } - }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { "id": "ik0ICagvIjm" } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "GQyudNlGzkI" - } } ], "organisationUnits": [ @@ -1654,26 +1621,13 @@ ], "columns": [ { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", - "categoryOptions": [ - { - "code": "TARGET", - "id": "imyqCWQ229K" - }, - { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" - } - ] + "id": "dx" } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "dx" + ], "filters": [ - { - "id": "dx" - }, { "id": "ou" }, @@ -1708,13 +1662,35 @@ ] } ], - "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "pe" + }, + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -1779,9 +1755,9 @@ ] }, { - "id": "yWq2ZBWiK8T", - "type": "COLUMN", - "name": "12345en - MyProject - MER - Target vs Actual - Benefits - Column Chart", + "id": "i07AWJAND8a", + "type": "PIVOT_TABLE", + "name": "12345en - MyProject - Target vs Actual - Benefits", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -1795,7 +1771,7 @@ { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "ik0ICagvIjm" + "id": "WS8XV4WWPE7" } }, { @@ -1831,6 +1807,25 @@ } ], "columns": [ + { + "id": "pe" + } + ], + "columnDimensions": [ + "pe" + ], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": [ + "ou" + ], + "rows": [ + { + "id": "dx" + }, { "code": "ACTUAL_TARGET", "id": "GIIHAr9BzzO", @@ -1847,22 +1842,10 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], - "filters": [ - { - "id": "dx" - }, - { - "id": "ou" - } - ], - "filterDimensions": ["dx", "ou"], - "rows": [ - { - "id": "pe" - } + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" ], - "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -1901,9 +1884,9 @@ ] }, { - "id": "uYWdSMZQ1LH", - "type": "COLUMN", - "name": "12345en - MyProject - MER - Target vs Actual - People - Column Chart", + "id": "iqqgnCj9DQj", + "type": "PIVOT_TABLE", + "name": "12345en - MyProject - Target vs Actual - People", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -1914,11 +1897,23 @@ "rowTotals": true, "digitGroupSeparator": "SPACE", "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { "id": "ik0ICagvIjm" } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } } ], "organisationUnits": [ @@ -1948,41 +1943,52 @@ ], "columns": [ { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", + "id": "pe" + }, + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", "categoryOptions": [ { - "code": "TARGET", - "id": "imyqCWQ229K" + "code": "MALE", + "id": "qk2FihwV6IL" }, { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" + "code": "FEMALE", + "id": "yW2hYVS3S4u" } ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "pe", + "Kyg1O6YEGa9" + ], "filters": [ - { - "id": "dx" - }, { "id": "ou" + } + ], + "filterDimensions": [ + "ou" + ], + "rows": [ + { + "id": "dx" }, { - "code": "GENDER", - "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", "categoryOptions": [ { - "code": "MALE", - "id": "qk2FihwV6IL" + "code": "TARGET", + "id": "imyqCWQ229K" }, { - "code": "FEMALE", - "id": "yW2hYVS3S4u" + "code": "ACTUAL", + "id": "eWeQoOlAcxV" } ] }, @@ -2002,37 +2008,35 @@ ] } ], - "filterDimensions": ["dx", "ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], - "rows": [ - { - "id": "pe" - } + "rowDimensions": [ + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" ], - "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { - "id": "GIIHAr9BzzO" + "id": "Kyg1O6YEGa9" }, "categoryOptions": [ { - "id": "imyqCWQ229K" + "id": "qk2FihwV6IL" }, { - "id": "eWeQoOlAcxV" + "id": "yW2hYVS3S4u" } ] }, { "category": { - "id": "Kyg1O6YEGa9" + "id": "GIIHAr9BzzO" }, "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "imyqCWQ229K" }, { - "id": "yW2hYVS3S4u" + "id": "eWeQoOlAcxV" } ] }, @@ -2073,131 +2077,9 @@ ] }, { - "id": "i07AWJAND8a", - "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Target vs Actual - Benefits", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": true, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "WS8XV4WWPE7" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "yMqK9DKbA3X" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - } - ], - "columns": [ - { - "id": "pe" - } - ], - "columnDimensions": ["pe"], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "dx" - }, - { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", - "categoryOptions": [ - { - "code": "TARGET", - "id": "imyqCWQ229K" - }, - { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" - } - ] - } - ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], - "categoryDimensions": [ - { - "category": { - "id": "GIIHAr9BzzO" - }, - "categoryOptions": [ - { - "id": "imyqCWQ229K" - }, - { - "id": "eWeQoOlAcxV" - } - ] - } - ], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } - ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ] - }, - { - "id": "iqqgnCj9DQj", - "type": "PIVOT_TABLE", - "name": "12345en - MyProject - Target vs Actual - People", + "id": "S2kJHgM41El", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Male Only", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2254,47 +2136,33 @@ ], "columns": [ { - "id": "pe" - }, - { - "code": "GENDER", - "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", "categoryOptions": [ { - "code": "MALE", - "id": "qk2FihwV6IL" + "code": "TARGET", + "id": "imyqCWQ229K" }, { - "code": "FEMALE", - "id": "yW2hYVS3S4u" + "code": "ACTUAL", + "id": "eWeQoOlAcxV" } ] } ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "dx" }, { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", + "id": "Kyg1O6YEGa9", "categoryOptions": [ { - "code": "TARGET", - "id": "imyqCWQ229K" - }, - { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" + "id": "qk2FihwV6IL" } ] }, @@ -2314,31 +2182,44 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { - "id": "Kyg1O6YEGa9" + "id": "GIIHAr9BzzO" }, "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "imyqCWQ229K" }, { - "id": "yW2hYVS3S4u" + "id": "eWeQoOlAcxV" } ] }, { "category": { - "id": "GIIHAr9BzzO" + "id": "Kyg1O6YEGa9" }, "categoryOptions": [ { - "id": "imyqCWQ229K" - }, - { - "id": "eWeQoOlAcxV" + "id": "qk2FihwV6IL" } ] }, @@ -2379,9 +2260,9 @@ ] }, { - "id": "a46jcQ65Axt", - "type": "COLUMN", - "name": "12345en - MyProject - Target vs Actual - Benefits - Column Chart Disaggregated By Indicator", + "id": "W2SCFrHCiEm", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line/Column Chart - Male Only", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2395,13 +2276,19 @@ { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "WS8XV4WWPE7" + "id": "K6mAC5SiO29" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "yMqK9DKbA3X" + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" } } ], @@ -2431,21 +2318,6 @@ } ], "columns": [ - { - "id": "dx" - } - ], - "columnDimensions": ["dx"], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "pe" - }, { "code": "ACTUAL_TARGET", "id": "GIIHAr9BzzO", @@ -2462,124 +2334,18 @@ ] } ], - "rowDimensions": ["pe", "GIIHAr9BzzO"], - "categoryDimensions": [ - { - "category": { - "id": "GIIHAr9BzzO" - }, - "categoryOptions": [ - { - "id": "imyqCWQ229K" - }, - { - "id": "eWeQoOlAcxV" - } - ] - } - ], - "publicAccess": "--------", - "externalAccess": false, - "userAccesses": [ - { - "id": "M5zQapPyTZI", - "displayName": "admin admin", - "access": "rw------" - } + "columnDimensions": [ + "GIIHAr9BzzO" ], - "userGroupAccesses": [ - { - "id": "ywuI2WspUUG", - "displayName": "System Admin", - "access": "rw------" - }, - { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" - } - ] - }, - { - "id": "GA87u7JwgSK", - "type": "COLUMN", - "name": "12345en - MyProject - Target vs Actual - People - Column Chart Disaggregated By Indicator", - "numberType": "VALUE", - "legendDisplayStyle": "FILL", - "rowSubTotals": true, - "showDimensionLabels": true, - "showData": true, - "aggregationType": "DEFAULT", - "legendDisplayStrategy": "FIXED", - "rowTotals": true, - "digitGroupSeparator": "SPACE", - "dataDimensionItems": [ - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "K6mAC5SiO29" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "ik0ICagvIjm" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "GQyudNlGzkI" - } - } - ], - "organisationUnits": [ - { - "id": "WGC0DJ0YSis" - } - ], - "periods": [ - { - "id": "201810" - }, - { - "id": "201811" - }, - { - "id": "201812" - }, - { - "id": "201901" - }, - { - "id": "201902" - }, - { - "id": "201903" - } - ], - "columns": [ - { - "id": "dx" - } - ], - "columnDimensions": ["dx"], "filters": [ { "id": "ou" }, { - "code": "GENDER", "id": "Kyg1O6YEGa9", - "dataDimensionType": "DISAGGREGATION", "categoryOptions": [ { - "code": "MALE", "id": "qk2FihwV6IL" - }, - { - "code": "FEMALE", - "id": "yW2hYVS3S4u" } ] }, @@ -2599,28 +2365,23 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { - "id": "pe" + "id": "dx" }, { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", - "categoryOptions": [ - { - "code": "TARGET", - "id": "imyqCWQ229K" - }, - { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" - } - ] + "id": "pe" } ], - "rowDimensions": ["pe", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -2642,9 +2403,6 @@ "categoryOptions": [ { "id": "qk2FihwV6IL" - }, - { - "id": "yW2hYVS3S4u" } ] }, @@ -2678,16 +2436,27 @@ "access": "rw------" }, { - "id": "mKKNXzeIAJs", - "displayName": "Data Management Admin", - "access": "rw------" + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ], + "series": [ + { + "dimensionItem": "imyqCWQ229K", + "axis": 0 + }, + { + "dimensionItem": "eWeQoOlAcxV", + "axis": 0, + "type": "COLUMN" } ] }, { - "id": "KiUTxsMMYde", - "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - Benefits - Line Chart", + "id": "a46jcQ65Axt", + "type": "COLUMN", + "name": "12345en - MyProject - Target vs Actual - Benefits - Column Chart Disaggregated By Indicator", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2737,6 +2506,25 @@ } ], "columns": [ + { + "id": "dx" + } + ], + "columnDimensions": [ + "dx" + ], + "filters": [ + { + "id": "ou" + } + ], + "filterDimensions": [ + "ou" + ], + "rows": [ + { + "id": "pe" + }, { "code": "ACTUAL_TARGET", "id": "GIIHAr9BzzO", @@ -2753,22 +2541,10 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], - "filters": [ - { - "id": "ou" - } - ], - "filterDimensions": ["ou"], - "rows": [ - { - "id": "dx" - }, - { - "id": "pe" - } + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" ], - "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -2807,9 +2583,9 @@ ] }, { - "id": "GkoTRBEmIQt", - "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - People - Line Chart", + "id": "GA87u7JwgSK", + "type": "COLUMN", + "name": "12345en - MyProject - Target vs Actual - People - Column Chart Disaggregated By Indicator", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2866,22 +2642,12 @@ ], "columns": [ { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", - "categoryOptions": [ - { - "code": "TARGET", - "id": "imyqCWQ229K" - }, - { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" - } - ] + "id": "dx" } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -2917,16 +2683,35 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { - "id": "dx" + "id": "pe" }, { - "id": "pe" + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -2991,9 +2776,9 @@ ] }, { - "id": "S2kJHgM41El", + "id": "KiUTxsMMYde", "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Male Only", + "name": "12345en - MyProject - Target vs Actual - Benefits - Line Chart", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -3007,19 +2792,13 @@ { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "K6mAC5SiO29" - } - }, - { - "dataDimensionItemType": "DATA_ELEMENT", - "dataElement": { - "id": "ik0ICagvIjm" + "id": "WS8XV4WWPE7" } }, { "dataDimensionItemType": "DATA_ELEMENT", "dataElement": { - "id": "GQyudNlGzkI" + "id": "yMqK9DKbA3X" } } ], @@ -3065,36 +2844,17 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" - }, - { - "id": "Kyg1O6YEGa9", - "categoryOptions": [ - { - "id": "qk2FihwV6IL" - } - ] - }, - { - "code": "NEW_RETURNING", - "id": "uSMHdwhxFSV", - "dataDimensionType": "DISAGGREGATION", - "categoryOptions": [ - { - "code": "NEW", - "id": "KiK0FMExoqh" - }, - { - "code": "RETURNING", - "id": "a6AJLXQy8vO" - } - ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -3103,7 +2863,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -3117,29 +2880,6 @@ "id": "eWeQoOlAcxV" } ] - }, - { - "category": { - "id": "Kyg1O6YEGa9" - }, - "categoryOptions": [ - { - "id": "qk2FihwV6IL" - } - ] - }, - { - "category": { - "id": "uSMHdwhxFSV" - }, - "categoryOptions": [ - { - "id": "KiK0FMExoqh" - }, - { - "id": "a6AJLXQy8vO" - } - ] } ], "publicAccess": "--------", @@ -3165,9 +2905,9 @@ ] }, { - "id": "KasxZ8vT1n0", + "id": "GkoTRBEmIQt", "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Female Only", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -3239,15 +2979,24 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" }, { + "code": "GENDER", "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", "categoryOptions": [ { + "code": "MALE", + "id": "qk2FihwV6IL" + }, + { + "code": "FEMALE", "id": "yW2hYVS3S4u" } ] @@ -3268,7 +3017,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -3277,7 +3030,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -3297,6 +3053,9 @@ "id": "Kyg1O6YEGa9" }, "categoryOptions": [ + { + "id": "qk2FihwV6IL" + }, { "id": "yW2hYVS3S4u" } @@ -3339,9 +3098,9 @@ ] }, { - "id": "W2SCFrHCiEm", + "id": "KasxZ8vT1n0", "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - People - Line/Column Chart - Male Only", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Female Only", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -3413,7 +3172,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" @@ -3422,7 +3183,7 @@ "id": "Kyg1O6YEGa9", "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "yW2hYVS3S4u" } ] }, @@ -3442,7 +3203,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -3451,7 +3216,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -3472,7 +3240,7 @@ }, "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "yW2hYVS3S4u" } ] }, @@ -3510,17 +3278,6 @@ "displayName": "Data Management Admin", "access": "rw------" } - ], - "series": [ - { - "dimensionItem": "imyqCWQ229K", - "axis": 0 - }, - { - "dimensionItem": "eWeQoOlAcxV", - "axis": 0, - "type": "COLUMN" - } ] }, { @@ -3598,7 +3355,9 @@ ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": [ + "GIIHAr9BzzO" + ], "filters": [ { "id": "ou" @@ -3627,7 +3386,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -3636,7 +3399,10 @@ "id": "pe" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": [ + "dx", + "pe" + ], "categoryDimensions": [ { "category": { @@ -3765,19 +3531,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3868,19 +3640,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3965,19 +3743,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4064,7 +3848,9 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" @@ -4078,13 +3864,18 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -4194,7 +3985,9 @@ ] } ], - "columnDimensions": ["Kyg1O6YEGa9"], + "columnDimensions": [ + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" @@ -4211,13 +4004,19 @@ ] } ], - "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "pe", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -4316,19 +4115,25 @@ "id": "ou" } ], - "columnDimensions": ["ou"], + "columnDimensions": [ + "ou" + ], "filters": [ { "id": "pe" } ], - "filterDimensions": ["pe"], + "filterDimensions": [ + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4453,7 +4258,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "pe" @@ -4475,13 +4282,19 @@ ] } ], - "filterDimensions": ["pe", "uSMHdwhxFSV", "GIIHAr9BzzO"], + "filterDimensions": [ + "pe", + "uSMHdwhxFSV", + "GIIHAr9BzzO" + ], "rows": [ { "id": "ou" } ], - "rowDimensions": ["ou"], + "rowDimensions": [ + "ou" + ], "categoryDimensions": [ { "category": { @@ -4589,7 +4402,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "pe" @@ -4603,13 +4418,18 @@ ] } ], - "filterDimensions": ["pe", "GIIHAr9BzzO"], + "filterDimensions": [ + "pe", + "GIIHAr9BzzO" + ], "rows": [ { "id": "ou" } ], - "rowDimensions": ["ou"], + "rowDimensions": [ + "ou" + ], "categoryDimensions": [ { "category": { @@ -4719,7 +4539,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -4741,13 +4563,19 @@ ] } ], - "filterDimensions": ["ou", "uSMHdwhxFSV", "GIIHAr9BzzO"], + "filterDimensions": [ + "ou", + "uSMHdwhxFSV", + "GIIHAr9BzzO" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -4849,7 +4677,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -4863,13 +4693,18 @@ ] } ], - "filterDimensions": ["ou", "GIIHAr9BzzO"], + "filterDimensions": [ + "ou", + "GIIHAr9BzzO" + ], "rows": [ { "id": "pe" } ], - "rowDimensions": ["pe"], + "rowDimensions": [ + "pe" + ], "categoryDimensions": [ { "category": { @@ -4992,13 +4827,17 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -5034,7 +4873,11 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" + ], "categoryDimensions": [ { "category": { @@ -5193,7 +5036,9 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" @@ -5229,7 +5074,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "code": "ACTUAL_TARGET", @@ -5250,7 +5099,10 @@ "id": "pe" } ], - "rowDimensions": ["GIIHAr9BzzO", "pe"], + "rowDimensions": [ + "GIIHAr9BzzO", + "pe" + ], "categoryDimensions": [ { "category": { @@ -5404,13 +5256,17 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -5431,7 +5287,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -5559,13 +5418,17 @@ "id": "dx" } ], - "columnDimensions": ["dx"], + "columnDimensions": [ + "dx" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "code": "ACTUAL_TARGET", @@ -5586,7 +5449,10 @@ "id": "pe" } ], - "rowDimensions": ["GIIHAr9BzzO", "pe"], + "rowDimensions": [ + "GIIHAr9BzzO", + "pe" + ], "categoryDimensions": [ { "category": { @@ -5803,7 +5669,9 @@ ] } ], - "columnDimensions": ["uSMHdwhxFSV"], + "columnDimensions": [ + "uSMHdwhxFSV" + ], "filters": [ { "id": "ou" @@ -5812,13 +5680,18 @@ "id": "pe" } ], - "filterDimensions": ["ou", "pe"], + "filterDimensions": [ + "ou", + "pe" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [ { "category": { @@ -6013,19 +5886,25 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" } ], - "rowDimensions": ["dx"], + "rowDimensions": [ + "dx" + ], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6242,13 +6121,18 @@ ] } ], - "columnDimensions": ["pe", "Kyg1O6YEGa9"], + "columnDimensions": [ + "pe", + "Kyg1O6YEGa9" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -6284,7 +6168,11 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO", + "uSMHdwhxFSV" + ], "categoryDimensions": [ { "category": { @@ -6504,13 +6392,17 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -6531,7 +6423,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -6743,7 +6638,9 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" @@ -6779,7 +6676,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -6800,7 +6701,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -7020,13 +6924,17 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" } ], - "filterDimensions": ["ou"], + "filterDimensions": [ + "ou" + ], "rows": [ { "id": "dx" @@ -7047,7 +6955,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -7193,7 +7104,9 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" @@ -7215,7 +7128,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -7236,7 +7153,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -7402,7 +7322,9 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" @@ -7424,7 +7346,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -7445,7 +7371,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -7611,7 +7540,9 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" @@ -7633,7 +7564,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -7654,7 +7589,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -7820,7 +7758,9 @@ "id": "pe" } ], - "columnDimensions": ["pe"], + "columnDimensions": [ + "pe" + ], "filters": [ { "id": "ou" @@ -7842,7 +7782,11 @@ ] } ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "filterDimensions": [ + "ou", + "Kyg1O6YEGa9", + "uSMHdwhxFSV" + ], "rows": [ { "id": "dx" @@ -7863,7 +7807,10 @@ ] } ], - "rowDimensions": ["dx", "GIIHAr9BzzO"], + "rowDimensions": [ + "dx", + "GIIHAr9BzzO" + ], "categoryDimensions": [ { "category": { @@ -7922,4 +7869,4 @@ ] } ] -} +} \ No newline at end of file From a09834762f180a505160c34a30fd538edd4bd4d6 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Wed, 29 Apr 2026 14:40:50 -0500 Subject: [PATCH 26/49] update metadata test --- .../__tests__/data/project-db-metadata.json | 499 ++++-------------- 1 file changed, 109 insertions(+), 390 deletions(-) diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index cf821c0c..b5d13dea 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -1501,17 +1501,13 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "pe" @@ -1532,10 +1528,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -1624,9 +1617,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -1662,11 +1653,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "pe" @@ -1687,10 +1674,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -1811,17 +1795,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -1842,10 +1822,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -1961,18 +1938,13 @@ ] } ], - "columnDimensions": [ - "pe", - "Kyg1O6YEGa9" - ], + "columnDimensions": ["pe", "Kyg1O6YEGa9"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2008,11 +1980,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -2151,9 +2119,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -2182,11 +2148,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -2195,10 +2157,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -2334,9 +2293,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -2365,11 +2322,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -2378,10 +2331,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -2510,17 +2460,13 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "pe" @@ -2541,10 +2487,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2645,9 +2588,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -2683,11 +2624,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "pe" @@ -2708,10 +2645,7 @@ ] } ], - "rowDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "rowDimensions": ["pe", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -2844,17 +2778,13 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -2863,10 +2793,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -2979,9 +2906,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3017,11 +2942,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3030,10 +2951,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3172,9 +3090,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3203,11 +3119,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3216,10 +3128,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3355,9 +3264,7 @@ ] } ], - "columnDimensions": [ - "GIIHAr9BzzO" - ], + "columnDimensions": ["GIIHAr9BzzO"], "filters": [ { "id": "ou" @@ -3386,11 +3293,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -3399,10 +3302,7 @@ "id": "pe" } ], - "rowDimensions": [ - "dx", - "pe" - ], + "rowDimensions": ["dx", "pe"], "categoryDimensions": [ { "category": { @@ -3531,25 +3431,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3640,25 +3534,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3743,25 +3631,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -3848,9 +3730,7 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" @@ -3864,18 +3744,13 @@ ] } ], - "filterDimensions": [ - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -3985,9 +3860,7 @@ ] } ], - "columnDimensions": [ - "Kyg1O6YEGa9" - ], + "columnDimensions": ["Kyg1O6YEGa9"], "filters": [ { "id": "ou" @@ -4004,19 +3877,13 @@ ] } ], - "filterDimensions": [ - "ou", - "pe", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "pe", "uSMHdwhxFSV"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -4115,25 +3982,19 @@ "id": "ou" } ], - "columnDimensions": [ - "ou" - ], + "columnDimensions": ["ou"], "filters": [ { "id": "pe" } ], - "filterDimensions": [ - "pe" - ], + "filterDimensions": ["pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -4258,9 +4119,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "pe" @@ -4282,19 +4141,13 @@ ] } ], - "filterDimensions": [ - "pe", - "uSMHdwhxFSV", - "GIIHAr9BzzO" - ], + "filterDimensions": ["pe", "uSMHdwhxFSV", "GIIHAr9BzzO"], "rows": [ { "id": "ou" } ], - "rowDimensions": [ - "ou" - ], + "rowDimensions": ["ou"], "categoryDimensions": [ { "category": { @@ -4402,9 +4255,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "pe" @@ -4418,18 +4269,13 @@ ] } ], - "filterDimensions": [ - "pe", - "GIIHAr9BzzO" - ], + "filterDimensions": ["pe", "GIIHAr9BzzO"], "rows": [ { "id": "ou" } ], - "rowDimensions": [ - "ou" - ], + "rowDimensions": ["ou"], "categoryDimensions": [ { "category": { @@ -4539,9 +4385,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -4563,19 +4407,13 @@ ] } ], - "filterDimensions": [ - "ou", - "uSMHdwhxFSV", - "GIIHAr9BzzO" - ], + "filterDimensions": ["ou", "uSMHdwhxFSV", "GIIHAr9BzzO"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -4677,9 +4515,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -4693,18 +4529,13 @@ ] } ], - "filterDimensions": [ - "ou", - "GIIHAr9BzzO" - ], + "filterDimensions": ["ou", "GIIHAr9BzzO"], "rows": [ { "id": "pe" } ], - "rowDimensions": [ - "pe" - ], + "rowDimensions": ["pe"], "categoryDimensions": [ { "category": { @@ -4827,17 +4658,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -4873,11 +4700,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -5036,9 +4859,7 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" @@ -5074,11 +4895,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "code": "ACTUAL_TARGET", @@ -5099,10 +4916,7 @@ "id": "pe" } ], - "rowDimensions": [ - "GIIHAr9BzzO", - "pe" - ], + "rowDimensions": ["GIIHAr9BzzO", "pe"], "categoryDimensions": [ { "category": { @@ -5256,17 +5070,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -5287,10 +5097,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -5418,17 +5225,13 @@ "id": "dx" } ], - "columnDimensions": [ - "dx" - ], + "columnDimensions": ["dx"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "code": "ACTUAL_TARGET", @@ -5449,10 +5252,7 @@ "id": "pe" } ], - "rowDimensions": [ - "GIIHAr9BzzO", - "pe" - ], + "rowDimensions": ["GIIHAr9BzzO", "pe"], "categoryDimensions": [ { "category": { @@ -5669,9 +5469,7 @@ ] } ], - "columnDimensions": [ - "uSMHdwhxFSV" - ], + "columnDimensions": ["uSMHdwhxFSV"], "filters": [ { "id": "ou" @@ -5680,18 +5478,13 @@ "id": "pe" } ], - "filterDimensions": [ - "ou", - "pe" - ], + "filterDimensions": ["ou", "pe"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [ { "category": { @@ -5886,25 +5679,19 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" } ], - "rowDimensions": [ - "dx" - ], + "rowDimensions": ["dx"], "categoryDimensions": [], "publicAccess": "--------", "externalAccess": false, @@ -6121,18 +5908,13 @@ ] } ], - "columnDimensions": [ - "pe", - "Kyg1O6YEGa9" - ], + "columnDimensions": ["pe", "Kyg1O6YEGa9"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -6168,11 +5950,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO", - "uSMHdwhxFSV" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO", "uSMHdwhxFSV"], "categoryDimensions": [ { "category": { @@ -6392,17 +6170,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -6423,10 +6197,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -6638,9 +6409,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -6676,11 +6445,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -6701,10 +6466,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -6924,17 +6686,13 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" } ], - "filterDimensions": [ - "ou" - ], + "filterDimensions": ["ou"], "rows": [ { "id": "dx" @@ -6955,10 +6713,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7104,9 +6859,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7128,11 +6881,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7153,10 +6902,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7322,9 +7068,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7346,11 +7090,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7371,10 +7111,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7540,9 +7277,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7564,11 +7299,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7589,10 +7320,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7758,9 +7486,7 @@ "id": "pe" } ], - "columnDimensions": [ - "pe" - ], + "columnDimensions": ["pe"], "filters": [ { "id": "ou" @@ -7782,11 +7508,7 @@ ] } ], - "filterDimensions": [ - "ou", - "Kyg1O6YEGa9", - "uSMHdwhxFSV" - ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], "rows": [ { "id": "dx" @@ -7807,10 +7529,7 @@ ] } ], - "rowDimensions": [ - "dx", - "GIIHAr9BzzO" - ], + "rowDimensions": ["dx", "GIIHAr9BzzO"], "categoryDimensions": [ { "category": { @@ -7869,4 +7588,4 @@ ] } ] -} \ No newline at end of file +} From 66d8980cd5dbbee5cef48526ccfb321103f40ee2 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Thu, 30 Apr 2026 10:08:52 -0500 Subject: [PATCH 27/49] reorder indicators in MER charts --- src/models/ProjectDashboard.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 520be54e..1cff37a3 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -283,9 +283,10 @@ export default class ProjectDashboard { targetVsActualBenefitsDisaggregatedByIndicatorChart(): MaybeD2Visualization { const { config, dataElements } = this; - const dataElementsNoDisaggregated = dataElements.benefit.filter( - de => !de.categories.includes("newRecurring") - ); + const dataElementsNoDisaggregated = _(dataElements.benefit) + .filter(de => !de.categories.includes("newRecurring")) + .sortBy(de => de.code) + .value(); return this.getD2VisualizationFromDefinition({ type: "chart", From 82680f611e680ad0d9a5061e78023afaf242963d Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Date: Thu, 30 Apr 2026 13:00:43 -0500 Subject: [PATCH 28/49] sorted only selected items for MER visualizations --- src/models/ProjectDashboard.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 1cff37a3..74d8ef8e 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -252,9 +252,10 @@ export default class ProjectDashboard { merTargetVsActualBenefitsChart(): MaybeD2Visualization { const { config, merDataElements } = this; - const dataElementsNoDisaggregated = merDataElements.all.filter( - de => !de.categories.includes("newRecurring") - ); + const dataElementsNoDisaggregated = _(merDataElements.all) + .filter(de => !de.categories.includes("newRecurring")) + .sortBy(de => de.code) + .value(); return this.getD2VisualizationFromDefinition({ type: "chart", @@ -270,11 +271,15 @@ export default class ProjectDashboard { merTargetVsActualPeopleChart(): MaybeD2Visualization { const { config, merDataElements } = this; + const sortedItems = _(merDataElements.people) + .sortBy(de => de.code) + .value(); + return this.getD2VisualizationFromDefinition({ type: "chart", key: "chart-mer-target-actual-people", name: i18n.t("MER - Target vs Actual - People - Column Chart"), - items: dataElementItems(merDataElements.people), + items: dataElementItems(sortedItems), filters: [dimensions.orgUnit, config.categories.gender, config.categories.newRecurring], columns: [dimensions.data], rows: [dimensions.period, config.categories.targetActual], From deca3f7aedb269e8919d13bd3ee4f39ace4dd20d Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 1 May 2026 13:11:02 -0500 Subject: [PATCH 29/49] fix reorder charts --- src/models/ProjectDashboard.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index 74d8ef8e..e115ff3d 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -149,13 +149,13 @@ export default class ProjectDashboard { this.merTargetVsActualPeopleChart(), targetVsActualBenefitsTable_, targetVsActualPeopleTable_, - this.targetVsActualPeopleLineChartMaleOnly(), - this.targetVsActualPeopleLineColumnChartMaleOnly(), this.targetVsActualBenefitsDisaggregatedByIndicatorChart(), this.targetVsActualPeopleDisaggregatedByIndicatorChart(), this.targetVsActualBenefitsLineChart(), this.targetVsActualPeopleLineChart(), + this.targetVsActualPeopleLineChartMaleOnly(), this.targetVsActualPeopleLineChartFemaleOnly(), + this.targetVsActualPeopleLineColumnChartMaleOnly(), this.targetVsActualPeopleLineColumnChartFemaleOnly(), achievedBenefitsToDateTable_, achievedPeopleToDateTable_, From c88edee779aab1e3a9fb37eac6dbd6c48705999a Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Fri, 1 May 2026 16:16:16 -0500 Subject: [PATCH 30/49] add new charts and text items --- i18n/en.pot | 10 +- src/models/Dashboard.ts | 3 +- src/models/ProjectDashboard.ts | 61 +- src/models/__tests__/ProjectDb.spec.ts | 2 +- .../__tests__/data/project-db-metadata.json | 620 +++++++++++++++--- 5 files changed, 584 insertions(+), 112 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index ed20a6f7..e6215582 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2026-03-27T15:30:46.362Z\n" -"PO-Revision-Date: 2026-03-27T15:30:46.362Z\n" +"POT-Creation-Date: 2026-05-01T19:09:52.637Z\n" +"PO-Revision-Date: 2026-05-01T19:09:52.637Z\n" msgid "Validating Project" msgstr "" @@ -624,6 +624,12 @@ msgstr "" msgid "Target vs Actual - People - Line Chart - Male Only" msgstr "" +msgid "Target vs Actual - People - Line Chart - Gender New Only" +msgstr "" + +msgid "Target vs Actual - People - Line Chart - New Only" +msgstr "" + msgid "Target vs Actual - People - Line Chart - Female Only" msgstr "" diff --git a/src/models/Dashboard.ts b/src/models/Dashboard.ts index 87732c97..e233a0b7 100644 --- a/src/models/Dashboard.ts +++ b/src/models/Dashboard.ts @@ -175,9 +175,10 @@ export function positionItems(items: DashboardItem[], options: PositionItemsOpti return items.reduce<{ pos: Pos; outputItems: DashboardItem[] }>( ({ pos, outputItems }, item) => { + const isText = item.type === "TEXT"; const width = Math.min(item.width || defaultWidth, maxWidth); const itemPos = pos.x + width > maxWidth ? { x: 0, y: pos.y + defaultHeight } : pos; - const newItem = { ...item, width, height: defaultHeight, ...itemPos }; + const newItem = { ...item, width, height: isText ? 6 : defaultHeight, ...itemPos }; const newPos = { x: itemPos.x + newItem.width, y: itemPos.y }; return { pos: newPos, outputItems: [...outputItems, newItem] }; }, diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index e115ff3d..a68ad05a 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -122,10 +122,37 @@ export default class ProjectDashboard { defaultHeight: 20, // 20 vertical units ~ 50% of viewport height }; + const title = + "*Comparison of Target vs Actual Benefit and People Indicators* \n _(Used to compare make comparison between the target and actual of an indicator, comparison of actuals between activities that go together, used to look at the distribution (shape) of an activity (does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_"; + + const firstTextItem: PartialModel = { + id: getUid("first", "text-project-dashboard"), + type: "TEXT", + text: i18n.t(title), + width: toItemWidth(100), + }; + + const eigthTitle = + "*Comparison of Target vs Actual Benefit and People Disaggregated by Indicator* \n _(Better to analyze trends by indicator or up to 5 indicators across time, does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_"; + + const eighthTextItem: PartialModel = { + id: getUid("eighth", "text-project-dashboard"), + type: "TEXT", + text: i18n.t(eigthTitle), + width: toItemWidth(100), + }; + + const dashboardItemsToSave = [ + firstTextItem, + ...items.slice(0, 8), + eighthTextItem, + ...items.slice(8), + ]; + const dashboard = { id: getUid("dashboard", projectsListDashboard.id), name: projectsListDashboard.name, - dashboardItems: positionItems(items, positionItemsOptions), + dashboardItems: positionItems(dashboardItemsToSave, positionItemsOptions), ...new ProjectSharing(config, projectsListDashboard).getSharingAttributesForDashboard(), }; @@ -149,6 +176,8 @@ export default class ProjectDashboard { this.merTargetVsActualPeopleChart(), targetVsActualBenefitsTable_, targetVsActualPeopleTable_, + this.targetVsActualPeopleLineChartGenderNewOnly(), + this.targetVsActualPeopleLineChartNewOnly(), this.targetVsActualBenefitsDisaggregatedByIndicatorChart(), this.targetVsActualPeopleDisaggregatedByIndicatorChart(), this.targetVsActualBenefitsLineChart(), @@ -370,6 +399,36 @@ export default class ProjectDashboard { }); } + targetVsActualPeopleLineChartGenderNewOnly(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-people-line-gender-new", + name: i18n.t("Target vs Actual - People - Line Chart - Gender New Only"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, this.categoryOnlyNew, dimensions.period], + columns: [config.categories.gender], + rows: [config.categories.targetActual, dimensions.data], + }); + } + + targetVsActualPeopleLineChartNewOnly(): MaybeD2Visualization { + const { config, dataElements } = this; + + return this.getD2VisualizationFromDefinition({ + type: "chart", + chartType: "LINE", + key: "chart-target-actual-people-line-new-only", + name: i18n.t("Target vs Actual - People - Line Chart - New Only"), + items: dataElementItems(dataElements.people), + filters: [dimensions.orgUnit, this.categoryOnlyNew, dimensions.period], + columns: [config.categories.targetActual], + rows: [config.categories.gender, dimensions.data], + }); + } + targetVsActualPeopleLineChartFemaleOnly(): MaybeD2Visualization { const { config, dataElements } = this; diff --git a/src/models/__tests__/ProjectDb.spec.ts b/src/models/__tests__/ProjectDb.spec.ts index 97c38125..b0fd8d84 100644 --- a/src/models/__tests__/ProjectDb.spec.ts +++ b/src/models/__tests__/ProjectDb.spec.ts @@ -142,7 +142,7 @@ describe("ProjectDb", () => { mock.onGet("/metadata", { params: { - filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,yWq2ZBWiK8T,uYWdSMZQ1LH,i07AWJAND8a,iqqgnCj9DQj,S2kJHgM41El,W2SCFrHCiEm,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,KasxZ8vT1n0,OuKm5zK7l53,iOk52Z42bjp,GM6SxObVwI3,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,CAEdMM5XM5T,GiUz1pZI2Rq,uwoFl2upiOM,ui6nUS98GBM,mUCwcWSsa9T,ew6e1j5HwkE,OS2K2s8VIIq,uqMTlezGj0I,i8TrzIkXGrG,aGYruOfBtaD,KoIzyX81ZVL,WikhmLU9agJ,yamOXKh6Vok,yaQ772dtmLb]", + filter: "id:in:[WGC0DJ0YSis,eu2XF73JOzl,GG0k0oNhgS7,em8NIwi0KvM,OKEZCrPzqph,WIEp6vpQw6n,OUGGW1cHaYy,SCS4Dusnfdd,CwUxT9UIX3z,WgOMVlwSV2i,qyG6foGIKEx,OiCmorbkHNf,yWq2ZBWiK8T,uYWdSMZQ1LH,i07AWJAND8a,iqqgnCj9DQj,mwCW9Tw2EGo,yGi6VuebV62,a46jcQ65Axt,GA87u7JwgSK,KiUTxsMMYde,GkoTRBEmIQt,S2kJHgM41El,KasxZ8vT1n0,W2SCFrHCiEm,OuKm5zK7l53,iOk52Z42bjp,GM6SxObVwI3,qmsj4FqnVPX,uiyYMLiDaK2,u6Sin4Fy1Wt,ukewRkZsyCI,KOiGcdA4JjD,CS7csnUtibF,GqYJDh6asM8,me6p7L8VHXl,CAEdMM5XM5T,GiUz1pZI2Rq,uwoFl2upiOM,ui6nUS98GBM,mUCwcWSsa9T,ew6e1j5HwkE,OS2K2s8VIIq,uqMTlezGj0I,i8TrzIkXGrG,aGYruOfBtaD,KoIzyX81ZVL,WikhmLU9agJ,yamOXKh6Vok,yaQ772dtmLb]", fields: "id,created", }, }).replyOnce(200, {}); diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index b5d13dea..35e1be8b 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -995,6 +995,15 @@ "id": "WgOMVlwSV2i", "name": "12345en - MyProject", "dashboardItems": [ + { + "id": "eyYVx2rS9d6", + "type": "TEXT", + "text": "*Comparison of Target vs Actual Benefit and People Indicators* \n _(Used to compare make comparison between the target and actual of an indicator, comparison of actuals between activities that go together, used to look at the distribution (shape) of an activity (does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", + "width": 58, + "height": 6, + "x": 0, + "y": 0 + }, { "id": "WQwlyfCElo8", "type": "CHART", @@ -1004,7 +1013,7 @@ "width": 29, "height": 20, "x": 0, - "y": 0 + "y": 20 }, { "id": "imK8xQLwwYX", @@ -1015,7 +1024,7 @@ "width": 29, "height": 20, "x": 29, - "y": 0 + "y": 20 }, { "id": "Ka4yijY2Vhl", @@ -1026,7 +1035,7 @@ "width": 29, "height": 20, "x": 0, - "y": 20 + "y": 40 }, { "id": "yWGKgz9vaOh", @@ -1037,29 +1046,29 @@ "width": 29, "height": 20, "x": 29, - "y": 20 + "y": 40 }, { - "id": "W4DOghdXUmp", + "id": "ukqMD1FXnpN", "type": "CHART", "visualization": { - "id": "S2kJHgM41El" + "id": "mwCW9Tw2EGo" }, "width": 29, "height": 20, "x": 0, - "y": 40 + "y": 60 }, { - "id": "K2amO1SBZFm", + "id": "iEIdvITqSEp", "type": "CHART", "visualization": { - "id": "W2SCFrHCiEm" + "id": "yGi6VuebV62" }, "width": 29, "height": 20, "x": 29, - "y": 40 + "y": 60 }, { "id": "i66m5HwnH6v", @@ -1070,7 +1079,7 @@ "width": 29, "height": 20, "x": 0, - "y": 60 + "y": 80 }, { "id": "a4GacNVWHLX", @@ -1081,7 +1090,16 @@ "width": 29, "height": 20, "x": 29, - "y": 60 + "y": 80 + }, + { + "id": "qSeVeYd2sd8", + "type": "TEXT", + "text": "*Comparison of Target vs Actual Benefit and People Disaggregated by Indicator* \n _(Better to analyze trends by indicator or up to 5 indicators across time, does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", + "width": 58, + "height": 6, + "x": 0, + "y": 100 }, { "id": "KYcDaXAZa1q", @@ -1092,7 +1110,7 @@ "width": 29, "height": 20, "x": 0, - "y": 80 + "y": 120 }, { "id": "a6cSVlR6bSj", @@ -1103,7 +1121,18 @@ "width": 29, "height": 20, "x": 29, - "y": 80 + "y": 120 + }, + { + "id": "W4DOghdXUmp", + "type": "CHART", + "visualization": { + "id": "S2kJHgM41El" + }, + "width": 29, + "height": 20, + "x": 0, + "y": 140 }, { "id": "OgO4mL6ovvU", @@ -1113,8 +1142,19 @@ }, "width": 29, "height": 20, + "x": 29, + "y": 140 + }, + { + "id": "K2amO1SBZFm", + "type": "CHART", + "visualization": { + "id": "W2SCFrHCiEm" + }, + "width": 29, + "height": 20, "x": 0, - "y": 100 + "y": 160 }, { "id": "GW6MALzFIVR", @@ -1125,7 +1165,7 @@ "width": 29, "height": 20, "x": 29, - "y": 100 + "y": 160 }, { "id": "m4LaU9HizHi", @@ -1136,7 +1176,7 @@ "width": 29, "height": 20, "x": 0, - "y": 120 + "y": 180 }, { "id": "uyoJujQVRjE", @@ -1147,7 +1187,7 @@ "width": 29, "height": 20, "x": 29, - "y": 120 + "y": 180 }, { "id": "KI0C90Ol10x", @@ -1158,7 +1198,7 @@ "width": 29, "height": 20, "x": 0, - "y": 140 + "y": 200 }, { "id": "uYY7v977Ubm", @@ -1169,7 +1209,7 @@ "width": 29, "height": 20, "x": 29, - "y": 140 + "y": 200 }, { "id": "qUqsDmtiBLF", @@ -1180,7 +1220,7 @@ "width": 29, "height": 20, "x": 0, - "y": 160 + "y": 220 }, { "id": "mwMpIdPdu8H", @@ -1191,7 +1231,7 @@ "width": 29, "height": 20, "x": 29, - "y": 160 + "y": 220 } ], "publicAccess": "--------", @@ -1271,6 +1311,15 @@ "id": "OiCmorbkHNf", "name": "Award Number 12345", "dashboardItems": [ + { + "id": "eyYVx2rS9d6", + "type": "TEXT", + "text": "*Comparison of Target vs Actual Benefit and People Indicators* \n _(Used to compare make comparison between the target and actual of an indicator, comparison of actuals between activities that go together, used to look at the distribution (shape) of an activity (does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", + "width": 58, + "height": 6, + "x": 0, + "y": 0 + }, { "id": "CSL3EN6eJwx", "type": "REPORT_TABLE", @@ -1280,7 +1329,7 @@ "width": 29, "height": 20, "x": 0, - "y": 0 + "y": 20 }, { "id": "iYkPSnM7m4E", @@ -1291,7 +1340,7 @@ "width": 29, "height": 20, "x": 29, - "y": 0 + "y": 20 }, { "id": "yI8WlxGRfXU", @@ -1302,7 +1351,7 @@ "width": 29, "height": 20, "x": 0, - "y": 20 + "y": 40 }, { "id": "aCiqCXWYZ9P", @@ -1313,7 +1362,7 @@ "width": 29, "height": 20, "x": 29, - "y": 20 + "y": 40 }, { "id": "KEy2fuNrALy", @@ -1324,7 +1373,7 @@ "width": 29, "height": 20, "x": 0, - "y": 40 + "y": 60 }, { "id": "O0uabsxLqGS", @@ -1335,7 +1384,7 @@ "width": 29, "height": 20, "x": 29, - "y": 40 + "y": 60 }, { "id": "GCm9PNnLAgP", @@ -1346,7 +1395,7 @@ "width": 29, "height": 20, "x": 0, - "y": 60 + "y": 80 }, { "id": "W4EN8esNyGQ", @@ -1357,7 +1406,16 @@ "width": 29, "height": 20, "x": 29, - "y": 60 + "y": 80 + }, + { + "id": "qSeVeYd2sd8", + "type": "TEXT", + "text": "*Comparison of Target vs Actual Benefit and People Disaggregated by Indicator* \n _(Better to analyze trends by indicator or up to 5 indicators across time, does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", + "width": 58, + "height": 6, + "x": 0, + "y": 100 }, { "id": "OuQLaEe9G9v", @@ -1368,7 +1426,7 @@ "width": 29, "height": 20, "x": 0, - "y": 80 + "y": 120 }, { "id": "i60k7CBbyJZ", @@ -1379,7 +1437,7 @@ "width": 29, "height": 20, "x": 29, - "y": 80 + "y": 120 }, { "id": "qeWaohT6Mgt", @@ -1390,7 +1448,7 @@ "width": 29, "height": 20, "x": 0, - "y": 100 + "y": 140 }, { "id": "y84WQGCtWxT", @@ -1401,7 +1459,7 @@ "width": 29, "height": 20, "x": 29, - "y": 100 + "y": 140 }, { "id": "eCWMTNjreWb", @@ -1412,7 +1470,7 @@ "width": 29, "height": 20, "x": 0, - "y": 120 + "y": 160 }, { "id": "eUcnQVKRn34", @@ -1423,7 +1481,7 @@ "width": 29, "height": 20, "x": 29, - "y": 120 + "y": 160 } ], "publicAccess": "--------", @@ -2045,9 +2103,9 @@ ] }, { - "id": "S2kJHgM41El", + "id": "mwCW9Tw2EGo", "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Male Only", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Gender New Only", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2104,81 +2162,84 @@ ], "columns": [ { - "code": "ACTUAL_TARGET", - "id": "GIIHAr9BzzO", - "dataDimensionType": "ATTRIBUTE", + "code": "GENDER", + "id": "Kyg1O6YEGa9", + "dataDimensionType": "DISAGGREGATION", "categoryOptions": [ { - "code": "TARGET", - "id": "imyqCWQ229K" + "code": "MALE", + "id": "qk2FihwV6IL" }, { - "code": "ACTUAL", - "id": "eWeQoOlAcxV" + "code": "FEMALE", + "id": "yW2hYVS3S4u" } ] } ], - "columnDimensions": ["GIIHAr9BzzO"], + "columnDimensions": ["Kyg1O6YEGa9"], "filters": [ { "id": "ou" }, { - "id": "Kyg1O6YEGa9", + "id": "uSMHdwhxFSV", "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "KiK0FMExoqh" } ] }, { - "code": "NEW_RETURNING", - "id": "uSMHdwhxFSV", - "dataDimensionType": "DISAGGREGATION", + "id": "pe" + } + ], + "filterDimensions": ["ou", "uSMHdwhxFSV", "pe"], + "rows": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", "categoryOptions": [ { - "code": "NEW", - "id": "KiK0FMExoqh" + "code": "TARGET", + "id": "imyqCWQ229K" }, { - "code": "RETURNING", - "id": "a6AJLXQy8vO" + "code": "ACTUAL", + "id": "eWeQoOlAcxV" } ] - } - ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], - "rows": [ - { - "id": "dx" }, { - "id": "pe" + "id": "dx" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": ["GIIHAr9BzzO", "dx"], "categoryDimensions": [ { "category": { - "id": "GIIHAr9BzzO" + "id": "Kyg1O6YEGa9" }, "categoryOptions": [ { - "id": "imyqCWQ229K" + "id": "qk2FihwV6IL" }, { - "id": "eWeQoOlAcxV" + "id": "yW2hYVS3S4u" } ] }, { "category": { - "id": "Kyg1O6YEGa9" + "id": "GIIHAr9BzzO" }, "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" } ] }, @@ -2189,9 +2250,6 @@ "categoryOptions": [ { "id": "KiK0FMExoqh" - }, - { - "id": "a6AJLXQy8vO" } ] } @@ -2219,9 +2277,9 @@ ] }, { - "id": "W2SCFrHCiEm", + "id": "yGi6VuebV62", "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - People - Line/Column Chart - Male Only", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - New Only", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -2299,39 +2357,39 @@ "id": "ou" }, { - "id": "Kyg1O6YEGa9", + "id": "uSMHdwhxFSV", "categoryOptions": [ { - "id": "qk2FihwV6IL" + "id": "KiK0FMExoqh" } ] }, { - "code": "NEW_RETURNING", - "id": "uSMHdwhxFSV", + "id": "pe" + } + ], + "filterDimensions": ["ou", "uSMHdwhxFSV", "pe"], + "rows": [ + { + "code": "GENDER", + "id": "Kyg1O6YEGa9", "dataDimensionType": "DISAGGREGATION", "categoryOptions": [ { - "code": "NEW", - "id": "KiK0FMExoqh" + "code": "MALE", + "id": "qk2FihwV6IL" }, { - "code": "RETURNING", - "id": "a6AJLXQy8vO" + "code": "FEMALE", + "id": "yW2hYVS3S4u" } ] - } - ], - "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], - "rows": [ - { - "id": "dx" }, { - "id": "pe" + "id": "dx" } ], - "rowDimensions": ["dx", "pe"], + "rowDimensions": ["Kyg1O6YEGa9", "dx"], "categoryDimensions": [ { "category": { @@ -2353,6 +2411,9 @@ "categoryOptions": [ { "id": "qk2FihwV6IL" + }, + { + "id": "yW2hYVS3S4u" } ] }, @@ -2363,9 +2424,6 @@ "categoryOptions": [ { "id": "KiK0FMExoqh" - }, - { - "id": "a6AJLXQy8vO" } ] } @@ -2390,17 +2448,6 @@ "displayName": "Data Management Admin", "access": "rw------" } - ], - "series": [ - { - "dimensionItem": "imyqCWQ229K", - "axis": 0 - }, - { - "dimensionItem": "eWeQoOlAcxV", - "axis": 0, - "type": "COLUMN" - } ] }, { @@ -3016,9 +3063,9 @@ ] }, { - "id": "KasxZ8vT1n0", + "id": "S2kJHgM41El", "type": "LINE", - "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Female Only", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Male Only", "numberType": "VALUE", "legendDisplayStyle": "FILL", "rowSubTotals": true, @@ -3099,7 +3146,7 @@ "id": "Kyg1O6YEGa9", "categoryOptions": [ { - "id": "yW2hYVS3S4u" + "id": "qk2FihwV6IL" } ] }, @@ -3149,7 +3196,7 @@ }, "categoryOptions": [ { - "id": "yW2hYVS3S4u" + "id": "qk2FihwV6IL" } ] }, @@ -3189,6 +3236,365 @@ } ] }, + { + "id": "KasxZ8vT1n0", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line Chart - Female Only", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": ["GIIHAr9BzzO"], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": ["dx", "pe"], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "yW2hYVS3S4u" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ] + }, + { + "id": "W2SCFrHCiEm", + "type": "LINE", + "name": "12345en - MyProject - Target vs Actual - People - Line/Column Chart - Male Only", + "numberType": "VALUE", + "legendDisplayStyle": "FILL", + "rowSubTotals": true, + "showDimensionLabels": true, + "showData": true, + "aggregationType": "DEFAULT", + "legendDisplayStrategy": "FIXED", + "rowTotals": true, + "digitGroupSeparator": "SPACE", + "dataDimensionItems": [ + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "K6mAC5SiO29" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "ik0ICagvIjm" + } + }, + { + "dataDimensionItemType": "DATA_ELEMENT", + "dataElement": { + "id": "GQyudNlGzkI" + } + } + ], + "organisationUnits": [ + { + "id": "WGC0DJ0YSis" + } + ], + "periods": [ + { + "id": "201810" + }, + { + "id": "201811" + }, + { + "id": "201812" + }, + { + "id": "201901" + }, + { + "id": "201902" + }, + { + "id": "201903" + } + ], + "columns": [ + { + "code": "ACTUAL_TARGET", + "id": "GIIHAr9BzzO", + "dataDimensionType": "ATTRIBUTE", + "categoryOptions": [ + { + "code": "TARGET", + "id": "imyqCWQ229K" + }, + { + "code": "ACTUAL", + "id": "eWeQoOlAcxV" + } + ] + } + ], + "columnDimensions": ["GIIHAr9BzzO"], + "filters": [ + { + "id": "ou" + }, + { + "id": "Kyg1O6YEGa9", + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "code": "NEW_RETURNING", + "id": "uSMHdwhxFSV", + "dataDimensionType": "DISAGGREGATION", + "categoryOptions": [ + { + "code": "NEW", + "id": "KiK0FMExoqh" + }, + { + "code": "RETURNING", + "id": "a6AJLXQy8vO" + } + ] + } + ], + "filterDimensions": ["ou", "Kyg1O6YEGa9", "uSMHdwhxFSV"], + "rows": [ + { + "id": "dx" + }, + { + "id": "pe" + } + ], + "rowDimensions": ["dx", "pe"], + "categoryDimensions": [ + { + "category": { + "id": "GIIHAr9BzzO" + }, + "categoryOptions": [ + { + "id": "imyqCWQ229K" + }, + { + "id": "eWeQoOlAcxV" + } + ] + }, + { + "category": { + "id": "Kyg1O6YEGa9" + }, + "categoryOptions": [ + { + "id": "qk2FihwV6IL" + } + ] + }, + { + "category": { + "id": "uSMHdwhxFSV" + }, + "categoryOptions": [ + { + "id": "KiK0FMExoqh" + }, + { + "id": "a6AJLXQy8vO" + } + ] + } + ], + "publicAccess": "--------", + "externalAccess": false, + "userAccesses": [ + { + "id": "M5zQapPyTZI", + "displayName": "admin admin", + "access": "rw------" + } + ], + "userGroupAccesses": [ + { + "id": "ywuI2WspUUG", + "displayName": "System Admin", + "access": "rw------" + }, + { + "id": "mKKNXzeIAJs", + "displayName": "Data Management Admin", + "access": "rw------" + } + ], + "series": [ + { + "dimensionItem": "imyqCWQ229K", + "axis": 0 + }, + { + "dimensionItem": "eWeQoOlAcxV", + "axis": 0, + "type": "COLUMN" + } + ] + }, { "id": "OuKm5zK7l53", "type": "LINE", From 0b9d8c8bcf467a5d16300ec67e3866a818a1dd8d Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Mon, 4 May 2026 08:43:27 -0500 Subject: [PATCH 31/49] add unique id for text dashboard items --- i18n/en.pot | 4 +-- src/models/ProjectDashboard.ts | 27 ++++++++++++++++--- .../__tests__/data/project-db-metadata.json | 19 ++++++++++--- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/i18n/en.pot b/i18n/en.pot index e6215582..d846e938 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -5,8 +5,8 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1)\n" -"POT-Creation-Date: 2026-05-01T19:09:52.637Z\n" -"PO-Revision-Date: 2026-05-01T19:09:52.637Z\n" +"POT-Creation-Date: 2026-05-04T13:11:15.065Z\n" +"PO-Revision-Date: 2026-05-04T13:11:15.065Z\n" msgid "Validating Project" msgstr "" diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index a68ad05a..dfb0fb0c 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -47,6 +47,7 @@ export default class ProjectDashboard { this.dataElements = this.projectsListDashboard.dataElements; const projectMerDataElements = _(project?.dataElementsMER.getAllSelected()) + .sortBy(de => de.code) .uniqBy(de => de.id) .value(); @@ -126,7 +127,7 @@ export default class ProjectDashboard { "*Comparison of Target vs Actual Benefit and People Indicators* \n _(Used to compare make comparison between the target and actual of an indicator, comparison of actuals between activities that go together, used to look at the distribution (shape) of an activity (does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_"; const firstTextItem: PartialModel = { - id: getUid("first", "text-project-dashboard"), + id: getUid("first-text-project-dashboard", this.projectsListDashboard.id), type: "TEXT", text: i18n.t(title), width: toItemWidth(100), @@ -136,7 +137,7 @@ export default class ProjectDashboard { "*Comparison of Target vs Actual Benefit and People Disaggregated by Indicator* \n _(Better to analyze trends by indicator or up to 5 indicators across time, does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_"; const eighthTextItem: PartialModel = { - id: getUid("eighth", "text-project-dashboard"), + id: getUid("eighth-text-project-dashboard", this.projectsListDashboard.id), type: "TEXT", text: i18n.t(eigthTitle), width: toItemWidth(100), @@ -402,12 +403,16 @@ export default class ProjectDashboard { targetVsActualPeopleLineChartGenderNewOnly(): MaybeD2Visualization { const { config, dataElements } = this; + const sortedDe = _(dataElements.people) + .sortBy(de => de.code) + .value(); + return this.getD2VisualizationFromDefinition({ type: "chart", chartType: "LINE", key: "chart-target-actual-people-line-gender-new", name: i18n.t("Target vs Actual - People - Line Chart - Gender New Only"), - items: dataElementItems(dataElements.people), + items: dataElementItems(sortedDe), filters: [dimensions.orgUnit, this.categoryOnlyNew, dimensions.period], columns: [config.categories.gender], rows: [config.categories.targetActual, dimensions.data], @@ -417,15 +422,29 @@ export default class ProjectDashboard { targetVsActualPeopleLineChartNewOnly(): MaybeD2Visualization { const { config, dataElements } = this; + const sortedDe = _(dataElements.people) + .sortBy(de => de.code) + .value(); + return this.getD2VisualizationFromDefinition({ type: "chart", chartType: "LINE", key: "chart-target-actual-people-line-new-only", name: i18n.t("Target vs Actual - People - Line Chart - New Only"), - items: dataElementItems(dataElements.people), + items: dataElementItems(sortedDe), filters: [dimensions.orgUnit, this.categoryOnlyNew, dimensions.period], columns: [config.categories.targetActual], rows: [config.categories.gender, dimensions.data], + extra: { + series: [ + { dimensionItem: config.categoryOptions.target.id, axis: 0 }, + { + dimensionItem: config.categoryOptions.actual.id, + axis: 0, + type: "COLUMN", + }, + ], + }, }); } diff --git a/src/models/__tests__/data/project-db-metadata.json b/src/models/__tests__/data/project-db-metadata.json index 35e1be8b..2070f7da 100644 --- a/src/models/__tests__/data/project-db-metadata.json +++ b/src/models/__tests__/data/project-db-metadata.json @@ -996,7 +996,7 @@ "name": "12345en - MyProject", "dashboardItems": [ { - "id": "eyYVx2rS9d6", + "id": "eW2hY45BmwK", "type": "TEXT", "text": "*Comparison of Target vs Actual Benefit and People Indicators* \n _(Used to compare make comparison between the target and actual of an indicator, comparison of actuals between activities that go together, used to look at the distribution (shape) of an activity (does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", "width": 58, @@ -1093,7 +1093,7 @@ "y": 80 }, { - "id": "qSeVeYd2sd8", + "id": "qmsjS4Pol2D", "type": "TEXT", "text": "*Comparison of Target vs Actual Benefit and People Disaggregated by Indicator* \n _(Better to analyze trends by indicator or up to 5 indicators across time, does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", "width": 58, @@ -1312,7 +1312,7 @@ "name": "Award Number 12345", "dashboardItems": [ { - "id": "eyYVx2rS9d6", + "id": "qmaYzFsnHb0", "type": "TEXT", "text": "*Comparison of Target vs Actual Benefit and People Indicators* \n _(Used to compare make comparison between the target and actual of an indicator, comparison of actuals between activities that go together, used to look at the distribution (shape) of an activity (does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", "width": 58, @@ -1409,7 +1409,7 @@ "y": 80 }, { - "id": "qSeVeYd2sd8", + "id": "ucwTFh4n6xh", "type": "TEXT", "text": "*Comparison of Target vs Actual Benefit and People Disaggregated by Indicator* \n _(Better to analyze trends by indicator or up to 5 indicators across time, does the actual shape match the target shape? If not, should there be a discussion? Is this ok?)_", "width": 58, @@ -2448,6 +2448,17 @@ "displayName": "Data Management Admin", "access": "rw------" } + ], + "series": [ + { + "dimensionItem": "imyqCWQ229K", + "axis": 0 + }, + { + "dimensionItem": "eWeQoOlAcxV", + "axis": 0, + "type": "COLUMN" + } ] }, { From d4a63f5ffe0c3ca8c2d2da409b481ec8477438db Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Mon, 4 May 2026 10:54:14 -0500 Subject: [PATCH 32/49] include spacer if visualization is not present --- src/models/Dashboard.ts | 3 ++- src/models/ProjectDashboard.ts | 37 +++++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/models/Dashboard.ts b/src/models/Dashboard.ts index e233a0b7..87974ea5 100644 --- a/src/models/Dashboard.ts +++ b/src/models/Dashboard.ts @@ -178,7 +178,8 @@ export function positionItems(items: DashboardItem[], options: PositionItemsOpti const isText = item.type === "TEXT"; const width = Math.min(item.width || defaultWidth, maxWidth); const itemPos = pos.x + width > maxWidth ? { x: 0, y: pos.y + defaultHeight } : pos; - const newItem = { ...item, width, height: isText ? 6 : defaultHeight, ...itemPos }; + const height = item.height ?? (isText ? 6 : defaultHeight); + const newItem = { ...item, width, height, ...itemPos }; const newPos = { x: itemPos.x + newItem.width, y: itemPos.y }; return { pos: newPos, outputItems: [...outputItems, newItem] }; }, diff --git a/src/models/ProjectDashboard.ts b/src/models/ProjectDashboard.ts index dfb0fb0c..aff3051f 100644 --- a/src/models/ProjectDashboard.ts +++ b/src/models/ProjectDashboard.ts @@ -103,20 +103,33 @@ export default class ProjectDashboard { if (!_.isNil(minimumOrgUnits) && projectsListDashboard.orgUnits.length < minimumOrgUnits) return { dashboards: [], visualizations: [] }; - const visualizations = + const rawVisualizations = this.dashboardType === "project" ? this.getProjectVisualizations() : this.getAwardNumberVisualizations(); - const items: Array> = _(visualizations) - .map(visualization => - visualization.type === "PIVOT_TABLE" - ? getReportTableItem(visualization) - : getChartDashboardItem(visualization) - ) + let spacerIndex = 0; + const items: Array> = _(rawVisualizations) + .map(visualization => { + if (visualization) { + return visualization.type === "PIVOT_TABLE" + ? getReportTableItem(visualization) + : getChartDashboardItem(visualization); + } + const spacer: PartialModel = { + id: getUid(`spacer-${spacerIndex}`, projectsListDashboard.id), + type: "TEXT", + text: "SPACER_ITEM_FOR_DASHBOARD_LAYOUT_CONVENIENCE", + height: 20, + }; + spacerIndex++; + return spacer; + }) .compact() .value(); + const visualizations = _.compact(rawVisualizations); + const positionItemsOptions: PositionItemsOptions = { maxWidth: toItemWidth(100), defaultWidth: toItemWidth(50), @@ -160,19 +173,19 @@ export default class ProjectDashboard { return { dashboards: [dashboard], visualizations }; } - getProjectVisualizations(): PartialPersistedModel[] { + getProjectVisualizations(): MaybeD2Visualization[] { const targetVsActualBenefitsTable_ = this.targetVsActualBenefitsTable(); const targetVsActualPeopleTable_ = this.targetVsActualPeopleTable(); const achievedBenefitsToDateTable_ = this.achievedBenefitsTable({ toDate: true }); const achievedPeopleToDateTable_ = this.achievedPeopleTable(); - const charts: Array> = _.compact([ + const charts: MaybeD2Visualization[] = [ this.achievedBenefitChart(), this.achievedPeopleChart(), this.genderChart(), this.costBenefitTable(), - ]); + ]; - return _.compact([ + return [ this.merTargetVsActualBenefitsChart(), this.merTargetVsActualPeopleChart(), targetVsActualBenefitsTable_, @@ -190,7 +203,7 @@ export default class ProjectDashboard { achievedBenefitsToDateTable_, achievedPeopleToDateTable_, ...charts, - ]); + ]; } getAwardNumberVisualizations(): PartialPersistedModel[] { From 2b9d4fc8c2381de1966a631ceb048a98221f93b0 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Tue, 12 May 2026 06:58:07 -0500 Subject: [PATCH 33/49] added script to remove paired indicators from projects --- src/models/Project.ts | 6 +- src/models/ProjectDb.ts | 16 +- ...move-paired-data-elements-from-projects.ts | 287 ++++++++++++++++++ 3 files changed, 300 insertions(+), 9 deletions(-) create mode 100644 src/scripts/remove-paired-data-elements-from-projects.ts diff --git a/src/models/Project.ts b/src/models/Project.ts index 7ca5043d..943e4c9e 100644 --- a/src/models/Project.ts +++ b/src/models/Project.ts @@ -8,7 +8,7 @@ import { TableSorting } from "@eyeseetea/d2-ui-components"; import i18n from "../locales"; import DataElementsSet, { PeopleOrBenefit, DataElement, SelectionInfo } from "./dataElementsSet"; -import ProjectDb from "./ProjectDb"; +import ProjectDb, { SaveOptions } from "./ProjectDb"; import { toISOString, getMonthsRange } from "../utils/date"; import ProjectDownload from "./ProjectDownload"; import ProjectList, { ProjectForList, FiltersForList } from "./ProjectsList"; @@ -523,8 +523,8 @@ class Project { return new ProjectDownload(this).generate(); } - save() { - return new ProjectDb(this).save(); + save(options: SaveOptions = {}) { + return new ProjectDb(this).save(options); } saveFiles() { diff --git a/src/models/ProjectDb.ts b/src/models/ProjectDb.ts index d26b054e..49d3f873 100644 --- a/src/models/ProjectDb.ts +++ b/src/models/ProjectDb.ts @@ -67,8 +67,8 @@ export default class ProjectDb { this.config = project.config; } - async save() { - return await this.saveMetadata(); + async save(options: SaveOptions = {}) { + return await this.saveMetadata(options); } async saveFiles() { @@ -227,13 +227,15 @@ export default class ProjectDb { return { id: orgUnit.id, name: orgUnit.name, metadata, data, dataValues }; } - async getMetadata() { + async getMetadata(options: SaveOptions = {}) { const { project, api, config } = this; const { startDate, endDate } = project; const country = project.parentOrgUnit; - const validationErrors = _.flatten(_.values(await project.validate())); + const validationErrors = options.skipValidation + ? [] + : _.flatten(_.values(await project.validate())); if (!_.isEmpty(validationErrors)) { throw new Error("Validation errors:\n" + validationErrors.join("\n")); } else if (!startDate || !endDate || !project.parentOrgUnit) { @@ -383,8 +385,8 @@ export default class ProjectDb { ); } - async saveMetadata() { - const { payload, orgUnit, project: projectUpdated } = await this.getMetadata(); + async saveMetadata(options: SaveOptions = {}) { + const { payload, orgUnit, project: projectUpdated } = await this.getMetadata(options); await this.saveDocuments(); @@ -1249,3 +1251,5 @@ export const dataSetFields = { userAccesses: { id: true, displayName: true, access: true }, userGroupAccesses: { id: true, displayName: true, access: true }, } as const; + +export type SaveOptions = { skipValidation?: boolean }; diff --git a/src/scripts/remove-paired-data-elements-from-projects.ts b/src/scripts/remove-paired-data-elements-from-projects.ts new file mode 100644 index 00000000..7629ab9c --- /dev/null +++ b/src/scripts/remove-paired-data-elements-from-projects.ts @@ -0,0 +1,287 @@ +import _ from "lodash"; +import fs from "fs"; +import parse from "parse-typed-args"; +import { promiseMap } from "../migrations/utils"; +import { Config } from "../models/Config"; +import DataElementsSet from "../models/dataElementsSet"; +import Project from "../models/Project"; +import ProjectDashboardSave from "../models/ProjectDashboardSave"; +import ProjectDb from "../models/ProjectDb"; +import ProjectsList from "../models/ProjectsList"; +import { D2Api, Id } from "../types/d2-api"; +import { App, getApp } from "./common"; + +const MAIN_CODES = ["B060300", "B060500", "B061000", "B130200", "B130400", "B130600"] as const; + +interface Opts { + url?: string; + persist?: boolean; + "project-ids"?: string; +} + +main().catch(err => { + console.error("ERROR", err); + process.exit(1); +}); + +async function main() { + const parser = parse({ + opts: { + url: {}, + persist: { switch: true }, + "project-ids": {}, + }, + }); + const { opts } = parser(process.argv) as { opts: Opts }; + + const usage = + "remove-paired-data-elements-from-projects --url=DHIS2_URL [--persist] [--project-ids=ID1,ID2,...]"; + if (!opts.url) { + console.error(usage); + process.exit(1); + } + + const app = await getApp({ baseUrl: opts.url }); + const persist = Boolean(opts.persist); + const filterIds = parseProjectIds(opts["project-ids"]); + + await run(app, { persist, filterIds }); +} + +function parseProjectIds(s: string | undefined): Set | null { + if (!s) return null; + const ids = s + .split(",") + .map(x => x.trim()) + .filter(Boolean); + return new Set(ids); +} + +async function run(app: App, options: { persist: boolean; filterIds: Set | null }) { + const { api, config } = app; + const { persist, filterIds } = options; + + const pairByMainId = buildPairByMainId(config); + if (_.isEmpty(pairByMainId)) { + console.error(`No paired DE mapping resolved for any main code: ${MAIN_CODES.join(", ")}`); + return; + } + + const mode = persist ? "PERSIST" : "DRY-RUN"; + console.info(`[${mode}] Pairs to look for:`); + console.info(describePairs(pairByMainId, config)); + + const allProjectIds = await getProjectIds(api, config); + const projectIds = filterIds ? allProjectIds.filter(id => filterIds.has(id)) : allProjectIds; + + if (filterIds && projectIds.length < filterIds.size) { + const missing = Array.from(filterIds).filter(id => !allProjectIds.includes(id)); + console.error(`WARN: ${missing.length} project id(s) not found: ${missing.join(", ")}`); + } + + console.info(`Projects to scan: ${projectIds.length}`); + + let changedCount = 0; + let totalRemoved = 0; + + await promiseMap(projectIds, async projectId => { + const project = await Project.get(api, config, projectId); + const { project: updatedProject, removed } = removePairedFromProject(project, pairByMainId); + const removedTotal = sumRemoved(removed); + if (removedTotal === 0) return; + + changedCount += 1; + totalRemoved += removedTotal; + + const label = `[${project.parentOrgUnit?.displayName}] ${project.name} (${project.id})`; + console.info( + `- ${label}: ${removedTotal} paired DE(s) ${persist ? "removed" : "to remove"}` + ); + logRemovedDetail(removed, config); + + if (persist) { + await updatedProject.save({ skipValidation: true }); + await new ProjectDashboardSave(updatedProject).execute(); + } else { + const json = await new ProjectDb(updatedProject).toJSON(); + fs.writeFileSync(`project-${project.id}.json`, JSON.stringify(json, null, 2), "utf-8"); + } + }); + + console.info( + `Done. ${changedCount} project(s) ${persist ? "updated" : "would be updated"}, ` + + `${totalRemoved} paired DE(s) ${persist ? "removed" : "would be removed"}.` + ); + if (!persist) { + console.info("Re-run with --persist to apply the changes."); + } +} + +async function getProjectIds(api: D2Api, config: Config): Promise { + const { objects } = await new ProjectsList(api, config).get( + {}, + { field: "id", order: "asc" }, + { page: 1, pageSize: 100000 } + ); + return _(objects) + .orderBy([p => p.parent.displayName, p => p.displayName]) + .map(p => p.id) + .value(); +} + +function buildPairByMainId(config: Config): Record { + const dataElementsByCode = _.keyBy(config.dataElements, de => de.code); + const pairedAttrCode = config.attributes.pairedDataElement.code; + + const result: Record = {}; + for (const mainCode of MAIN_CODES) { + const mainDe = dataElementsByCode[mainCode]; + if (!mainDe) { + console.error(`WARN: main code ${mainCode} not found in metadata`); + continue; + } + const value = getAttributeValue(mainDe, pairedAttrCode); + if (!value) { + console.error(`WARN: ${mainCode} has no ${pairedAttrCode} value`); + continue; + } + const pairedCodes = value + .split(",") + .map(s => s.trim()) + .filter(Boolean); + if (pairedCodes.length !== 1) { + console.error( + `WARN: ${mainCode} has unexpected ${pairedAttrCode} value: "${value}" — taking all` + ); + } + for (const pairedCode of pairedCodes) { + const pairedDe = dataElementsByCode[pairedCode]; + if (!pairedDe) { + console.error( + `WARN: paired code ${pairedCode} (for main ${mainCode}) not found in metadata` + ); + continue; + } + result[mainDe.id] = pairedDe.id; + } + } + return result; +} + +function getAttributeValue( + dataElement: { + attributeValues: Array<{ attribute: { code: string }; value: string }>; + }, + attributeCode: string +): string | null { + const av = dataElement.attributeValues.find(av => av.attribute.code === attributeCode); + return av?.value || null; +} + +function describePairs(pairByMainId: Record, config: Config): string { + const byId = _.keyBy(config.dataElements, de => de.id); + return Object.entries(pairByMainId) + .map(([mainId, pairedId]) => { + const mainCode = byId[mainId]?.code || mainId; + const pairedCode = byId[pairedId]?.code || pairedId; + return ` ${mainCode} (${mainId}) → ${pairedCode} (${pairedId})`; + }) + .join("\n"); +} + +type RemovedBySector = Record; + +interface RemovedSummary { + selection: RemovedBySector; + mer: RemovedBySector; + unique: RemovedBySector; +} + +function removePairedFromProject( + project: Project, + pairByMainId: Record +): { project: Project; removed: RemovedSummary } { + const { sectors, dataElementsSelection, dataElementsMER, uniqueIndicators } = project.data; + + const selection = computeFilteredSelection(dataElementsSelection, sectors, pairByMainId); + const mer = computeFilteredSelection(dataElementsMER, sectors, pairByMainId); + const unique = computeFilteredSelection(uniqueIndicators, sectors, pairByMainId); + + // Rebuild dataElementsSelection with groupPaired: false so that the + // includePaired: true expansion in Project.getSelectedDataElements no longer + // re-inflates the paired DE we just removed from `selected`. + const rebuiltSelection = DataElementsSet.build(project.config, { + groupPaired: false, + }).updateSelected(selection.next); + + const updated = project.setObj({ + dataElementsSelection: rebuiltSelection, + dataElementsMER: dataElementsMER.updateSelected(mer.next), + uniqueIndicators: uniqueIndicators.updateSelected(unique.next), + }); + + return { + project: updated, + removed: { + selection: selection.removed, + mer: mer.removed, + unique: unique.removed, + }, + }; +} + +function computeFilteredSelection( + set: DataElementsSet, + sectors: Array<{ id: Id }>, + pairByMainId: Record +): { next: Record; removed: RemovedBySector } { + const next: Record = {}; + const removed: RemovedBySector = {}; + + for (const sector of sectors) { + // Read selected IDs directly from set.data.selected — with groupPaired: true, + // set.get(...) hides paired DEs from the returned list (they are pruned out of + // dataElementsBySector), so we'd miss them and never detect them as removable. + const selectedIds = set.data.selected[sector.id] || []; + const idSet = new Set(selectedIds); + + const toRemove = new Set(); + for (const [mainId, pairedId] of Object.entries(pairByMainId)) { + if (idSet.has(mainId) && idSet.has(pairedId)) { + toRemove.add(pairedId); + } + } + + next[sector.id] = selectedIds.filter(id => !toRemove.has(id)); + if (toRemove.size > 0) removed[sector.id] = Array.from(toRemove); + } + + return { next, removed }; +} + +function sumRemoved(removed: RemovedSummary): number { + const all = [ + ..._.values(removed.selection), + ..._.values(removed.mer), + ..._.values(removed.unique), + ]; + return _.sumBy(all, arr => arr.length); +} + +function logRemovedDetail(removed: RemovedSummary, config: Config) { + const byId = _.keyBy(config.dataElements, de => de.id); + const code = (id: Id) => byId[id]?.code || id; + + const sections: Array<{ name: string; data: RemovedBySector }> = [ + { name: "selection", data: removed.selection }, + { name: "MER", data: removed.mer }, + { name: "uniqueIndicators", data: removed.unique }, + ]; + + for (const { name, data } of sections) { + for (const [sectorId, ids] of Object.entries(data)) { + if (ids.length === 0) continue; + console.info(` [${name}] sector=${sectorId} paired=${ids.map(code).join(",")}`); + } + } +} From 1c087f6ee12a07e03dea4d98ec827b5da7504e3d Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Mon, 18 May 2026 21:24:28 -0500 Subject: [PATCH 34/49] script to remove paired sub indicators --- src/models/ProjectDb.ts | 4 +- ...ove-paired-sub-indicators-from-projects.ts | 378 ++++++++++++++++++ 2 files changed, 380 insertions(+), 2 deletions(-) create mode 100644 src/scripts/remove-paired-sub-indicators-from-projects.ts diff --git a/src/models/ProjectDb.ts b/src/models/ProjectDb.ts index 49d3f873..6ce8ad39 100644 --- a/src/models/ProjectDb.ts +++ b/src/models/ProjectDb.ts @@ -190,8 +190,8 @@ export default class ProjectDb { throwResponseError(dataValueRes, "Error importing data values"); } - async toJSON(): Promise { - const { payload: metadata, orgUnit, project } = await this.getMetadata(); + async toJSON(options: SaveOptions = {}): Promise { + const { payload: metadata, orgUnit, project } = await this.getMetadata(options); const dataStore = getDataStore(this.api); const countryId = project.parentOrgUnit?.id; diff --git a/src/scripts/remove-paired-sub-indicators-from-projects.ts b/src/scripts/remove-paired-sub-indicators-from-projects.ts new file mode 100644 index 00000000..17bfb02f --- /dev/null +++ b/src/scripts/remove-paired-sub-indicators-from-projects.ts @@ -0,0 +1,378 @@ +import _ from "lodash"; +import fs from "fs"; +import parse from "parse-typed-args"; +import { promiseMap } from "../migrations/utils"; +import { Config } from "../models/Config"; +import DataElementsSet, { getSubs } from "../models/dataElementsSet"; +import Project from "../models/Project"; +import ProjectDashboardSave from "../models/ProjectDashboardSave"; +import ProjectDb from "../models/ProjectDb"; +import ProjectsList from "../models/ProjectsList"; +import { D2Api, Id } from "../types/d2-api"; +import { App, getApp } from "./common"; + +const MAIN_CODES = ["B060300", "B060500", "B061000", "B130200", "B130400", "B130600"] as const; + +interface Opts { + url?: string; + persist?: boolean; + "project-ids"?: string; +} + +main().catch(err => { + console.error("ERROR", err); + process.exit(1); +}); + +async function main() { + const parser = parse({ + opts: { + url: {}, + persist: { switch: true }, + "project-ids": {}, + }, + }); + const { opts } = parser(process.argv) as { opts: Opts }; + + const usage = + "remove-paired-sub-indicators-from-projects --url=DHIS2_URL [--persist] [--project-ids=ID1,ID2,...]"; + if (!opts.url) { + console.error(usage); + process.exit(1); + } + + const app = await getApp({ baseUrl: opts.url }); + const persist = Boolean(opts.persist); + const filterIds = parseProjectIds(opts["project-ids"]); + + await run(app, { persist, filterIds }); +} + +function parseProjectIds(s: string | undefined): Set | null { + if (!s) return null; + const ids = s + .split(",") + .map(x => x.trim()) + .filter(Boolean); + return new Set(ids); +} + +interface PairedInfo { + mainId: Id; + mainCode: string; + pairedId: Id; + pairedCode: string; + subs: Array<{ id: Id; code: string; name: string }>; +} + +async function run(app: App, options: { persist: boolean; filterIds: Set | null }) { + const { api, config } = app; + const { persist, filterIds } = options; + + const pairedInfos = buildPairedInfos(config); + if (_.isEmpty(pairedInfos)) { + console.error(`No paired DE mapping resolved for any main code: ${MAIN_CODES.join(", ")}`); + return; + } + + const subIdsToRemove = new Set( + _(pairedInfos) + .flatMap(p => p.subs.map(s => s.id)) + .value() + ); + + const mode = persist ? "PERSIST" : "DRY-RUN"; + console.info(`[${mode}] Sub-indicators to remove per paired:`); + console.info(describeSubsTree(pairedInfos)); + console.info( + `Total: ${subIdsToRemove.size} sub-indicators (de ${pairedInfos.length} paired DE(s))` + ); + + const allProjectIds = await getProjectIds(api, config); + const projectIds = filterIds ? allProjectIds.filter(id => filterIds.has(id)) : allProjectIds; + + if (filterIds && projectIds.length < filterIds.size) { + const missing = Array.from(filterIds).filter(id => !allProjectIds.includes(id)); + console.error(`WARN: ${missing.length} project id(s) not found: ${missing.join(", ")}`); + } + + console.info(`Projects to scan: ${projectIds.length}`); + + let changedCount = 0; + let totalRemoved = 0; + + await promiseMap(projectIds, async projectId => { + const project = await Project.get(api, config, projectId); + const { project: updatedProject, removed } = removeSubsFromProject(project, subIdsToRemove); + const removedTotal = sumRemoved(removed); + if (removedTotal === 0) { + console.info( + `- [${project.parentOrgUnit?.displayName}] ${project.name} (${project.id}): no sub indicators to remove` + ); + return; + } + + changedCount += 1; + totalRemoved += removedTotal; + + const label = `[${project.parentOrgUnit?.displayName}] ${project.name} (${project.id})`; + console.info(`- ${label}: ${removedTotal} sub(s) ${persist ? "removed" : "to remove"}`); + logRemovedDetail(removed, config); + + if (persist) { + await updatedProject.save({ skipValidation: true }); + await new ProjectDashboardSave(updatedProject).execute(); + } else { + const json = await new ProjectDb(updatedProject).toJSON({ skipValidation: true }); + fs.writeFileSync(`project-${project.id}.json`, JSON.stringify(json, null, 2), "utf-8"); + } + }); + + console.info( + `Done. ${changedCount} project(s) ${persist ? "updated" : "would be updated"}, ` + + `${totalRemoved} sub(s) ${persist ? "removed" : "would be removed"}.` + ); + + await removeSubsFromDataElementGroups(api, config, subIdsToRemove, persist); + + if (!persist) { + console.info("Re-run with --persist to apply the changes."); + } +} + +async function removeSubsFromDataElementGroups( + api: D2Api, + config: Config, + subIdsToRemove: Set, + persist: boolean +): Promise { + const groupCodes = [ + config.base.dataElementGroups.sub, + config.base.dataElementGroups.reportableSub, + ]; + + console.info(`\nUpdating DataElementGroups: ${groupCodes.join(", ")}`); + + const { dataElementGroups } = await api.metadata + .get({ + dataElementGroups: { + fields: { $owner: true }, + filter: { code: { in: groupCodes } }, + }, + }) + .getData(); + + const missing = groupCodes.filter(code => !dataElementGroups.some(g => g.code === code)); + if (missing.length > 0) { + console.error(`WARN: DataElementGroup(s) not found by code: ${missing.join(", ")}`); + } + + const groupsToUpdate = dataElementGroups + .map(group => { + const before = group.dataElements.length; + const filtered = group.dataElements.filter(de => !subIdsToRemove.has(de.id)); + const removedCount = before - filtered.length; + return { group, filtered, before, removedCount }; + }) + .filter(x => x.removedCount > 0); + + if (groupsToUpdate.length === 0) { + console.info("No DataElementGroup changes needed."); + return; + } + + for (const { group, before, removedCount } of groupsToUpdate) { + console.info( + `- ${group.code} (${group.id}): ${before} → ${before - removedCount} members ` + + `(${removedCount} ${persist ? "removed" : "to remove"})` + ); + } + + if (!persist) return; + + const payload = groupsToUpdate.map(({ group, filtered }) => ({ + ...group, + dataElements: filtered.map(de => ({ id: de.id })), + })); + + const response = await api.metadata + .post({ dataElementGroups: payload }, { importMode: "COMMIT" }) + .getData(); + + console.info(`DataElementGroups update: status=${response.status}`); + if (response.status !== "OK") { + console.error("ERROR posting dataElementGroups:", JSON.stringify(response, null, 2)); + } +} + +async function getProjectIds(api: D2Api, config: Config): Promise { + const { objects } = await new ProjectsList(api, config).get( + {}, + { field: "id", order: "asc" }, + { page: 1, pageSize: 100000 } + ); + return _(objects) + .orderBy([p => p.parent.displayName, p => p.displayName]) + .map(p => p.id) + .value(); +} + +function buildPairedInfos(config: Config): PairedInfo[] { + const dataElementsByCode = _.keyBy(config.dataElements, de => de.code); + const pairedAttrCode = config.attributes.pairedDataElement.code; + + const result: PairedInfo[] = []; + for (const mainCode of MAIN_CODES) { + const mainDe = dataElementsByCode[mainCode]; + if (!mainDe) { + console.error(`WARN: main code ${mainCode} not found in metadata`); + continue; + } + const value = getAttributeValue(mainDe, pairedAttrCode); + if (!value) { + console.error(`WARN: ${mainCode} has no ${pairedAttrCode} value`); + continue; + } + const pairedCodes = value + .split(",") + .map(s => s.trim()) + .filter(Boolean); + if (pairedCodes.length !== 1) { + console.error( + `WARN: ${mainCode} has unexpected ${pairedAttrCode} value: "${value}" — taking all` + ); + } + for (const pairedCode of pairedCodes) { + const pairedDe = dataElementsByCode[pairedCode]; + if (!pairedDe) { + console.error( + `WARN: paired code ${pairedCode} (for main ${mainCode}) not found in metadata` + ); + continue; + } + const subs = getSubs(config, pairedDe.id); + const subInfos = _(subs) + .map(s => ({ id: s.id, code: s.code, name: s.name })) + .orderBy(s => s.code) + .value(); + result.push({ + mainId: mainDe.id, + mainCode: mainDe.code, + pairedId: pairedDe.id, + pairedCode: pairedDe.code, + subs: subInfos, + }); + } + } + return result; +} + +function getAttributeValue( + dataElement: { + attributeValues: Array<{ attribute: { code: string }; value: string }>; + }, + attributeCode: string +): string | null { + const av = dataElement.attributeValues.find(av => av.attribute.code === attributeCode); + return av?.value || null; +} + +function describeSubsTree(pairedInfos: PairedInfo[]): string { + return pairedInfos + .map(p => { + const header = ` ${p.mainCode} → ${p.pairedCode} (${p.pairedId})`; + if (p.subs.length === 0) return `${header}\n (no sub indicators found)`; + const subLines = p.subs.map(s => ` - ${s.code} ${s.name} (${s.id})`).join("\n"); + return `${header}\n${subLines}`; + }) + .join("\n"); +} + +type RemovedBySector = Record; + +interface RemovedSummary { + selection: RemovedBySector; + mer: RemovedBySector; + unique: RemovedBySector; +} + +function removeSubsFromProject( + project: Project, + subIdsToRemove: Set +): { project: Project; removed: RemovedSummary } { + const { sectors, dataElementsSelection, dataElementsMER, uniqueIndicators } = project.data; + + const selection = computeFilteredSelection(dataElementsSelection, sectors, subIdsToRemove); + const mer = computeFilteredSelection(dataElementsMER, sectors, subIdsToRemove); + const unique = computeFilteredSelection(uniqueIndicators, sectors, subIdsToRemove); + + const updated = project.setObj({ + dataElementsSelection: dataElementsSelection.updateSelected(selection.next), + dataElementsMER: dataElementsMER.updateSelected(mer.next), + uniqueIndicators: uniqueIndicators.updateSelected(unique.next), + }); + + return { + project: updated, + removed: { + selection: selection.removed, + mer: mer.removed, + unique: unique.removed, + }, + }; +} + +function computeFilteredSelection( + set: DataElementsSet, + sectors: Array<{ id: Id }>, + subIdsToRemove: Set +): { next: Record; removed: RemovedBySector } { + const next: Record = {}; + const removed: RemovedBySector = {}; + + for (const sector of sectors) { + const selectedIds = set.data.selected[sector.id] || []; + + const toRemove: Id[] = []; + const kept: Id[] = []; + for (const id of selectedIds) { + if (subIdsToRemove.has(id)) { + toRemove.push(id); + } else { + kept.push(id); + } + } + + next[sector.id] = kept; + if (toRemove.length > 0) removed[sector.id] = toRemove; + } + + return { next, removed }; +} + +function sumRemoved(removed: RemovedSummary): number { + const all = [ + ..._.values(removed.selection), + ..._.values(removed.mer), + ..._.values(removed.unique), + ]; + return _.sumBy(all, arr => arr.length); +} + +function logRemovedDetail(removed: RemovedSummary, config: Config) { + const byId = _.keyBy(config.dataElements, de => de.id); + const code = (id: Id) => byId[id]?.code || id; + + const sections: Array<{ name: string; data: RemovedBySector }> = [ + { name: "selection", data: removed.selection }, + { name: "MER", data: removed.mer }, + { name: "uniqueIndicators", data: removed.unique }, + ]; + + for (const { name, data } of sections) { + for (const [sectorId, ids] of Object.entries(data)) { + if (ids.length === 0) continue; + console.info(` [${name}] sector=${sectorId} subs=${ids.map(code).join(",")}`); + } + } +} From f0bd1f59cf17148db0a83c8ab1baa45ffa75f499 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Tue, 19 May 2026 20:33:02 -0500 Subject: [PATCH 35/49] remove sub indicators from dashboards, improve logs to show updated projects --- ...ove-paired-sub-indicators-from-projects.ts | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/src/scripts/remove-paired-sub-indicators-from-projects.ts b/src/scripts/remove-paired-sub-indicators-from-projects.ts index 17bfb02f..954155bb 100644 --- a/src/scripts/remove-paired-sub-indicators-from-projects.ts +++ b/src/scripts/remove-paired-sub-indicators-from-projects.ts @@ -100,6 +100,7 @@ async function run(app: App, options: { persist: boolean; filterIds: Set | n let changedCount = 0; let totalRemoved = 0; + const updatedProjects: Array<{ id: Id; name: string }> = []; await promiseMap(projectIds, async projectId => { const project = await Project.get(api, config, projectId); @@ -122,6 +123,7 @@ async function run(app: App, options: { persist: boolean; filterIds: Set | n if (persist) { await updatedProject.save({ skipValidation: true }); await new ProjectDashboardSave(updatedProject).execute(); + updatedProjects.push({ id: project.id, name: project.name }); } else { const json = await new ProjectDb(updatedProject).toJSON({ skipValidation: true }); fs.writeFileSync(`project-${project.id}.json`, JSON.stringify(json, null, 2), "utf-8"); @@ -135,6 +137,13 @@ async function run(app: App, options: { persist: boolean; filterIds: Set | n await removeSubsFromDataElementGroups(api, config, subIdsToRemove, persist); + if (persist && updatedProjects.length > 0) { + console.info(`\nUpdated projects (${updatedProjects.length}):`); + for (const p of updatedProjects) { + console.info(` - ${p.name} (${p.id})`); + } + } + if (!persist) { console.info("Re-run with --persist to apply the changes."); } @@ -306,10 +315,26 @@ function removeSubsFromProject( const mer = computeFilteredSelection(dataElementsMER, sectors, subIdsToRemove); const unique = computeFilteredSelection(uniqueIndicators, sectors, subIdsToRemove); + const cleanedSelection = stripSubsFromDataElementsBySector( + project.config, + dataElementsSelection.updateSelected(selection.next), + subIdsToRemove + ); + const cleanedMER = stripSubsFromDataElementsBySector( + project.config, + dataElementsMER.updateSelected(mer.next), + subIdsToRemove + ); + const cleanedUnique = stripSubsFromDataElementsBySector( + project.config, + uniqueIndicators.updateSelected(unique.next), + subIdsToRemove + ); + const updated = project.setObj({ - dataElementsSelection: dataElementsSelection.updateSelected(selection.next), - dataElementsMER: dataElementsMER.updateSelected(mer.next), - uniqueIndicators: uniqueIndicators.updateSelected(unique.next), + dataElementsSelection: cleanedSelection, + dataElementsMER: cleanedMER, + uniqueIndicators: cleanedUnique, }); return { @@ -322,6 +347,40 @@ function removeSubsFromProject( }; } +/** + * Returns a copy of the DataElementsSet where the sub ids are removed from: + * - dataElementsBySector[sectorId] top-level entries. + * - Each remaining DE's pairedDataElements (nested). + * + * This is required because Project.getSelectedDataElements() runs + * `set.get({ onlySelected: true, includePaired: true })`, and the + * `includePaired` expansion uses `de.pairedDataElements` to re-inflate + * sub/paired ids that point at the sub via DM_PAIRED_DE. Without stripping + * those references, the subs reappear in dataSet sections, dataSetElements + * and dashboard visualizations on the next save. + */ +function stripSubsFromDataElementsBySector( + config: Config, + set: DataElementsSet, + subIdsToRemove: Set +): DataElementsSet { + const cleanedBySector = _.mapValues(set.data.dataElementsBySector, dataElements => + dataElements + .filter(de => !subIdsToRemove.has(de.id)) + .map(de => ({ + ...de, + pairedDataElements: de.pairedDataElements.filter( + paired => !subIdsToRemove.has(paired.id) + ), + })) + ); + + return new DataElementsSet(config, { + ...set.data, + dataElementsBySector: cleanedBySector, + }); +} + function computeFilteredSelection( set: DataElementsSet, sectors: Array<{ id: Id }>, From e604125bcf55ca2714d1f26cbac4d367fa5e55fb Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Rivero Date: Thu, 21 May 2026 07:17:53 -0500 Subject: [PATCH 36/49] add script to restore paired data elements --- ...ove-paired-sub-indicators-from-projects.ts | 8 +- ...estore-paired-data-elements-to-projects.ts | 284 ++++++++++++++++++ 2 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 src/scripts/restore-paired-data-elements-to-projects.ts diff --git a/src/scripts/remove-paired-sub-indicators-from-projects.ts b/src/scripts/remove-paired-sub-indicators-from-projects.ts index 954155bb..bb78eb59 100644 --- a/src/scripts/remove-paired-sub-indicators-from-projects.ts +++ b/src/scripts/remove-paired-sub-indicators-from-projects.ts @@ -121,8 +121,12 @@ async function run(app: App, options: { persist: boolean; filterIds: Set | n logRemovedDetail(removed, config); if (persist) { - await updatedProject.save({ skipValidation: true }); - await new ProjectDashboardSave(updatedProject).execute(); + await updatedProject.save({ skipValidation: true }).catch(err => { + console.error(`ERROR saving project ${project.id}:`, err); + }); + await new ProjectDashboardSave(updatedProject).execute().catch(err => { + console.error(`ERROR updating dashboards for project ${project.id}:`, err); + }); updatedProjects.push({ id: project.id, name: project.name }); } else { const json = await new ProjectDb(updatedProject).toJSON({ skipValidation: true }); diff --git a/src/scripts/restore-paired-data-elements-to-projects.ts b/src/scripts/restore-paired-data-elements-to-projects.ts new file mode 100644 index 00000000..d7ff65ed --- /dev/null +++ b/src/scripts/restore-paired-data-elements-to-projects.ts @@ -0,0 +1,284 @@ +import _ from "lodash"; +import fs from "fs"; +import parse from "parse-typed-args"; +import { promiseMap } from "../migrations/utils"; +import { Config } from "../models/Config"; +import DataElementsSet from "../models/dataElementsSet"; +import Project from "../models/Project"; +import ProjectDashboardSave from "../models/ProjectDashboardSave"; +import ProjectDb from "../models/ProjectDb"; +import ProjectsList from "../models/ProjectsList"; +import { D2Api, Id } from "../types/d2-api"; +import { App, getApp } from "./common"; + +const MAIN_CODES = ["B060300", "B060500", "B061000", "B130200", "B130400", "B130600"] as const; + +interface Opts { + url?: string; + persist?: boolean; + "project-ids"?: string; +} + +main().catch(err => { + console.error("ERROR", err); + process.exit(1); +}); + +async function main() { + const parser = parse({ + opts: { + url: {}, + persist: { switch: true }, + "project-ids": {}, + }, + }); + const { opts } = parser(process.argv) as { opts: Opts }; + + const usage = + "restore-paired-data-elements-to-projects --url=DHIS2_URL [--persist] [--project-ids=ID1,ID2,...]"; + if (!opts.url) { + console.error(usage); + process.exit(1); + } + + const app = await getApp({ baseUrl: opts.url }); + const persist = Boolean(opts.persist); + const filterIds = parseProjectIds(opts["project-ids"]); + + await run(app, { persist, filterIds }); +} + +function parseProjectIds(s: string | undefined): Set | null { + if (!s) return null; + const ids = s + .split(",") + .map(x => x.trim()) + .filter(Boolean); + return new Set(ids); +} + +async function run(app: App, options: { persist: boolean; filterIds: Set | null }) { + const { api, config } = app; + const { persist, filterIds } = options; + + const pairByMainId = buildPairByMainId(config); + if (_.isEmpty(pairByMainId)) { + console.error(`No paired DE mapping resolved for any main code: ${MAIN_CODES.join(", ")}`); + return; + } + + const mode = persist ? "PERSIST" : "DRY-RUN"; + console.info(`[${mode}] Pairs to look for:`); + console.info(describePairs(pairByMainId, config)); + + const allProjectIds = await getProjectIds(api, config); + const projectIds = filterIds ? allProjectIds.filter(id => filterIds.has(id)) : allProjectIds; + + if (filterIds && projectIds.length < filterIds.size) { + const missing = Array.from(filterIds).filter(id => !allProjectIds.includes(id)); + console.error(`WARN: ${missing.length} project id(s) not found: ${missing.join(", ")}`); + } + + console.info(`Projects to scan: ${projectIds.length}`); + + let changedCount = 0; + let totalAdded = 0; + + await promiseMap(projectIds, async projectId => { + const project = await Project.get(api, config, projectId); + const { project: updatedProject, added } = restorePairedToProject(project, pairByMainId); + const addedTotal = sumAdded(added); + if (addedTotal === 0) { + console.info(`- No paired DEs to restore.`); + return; + } + + changedCount += 1; + totalAdded += addedTotal; + + const label = `[${project.parentOrgUnit?.displayName}] ${project.name} (${project.id})`; + console.info( + `- ${label}: ${addedTotal} paired DE(s) ${persist ? "restored" : "to restore"}` + ); + logAddedDetail(added, config); + + if (persist) { + await updatedProject.save({ skipValidation: true }).catch(err => { + console.error(`ERROR saving project ${project.id}:`, err); + }); + } else { + const json = await new ProjectDb(updatedProject).toJSON(); + fs.writeFileSync(`project-${project.id}.json`, JSON.stringify(json, null, 2), "utf-8"); + } + }); + + console.info( + `Done. ${changedCount} project(s) ${persist ? "updated" : "would be updated"}, ` + + `${totalAdded} paired DE(s) ${persist ? "restored" : "would be restored"}.` + ); + if (!persist) { + console.info("Re-run with --persist to apply the changes."); + } +} + +async function getProjectIds(api: D2Api, config: Config): Promise { + const { objects } = await new ProjectsList(api, config).get( + {}, + { field: "id", order: "asc" }, + { page: 1, pageSize: 100000 } + ); + return _(objects) + .orderBy([p => p.parent.displayName, p => p.displayName]) + .map(p => p.id) + .value(); +} + +function buildPairByMainId(config: Config): Record { + const dataElementsByCode = _.keyBy(config.dataElements, de => de.code); + const pairedAttrCode = config.attributes.pairedDataElement.code; + + const result: Record = {}; + for (const mainCode of MAIN_CODES) { + const mainDe = dataElementsByCode[mainCode]; + if (!mainDe) { + console.error(`WARN: main code ${mainCode} not found in metadata`); + continue; + } + const value = getAttributeValue(mainDe, pairedAttrCode); + if (!value) { + console.error(`WARN: ${mainCode} has no ${pairedAttrCode} value`); + continue; + } + const pairedCodes = value + .split(",") + .map(s => s.trim()) + .filter(Boolean); + if (pairedCodes.length !== 1) { + console.error( + `WARN: ${mainCode} has unexpected ${pairedAttrCode} value: "${value}" — taking all` + ); + } + for (const pairedCode of pairedCodes) { + const pairedDe = dataElementsByCode[pairedCode]; + if (!pairedDe) { + console.error( + `WARN: paired code ${pairedCode} (for main ${mainCode}) not found in metadata` + ); + continue; + } + result[mainDe.id] = pairedDe.id; + } + } + return result; +} + +function getAttributeValue( + dataElement: { + attributeValues: Array<{ attribute: { code: string }; value: string }>; + }, + attributeCode: string +): string | null { + const av = dataElement.attributeValues.find(av => av.attribute.code === attributeCode); + return av?.value || null; +} + +function describePairs(pairByMainId: Record, config: Config): string { + const byId = _.keyBy(config.dataElements, de => de.id); + return Object.entries(pairByMainId) + .map(([mainId, pairedId]) => { + const mainCode = byId[mainId]?.code || mainId; + const pairedCode = byId[pairedId]?.code || pairedId; + return ` ${mainCode} (${mainId}) → ${pairedCode} (${pairedId})`; + }) + .join("\n"); +} + +type AddedBySector = Record; + +interface AddedSummary { + selection: AddedBySector; + mer: AddedBySector; + unique: AddedBySector; +} + +function restorePairedToProject( + project: Project, + pairByMainId: Record +): { project: Project; added: AddedSummary } { + const { sectors, dataElementsSelection, dataElementsMER, uniqueIndicators } = project.data; + + const selection = computeRestoredSelection(dataElementsSelection, sectors, pairByMainId); + const mer = computeRestoredSelection(dataElementsMER, sectors, pairByMainId); + const unique = computeRestoredSelection(uniqueIndicators, sectors, pairByMainId); + + // Rebuild dataElementsSelection with groupPaired: true so the includePaired: true + // expansion in Project.getSelectedDataElements re-inflates paired DEs into the + // dataSet sections on save (this is the original/default app behavior). + const rebuiltSelection = DataElementsSet.build(project.config, { + groupPaired: true, + }).updateSelected(selection.next); + + const updated = project.setObj({ + dataElementsSelection: rebuiltSelection, + dataElementsMER: dataElementsMER.updateSelected(mer.next), + uniqueIndicators: uniqueIndicators.updateSelected(unique.next), + }); + + return { + project: updated, + added: { + selection: selection.added, + mer: mer.added, + unique: unique.added, + }, + }; +} + +function computeRestoredSelection( + set: DataElementsSet, + sectors: Array<{ id: Id }>, + pairByMainId: Record +): { next: Record; added: AddedBySector } { + const next: Record = {}; + const added: AddedBySector = {}; + + for (const sector of sectors) { + const selectedIds = set.data.selected[sector.id] || []; + const idSet = new Set(selectedIds); + + const toAdd: Id[] = []; + for (const [mainId, pairedId] of Object.entries(pairByMainId)) { + if (idSet.has(mainId) && !idSet.has(pairedId)) { + toAdd.push(pairedId); + } + } + + next[sector.id] = toAdd.length > 0 ? [...selectedIds, ...toAdd] : selectedIds; + if (toAdd.length > 0) added[sector.id] = toAdd; + } + + return { next, added }; +} + +function sumAdded(added: AddedSummary): number { + const all = [..._.values(added.selection), ..._.values(added.mer), ..._.values(added.unique)]; + return _.sumBy(all, arr => arr.length); +} + +function logAddedDetail(added: AddedSummary, config: Config) { + const byId = _.keyBy(config.dataElements, de => de.id); + const code = (id: Id) => byId[id]?.code || id; + + const sections: Array<{ name: string; data: AddedBySector }> = [ + { name: "selection", data: added.selection }, + { name: "MER", data: added.mer }, + { name: "uniqueIndicators", data: added.unique }, + ]; + + for (const { name, data } of sections) { + for (const [sectorId, ids] of Object.entries(data)) { + if (ids.length === 0) continue; + console.info(` [${name}] sector=${sectorId} paired=${ids.map(code).join(",")}`); + } + } +} From 6e42e17522e55f192959d7c7e9f0b156b8a43230 Mon Sep 17 00:00:00 2001 From: Eduardo Peredo Date: Thu, 21 May 2026 21:10:21 -0500 Subject: [PATCH 37/49] add dashboard info --- .../DashboardInfoModal.tsx | 61 +++++++++++++++++++ src/components/dashboard/Dashboard.tsx | 4 ++ 2 files changed, 65 insertions(+) create mode 100644 src/components/dashboard-info-modal/DashboardInfoModal.tsx diff --git a/src/components/dashboard-info-modal/DashboardInfoModal.tsx b/src/components/dashboard-info-modal/DashboardInfoModal.tsx new file mode 100644 index 00000000..f92fb7ec --- /dev/null +++ b/src/components/dashboard-info-modal/DashboardInfoModal.tsx @@ -0,0 +1,61 @@ +import React from "react"; +import Button from "@material-ui/core/Button"; +import Dialog from "@material-ui/core/Dialog"; +import DialogActions from "@material-ui/core/DialogActions"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogTitle from "@material-ui/core/DialogTitle"; + +import i18n from "../../locales"; + +type DashboardInfoModalProps = { + isOpen: boolean; + onClose: () => void; +}; + +export const DashboardInfoModal: React.FC = props => { + const { isOpen, onClose } = props; + + return ( + + {i18n.t("Purpose of Platform Dashboards")} + +

{i18n.t("These dashboards are meant to:")}

+
    +
  • {i18n.t("Encourage data informed decisions.")}
  • +
  • + {i18n.t( + "Help implementers identify phenomena in data that can initiate opportunities for conversations and decision-making on how to engage in adaptive program management." + )} +
  • +
  • + {i18n.t( + "Be incorporated into the monthly quality process. Ideally, this check should be happening when preparing MERs for your regional teams." + )} +
  • +
+

{i18n.t("Create a task list with some common follow on actions:")}

+
    +
  • {i18n.t("Conversions by topic")}
  • +
  • {i18n.t("Errors identified")}
  • +
  • {i18n.t("Divergence from targets")}
  • +
  • + {i18n.t("Bullets on what to highlight in the MER with mitigation measures")} +
  • +
  • {i18n.t("Potential points to escalate")}
  • +
  • {i18n.t("Determining if site visits should be made")}
  • +
  • {i18n.t("Reviewing budget for spent, pending, and remaining")}
  • +
+

+ {i18n.t( + "If there is anything that can be improved, please let us know by sending an email to pmt@samaritan.org." + )} +

+
+ + + +
+ ); +}; diff --git a/src/components/dashboard/Dashboard.tsx b/src/components/dashboard/Dashboard.tsx index e937d22f..63b0b80f 100644 --- a/src/components/dashboard/Dashboard.tsx +++ b/src/components/dashboard/Dashboard.tsx @@ -5,6 +5,7 @@ import i18n from "../../locales"; import PageHeader from "../../components/page-header/PageHeader"; import { useAppHistory } from "../../utils/use-app-history"; import { useAppContext } from "../../contexts/api-context"; +import { DashboardInfoModal } from "../dashboard-info-modal/DashboardInfoModal"; function getTranslations(name: string) { return { @@ -39,6 +40,7 @@ const Dashboard: React.FC = props => { const dashboardUrl = dashboardUrlBase + `/#/${id}`; const translations = getTranslations(name); const appHistory = useAppHistory(backUrl); + const [openModal, setOpenModal] = React.useState(true); React.useEffect(() => { const iframe = iframeRef.current; @@ -74,6 +76,8 @@ const Dashboard: React.FC = props => { )} + setOpenModal(false)} /> +