Skip to content

Commit

Permalink
WAI-44 LESMIS HLO1 list visuals (beyondessential#3171)
Browse files Browse the repository at this point in the history
* NZ-44 Add drilldown dashboard items for number of students list items

* NZ-44 Add a migration to setup the actual HLO dashboards

* NZ-44 Update drilldowns to attach to HLO dashboards
Move migration to be after HLO migration

* NZ-44 Move drilldowns to HLO dashboards too

* NZ-44 Remove primary education level from drill downs migration

* WAI-44 Add HLO1 list visuals for ECE, LSE, USE

* WAI-44 Change aggregation to include per period

* WAI-44 Update report configs

* WAI-44 Change <= to < for 5 year indicator

Co-authored-by: Klaus-S <69126149+Klaus-S@users.noreply.github.com>
  • Loading branch information
EMcQ-BES and Klaus-S authored Sep 12, 2021
1 parent dbde490 commit 831c6f2
Show file tree
Hide file tree
Showing 5 changed files with 1,342 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
'use strict';

import {
insertObject,
generateId,
deleteObject,
updateValues,
findSingleRecord,
} from '../utilities';

var dbm;
var type;
var seed;

/**
* We receive the dbmigrate dependency from dbmigrate initially.
* This enables us to not have to rely on NODE_PATH.
*/
exports.setup = function (options, seedLink) {
dbm = options.dbmigrate;
type = dbm.dataType;
seed = seedLink;
};

const SUBSECTORS = [
'EarlyChildhoodSubSector',
'PrimarySubSector',
'LowerSecondarySubSector',
'UpperSecondarySubSector',
];

const NEW_DASHBOARDS = [
...SUBSECTORS.map(sector => ({
code: `LESMIS_ESSDP_${sector}_HLO1`,
name: 'HLO 1: Graduates',
})),
...SUBSECTORS.map(sector => ({
code: `LESMIS_ESSDP_${sector}_HLO2`,
name: 'HLO 2: Competent Teachers',
})),
...SUBSECTORS.map(sector => ({
code: `LESMIS_ESSDP_${sector}_HLO3`,
name: 'HLO 3: Resources',
})),
// From the docs only USE has HLO5
{
code: 'LESMIS_ESSDP_UpperSecondarySubSector_HLO5',
name: 'HLO 5: School Leavers',
},
];

const DASHBOARD_ITEMS = [
'LESMIS_enrolment_ece_5_target',
'LESMIS_enrolment_ece_3_4_target',
'LESMIS_enrolment_ece_0_2_target',
'LESMIS_ESSDP_ECE_HLO1', // We'll be moving it after it's renamed
];

const moveItemToNewDashboard = async (db, itemCode, oldDashboardCode, newDashboardCode) => {
const itemId = (await findSingleRecord(db, 'dashboard_item', { code: itemCode })).id;
const oldDashboardId = (await findSingleRecord(db, 'dashboard', { code: oldDashboardCode })).id;
const newDashboardId = (await findSingleRecord(db, 'dashboard', { code: newDashboardCode })).id;

await updateValues(
db,
'dashboard_relation',
{ dashboard_id: newDashboardId }, // new values
{ dashboard_id: oldDashboardId, child_id: itemId }, // old values
);
};

exports.up = async function (db) {
// Add new dashboards
for (const { code, name } of NEW_DASHBOARDS) {
await insertObject(db, 'dashboard', {
id: generateId(),
code,
name,
root_entity_code: 'LA',
});
}
// Rename list to be more accurate
await updateValues(
db,
'report',
{ code: 'LESMIS_ESSDP_ECE_HLO1' }, // new value
{ code: 'LESMIS_ESSDP_ECE_SubSector_List' }, // old value
);
await updateValues(
db,
'dashboard_item',
{ code: 'LESMIS_ESSDP_ECE_HLO1', report_code: 'LESMIS_ESSDP_ECE_HLO1' }, // new values
{ code: 'LESMIS_ESSDP_ECE_SubSector_List' }, // old value
);
// Move list and drilldowns to new dashboard
for (const code of DASHBOARD_ITEMS) {
await moveItemToNewDashboard(
db,
code,
'LESMIS_ESSDP_EarlyChildhoodSubSector_Schools',
'LESMIS_ESSDP_EarlyChildhoodSubSector_HLO1',
);
}
};

exports.down = async function (db) {
// Move list and drilldowns back to old dashboard
for (const code of DASHBOARD_ITEMS) {
await moveItemToNewDashboard(
db,
code,
'LESMIS_ESSDP_EarlyChildhoodSubSector_HLO1',
'LESMIS_ESSDP_EarlyChildhoodSubSector_Schools',
);
}
// Rename list
await updateValues(
db,
'report',
{ code: 'LESMIS_ESSDP_ECE_SubSector_List' }, // new value
{ code: 'LESMIS_ESSDP_ECE_HLO1' }, // old value
);
await updateValues(
db,
'dashboard_item',
{ code: 'LESMIS_ESSDP_ECE_SubSector_List', report_code: 'LESMIS_ESSDP_ECE_SubSector_List' }, // new value
{ code: 'LESMIS_ESSDP_ECE_HLO1' }, // old values
);
// Remove new dashboards
for (const { code } of NEW_DASHBOARDS) {
await deleteObject(db, 'dashboard', { code });
}
};

exports._meta = {
version: 1,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
'use strict';

import { insertObject, generateId, findSingleRecord, findSingleRecordBySql } from '../utilities';

var dbm;
var type;
var seed;

/**
* We receive the dbmigrate dependency from dbmigrate initially.
* This enables us to not have to rely on NODE_PATH.
*/
exports.setup = function (options, seedLink) {
dbm = options.dbmigrate;
type = dbm.dataType;
seed = seedLink;
};

const generateReportConfig = educationLevel => ({
fetch: {
dataElements: [
`nostu_${educationLevel}_f_public`,
`nostu_${educationLevel}_f_private`,
`nostu_${educationLevel}_m_public`,
`nostu_${educationLevel}_m_private`,
],
aggregations: [
'FINAL_EACH_YEAR',
{
type: 'SUM_PER_PERIOD_PER_ORG_GROUP',
config: {
dataSourceEntityType: 'sub_district',
aggregationEntityType: 'requested',
},
},
],
},
transform: [
{
transform: 'select',
"translate($row.dataElement.split('_')[3], { m: 'Male', f: 'Female' })": '$row.value',
"'name'":
"translate($row.dataElement.split('_')[4], { public: 'Public', private: 'Private' })",
"'timestamp'": 'periodToTimestamp($row.period)',
'...': '*',
},
{
transform: 'aggregate',
timestamp: 'group',
name: 'group',
'...': 'last',
},
{
transform: 'select',
"'name'": "$row.name.concat(' ', $row.period)",
"'GPI'": '$row.Female/$row.Male',
"'Male_metadata'": '{ total: $row.Male + $row.Female }',
"'Female_metadata'": '{ total: $row.Male + $row.Female }',
'...': ['Male', 'Female'],
},
{
transform: 'sort',
by: '$row.name',
},
],
});

const FRONT_END_CONFIG = {
name: 'Number of Students (Gender, GPI, Public/Private)',
type: 'chart',
chartType: 'composed',
xName: 'Year',
periodGranularity: 'year',
chartConfig: {
GPI: {
chartType: 'line',
color: '#ffeb3b',
yAxisOrientation: 'right',
yName: 'GPI',
},
Male: {
chartType: 'bar',
labelType: 'fraction',
color: '#f44336',
stackId: '1',
yName: 'Number of Students',
valueType: 'number',
},
Female: {
chartType: 'bar',
labelType: 'fraction',
color: '#2196f3',
stackId: '1',
valueType: 'number',
},
},
};

const DASHBOARD_ITEMS = [
{
code: 'LESMIS_ESSDP_ece_NumberOfStudents',
reportConfig: generateReportConfig('ece'),
dashboardCode: 'LESMIS_ESSDP_EarlyChildhoodSubSector_HLO1',
},
{
code: 'LESMIS_ESSDP_lse_NumberOfStudents',
reportConfig: generateReportConfig('lse'),
dashboardCode: 'LESMIS_ESSDP_LowerSecondarySubSector_HLO1',
},
{
code: 'LESMIS_ESSDP_use_NumberOfStudents',
reportConfig: generateReportConfig('use'),
dashboardCode: 'LESMIS_ESSDP_UpperSecondarySubSector_HLO1',
},
];

// Same util functions as always
const addNewDashboardItemAndReport = async (
db,
{ code, frontEndConfig, reportConfig, permissionGroup, dashboardCode, entityTypes, projectCodes },
) => {
// insert report
const reportId = generateId();
const permissionGroupId = (
await findSingleRecord(db, 'permission_group', { name: permissionGroup })
).id;
await insertObject(db, 'report', {
id: reportId,
code,
config: reportConfig,
permission_group_id: permissionGroupId,
});

// insert dashboard item
const dashboardItemId = generateId();
await insertObject(db, 'dashboard_item', {
id: dashboardItemId,
code,
config: frontEndConfig,
report_code: code,
});

// insert relation record connecting dashboard item to dashboard
const dashboardId = (await findSingleRecord(db, 'dashboard', { code: dashboardCode })).id;
const maxSortOrder = (
await findSingleRecordBySql(
db,
`SELECT max(sort_order) as max_sort_order FROM dashboard_relation WHERE dashboard_id = '${dashboardId}';`,
)
).max_sort_order;
await insertObject(db, 'dashboard_relation', {
id: generateId(),
dashboard_id: dashboardId,
child_id: dashboardItemId,
entity_types: `{${entityTypes.join(', ')}}`,
project_codes: `{${projectCodes.join(', ')}}`,
permission_groups: `{${permissionGroup}}`,
sort_order: maxSortOrder + 1,
});
};

const removeDashboardItemAndReport = async (db, code) => {
await db.runSql(`DELETE FROM dashboard_item WHERE code = '${code}';`); // delete cascades to dashboard_relation
await db.runSql(`DELETE FROM report WHERE code = '${code}';`);
};

exports.up = async function (db) {
for (const { code, reportConfig, dashboardCode } of DASHBOARD_ITEMS) {
await addNewDashboardItemAndReport(db, {
code,
reportConfig,
frontEndConfig: FRONT_END_CONFIG,
permissionGroup: 'LESMIS Public',
dashboardCode,
entityTypes: ['sub_district', 'district', 'country'],
projectCodes: ['laos_schools'],
});
}
};

exports.down = async function (db) {
for (const { code } of DASHBOARD_ITEMS) {
await removeDashboardItemAndReport(db, code);
}
};

exports._meta = {
version: 1,
};
Loading

0 comments on commit 831c6f2

Please sign in to comment.