From 1ffc4537d2ca32f70fa57ae763fbf1c493f753af Mon Sep 17 00:00:00 2001 From: Michael Hudson Nkotagu Date: Mon, 5 Aug 2024 15:21:14 +0300 Subject: [PATCH 1/3] feat: Add TreemapChartScope to HURUmap-core package --- .../src/Scope/TreemapChartScope.js | 245 ++++++++++++++++++ packages/hurumap-core/src/Scope/index.js | 2 + 2 files changed, 247 insertions(+) create mode 100644 packages/hurumap-core/src/Scope/TreemapChartScope.js diff --git a/packages/hurumap-core/src/Scope/TreemapChartScope.js b/packages/hurumap-core/src/Scope/TreemapChartScope.js new file mode 100644 index 000000000..406e343ab --- /dev/null +++ b/packages/hurumap-core/src/Scope/TreemapChartScope.js @@ -0,0 +1,245 @@ +import merge from "deepmerge"; + +import Scope from "./Scope"; + +export default function TreemapChartScope({ + primaryData, + metadata, + config, + secondaryData, + primaryParentData, + secondaryParentData, + profileNames, + isCompare, + isMobile, + theme, + args, +}) { + const { primary_group: primaryGroup } = metadata; + const nestedFields = config?.nest_fields ?? [primaryGroup]; // if nest fields are undefined, make use primaryGroup + const transform = [ + { + type: "nest", + keys: nestedFields, + }, + { + type: "treemap", + field: { signal: "datatype[Units]" }, + method: { signal: "layout" }, + ratio: { signal: "aspectRatio" }, + size: [ + { + signal: + "isCompare && data('secondary').length > 1 && !isMobile ? width/2 -30: width", + }, + { signal: "isCompare && isMobile ? height/2 : height" }, + ], + }, + ]; + console.log(theme); + return merge( + Scope({ + primaryData, + metadata, + config, + secondaryData, + primaryParentData, + secondaryParentData, + chartType: "treemap", + transform, + theme, + args, + }), + { + height: isMobile && isCompare && secondaryData?.length > 1 ? 760 : 380, + signals: [ + { + name: "height", + value: isMobile && isCompare && secondaryData?.length > 1 ? 760 : 380, + }, + { + name: "isMobile", + value: isMobile, + }, + { + name: "isCompare", + value: isCompare, + }, + { + name: "nestedFields", + value: nestedFields, + }, + ], + scales: [ + { + name: "color", + type: "ordinal", + domain: { data: "primary_formatted", field: nestedFields[0] }, + range: [theme.palette.primary.main], + }, + { + name: "secondary", + type: "ordinal", + domain: { data: "secondary_formatted", field: nestedFields[0] }, + range: [theme.palette.secondary.main], + }, + { + name: "legend_primary_scale", + type: "ordinal", + domain: [profileNames.primary.toUpperCase()], + range: [theme.palette.primary.main], + }, + { + name: "legend_secondary_scale", + type: "ordinal", + domain: [profileNames.secondary.toUpperCase()], + range: [theme.palette.secondary.main], + }, + ], + + marks: [ + { + type: "group", + name: "primary_tree", + encode: { + update: { + x: { value: 0 }, + y: { signal: "chartY" }, + }, + }, + legends: isCompare + ? [ + { + orient: "top", + fill: "legend_primary_scale", + labelFontWeight: "bold", + labelColor: "#666", + labelFont: theme.typography.fontFamily, + }, + ] + : null, + marks: [ + { + type: "rect", + from: { data: "primary_formatted" }, + encode: { + enter: { + fill: { scale: "color", field: { signal: "mainGroup" } }, + stroke: { value: "#fff" }, + }, + update: { + x: { field: "x0" }, + y: { field: "y0" }, + x2: { field: "x1" }, + y2: { field: "y1" }, + tooltip: { + signal: + "{'group': datum[mainGroup] + ' ' + (isValid(datum[nestedFields[1]]) ? datum[nestedFields[1]] : '' ) + ' ' + (isValid(datum[nestedFields[2]]) ? datum[nestedFields[2]] : '') , 'count': format(datum.count, numberFormat.value)}", + }, + }, + }, + }, + { + type: "text", + from: { data: "primary_formatted" }, + encode: { + enter: { + font: { value: theme.typography.fontFamily }, + fill: { value: theme.palette.text.secondary }, + }, + update: { + align: { value: "left" }, + x: { signal: "datum.x0 + 5" }, + y: { signal: "datum.y0 + 15" }, + limit: { signal: "datum.x1 - datum.x0 - 10" }, + text: { + signal: + "[format(datum[datatype[Units]], numberFormat[Units]), datum[mainGroup], datum[nestedFields[1]] || '', datum[nestedFields[2]] || '' ]", + }, + }, + }, + }, + ], + }, + { + type: "group", + name: "secondary_tree", + encode: { + update: { + x: { + signal: + "!isMobile && data('secondary').length > 1 ? width / 2 + 15 : 0", + }, + y: { + signal: + "isMobile && data('secondary').length > 1 ? height/2 + 30: data('secondary').length > 1 ? chartY: height + 40", + }, + height: { + signal: + "isMobile && data('secondary').length > 1 ? height/2: 0", + }, + width: { + signal: + "!isMobile && data('secondary').length > 1 ? (width / 2 ) : data('secondary').length > 1 ? width : 0", + }, + }, + }, + legends: isCompare + ? [ + { + orient: "top", + fill: "legend_secondary_scale", + labelFontWeight: "bold", + labelColor: "#666", + labelFont: theme.typography.fontFamily, + labelLimit: 400, + }, + ] + : null, + marks: [ + { + type: "rect", + from: { data: "secondary_formatted" }, + encode: { + enter: { + fill: { scale: "secondary", field: { signal: "mainGroup" } }, + stroke: { value: "#fff" }, + }, + update: { + x: { field: "x0" }, + y: { field: "y0" }, + x2: { field: "x1" }, + y2: { field: "y1" }, + tooltip: { + signal: + "{'group': datum[mainGroup] + ' ' + (isValid(datum[nestedFields[1]]) ? datum[nestedFields[1]] : '' ) + ' ' + (isValid(datum[nestedFields[2]]) ? datum[nestedFields[2]] : '') , 'count': format(datum.count, numberFormat.value)}", + }, + }, + }, + }, + { + type: "text", + from: { data: "secondary_formatted" }, + encode: { + enter: { + font: { value: theme.typography.fontFamily }, + fill: { value: theme.palette.text.secondary }, + }, + update: { + align: { value: "left" }, + x: { signal: "datum.x0 + 5" }, + y: { signal: "datum.y0 + 15" }, + limit: { signal: "datum.x1 - datum.x0 - 10" }, + text: { + signal: + "[format(datum[datatype[Units]], numberFormat[Units]), datum[mainGroup], datum[nestedFields[1]] || '', datum[nestedFields[2]] || '' ]", + }, + }, + }, + }, + ], + }, + ], + }, + ); +} diff --git a/packages/hurumap-core/src/Scope/index.js b/packages/hurumap-core/src/Scope/index.js index 453c25931..c96688f54 100644 --- a/packages/hurumap-core/src/Scope/index.js +++ b/packages/hurumap-core/src/Scope/index.js @@ -2,10 +2,12 @@ import BarChartScope from "./BarChartScope"; import DonutChartScope from "./DonutChartScope"; import LineChartScope from "./LineChartScope"; import Scope from "./Scope"; +import TreemapChartScope from "./TreemapChartScope"; export default { Scope, BarChartScope, LineChartScope, DonutChartScope, + TreemapChartScope, }; From cab619e89f8767fd4ae08476e625d5123451aff3 Mon Sep 17 00:00:00 2001 From: Michael Hudson Nkotagu Date: Mon, 5 Aug 2024 15:32:15 +0300 Subject: [PATCH 2/3] chore: Remove TreemapChartScope from PesaYetu --- .../HURUmap/Chart/TreemapChartScope.js | 242 ------------------ .../HURUmap/Chart/configureScope.js | 6 +- .../src/Scope/TreemapChartScope.js | 2 +- 3 files changed, 4 insertions(+), 246 deletions(-) delete mode 100644 apps/pesayetu/src/components/HURUmap/Chart/TreemapChartScope.js diff --git a/apps/pesayetu/src/components/HURUmap/Chart/TreemapChartScope.js b/apps/pesayetu/src/components/HURUmap/Chart/TreemapChartScope.js deleted file mode 100644 index 19c26271c..000000000 --- a/apps/pesayetu/src/components/HURUmap/Chart/TreemapChartScope.js +++ /dev/null @@ -1,242 +0,0 @@ -import merge from "deepmerge"; - -import Scope from "./Scope"; - -import theme from "@/pesayetu/theme"; - -export default function TreemapChartScope( - primaryData, - metadata, - config, - secondaryData, - primaryParentData, - secondaryParentData, - profileNames, - isCompare, - isMobile, -) { - const { primary_group: primaryGroup } = metadata; - const nestedFields = config?.nest_fields ?? [primaryGroup]; // if nest fields are undefined, make use primaryGroup - - return merge( - Scope( - primaryData, - metadata, - config, - secondaryData, - primaryParentData, - secondaryParentData, - "treemap", - [ - { - type: "nest", - keys: nestedFields, - }, - { - type: "treemap", - field: { signal: "datatype[Units]" }, - method: { signal: "layout" }, - ratio: { signal: "aspectRatio" }, - size: [ - { - signal: - "isCompare && data('secondary').length > 1 && !isMobile ? width/2 -30: width", - }, - { signal: "isCompare && isMobile ? height/2 : height" }, - ], - }, - ], - ), - { - height: isMobile && isCompare && secondaryData?.length > 1 ? 760 : 380, - signals: [ - { - name: "height", - value: isMobile && isCompare && secondaryData?.length > 1 ? 760 : 380, - }, - { - name: "isMobile", - value: isMobile, - }, - { - name: "isCompare", - value: isCompare, - }, - { - name: "nestedFields", - value: nestedFields, - }, - ], - scales: [ - { - name: "color", - type: "ordinal", - domain: { data: "primary_formatted", field: nestedFields[0] }, - range: [theme.palette.primary.main], - }, - { - name: "secondary", - type: "ordinal", - domain: { data: "secondary_formatted", field: nestedFields[0] }, - range: [theme.palette.secondary.main], - }, - { - name: "legend_primary_scale", - type: "ordinal", - domain: [profileNames.primary.toUpperCase()], - range: [theme.palette.primary.main], - }, - { - name: "legend_secondary_scale", - type: "ordinal", - domain: [profileNames.secondary.toUpperCase()], - range: [theme.palette.secondary.main], - }, - ], - - marks: [ - { - type: "group", - name: "primary_tree", - encode: { - update: { - x: { value: 0 }, - y: { signal: "chartY" }, - }, - }, - legends: isCompare - ? [ - { - orient: "top", - fill: "legend_primary_scale", - labelFontWeight: "bold", - labelColor: "#666", - labelFont: theme.typography.fontFamily, - }, - ] - : null, - marks: [ - { - type: "rect", - from: { data: "primary_formatted" }, - encode: { - enter: { - fill: { scale: "color", field: { signal: "mainGroup" } }, - stroke: { value: "#fff" }, - }, - update: { - x: { field: "x0" }, - y: { field: "y0" }, - x2: { field: "x1" }, - y2: { field: "y1" }, - tooltip: { - signal: - "{'group': datum[mainGroup] + ' ' + (isValid(datum[nestedFields[1]]) ? datum[nestedFields[1]] : '' ) + ' ' + (isValid(datum[nestedFields[2]]) ? datum[nestedFields[2]] : '') , 'count': format(datum.count, numberFormat.value)}", - }, - }, - }, - }, - { - type: "text", - from: { data: "primary_formatted" }, - encode: { - enter: { - font: { value: theme.typography.fontFamily }, - fill: { value: theme.palette.text.secondary }, - }, - update: { - align: { value: "left" }, - x: { signal: "datum.x0 + 5" }, - y: { signal: "datum.y0 + 15" }, - limit: { signal: "datum.x1 - datum.x0 - 10" }, - text: { - signal: - "[format(datum[datatype[Units]], numberFormat[Units]), datum[mainGroup], datum[nestedFields[1]] || '', datum[nestedFields[2]] || '' ]", - }, - }, - }, - }, - ], - }, - { - type: "group", - name: "secondary_tree", - encode: { - update: { - x: { - signal: - "!isMobile && data('secondary').length > 1 ? width / 2 + 15 : 0", - }, - y: { - signal: - "isMobile && data('secondary').length > 1 ? height/2 + 30: data('secondary').length > 1 ? chartY: height + 40", - }, - height: { - signal: - "isMobile && data('secondary').length > 1 ? height/2: 0", - }, - width: { - signal: - "!isMobile && data('secondary').length > 1 ? (width / 2 ) : data('secondary').length > 1 ? width : 0", - }, - }, - }, - legends: isCompare - ? [ - { - orient: "top", - fill: "legend_secondary_scale", - labelFontWeight: "bold", - labelColor: "#666", - labelFont: theme.typography.fontFamily, - labelLimit: 400, - }, - ] - : null, - marks: [ - { - type: "rect", - from: { data: "secondary_formatted" }, - encode: { - enter: { - fill: { scale: "secondary", field: { signal: "mainGroup" } }, - stroke: { value: "#fff" }, - }, - update: { - x: { field: "x0" }, - y: { field: "y0" }, - x2: { field: "x1" }, - y2: { field: "y1" }, - tooltip: { - signal: - "{'group': datum[mainGroup] + ' ' + (isValid(datum[nestedFields[1]]) ? datum[nestedFields[1]] : '' ) + ' ' + (isValid(datum[nestedFields[2]]) ? datum[nestedFields[2]] : '') , 'count': format(datum.count, numberFormat.value)}", - }, - }, - }, - }, - { - type: "text", - from: { data: "secondary_formatted" }, - encode: { - enter: { - font: { value: theme.typography.fontFamily }, - fill: { value: theme.palette.text.secondary }, - }, - update: { - align: { value: "left" }, - x: { signal: "datum.x0 + 5" }, - y: { signal: "datum.y0 + 15" }, - limit: { signal: "datum.x1 - datum.x0 - 10" }, - text: { - signal: - "[format(datum[datatype[Units]], numberFormat[Units]), datum[mainGroup], datum[nestedFields[1]] || '', datum[nestedFields[2]] || '' ]", - }, - }, - }, - }, - ], - }, - ], - }, - ); -} diff --git a/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js b/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js index f32afbbf6..974fac643 100644 --- a/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js +++ b/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js @@ -2,14 +2,14 @@ import { Scope } from "@hurumap/core"; import MultiLineChartScope from "./MultiLineChartScope"; import StackedChartScope from "./StackedChartScope"; -import TreemapChartScope from "./TreemapChartScope"; import VerticalBarChartScope from "./VerticalBarChartScope"; import VerticalStackedChartScope from "./VerticalStackedChartScope"; import { hurumapArgs } from "@/pesayetu/config"; import theme from "@/pesayetu/theme"; -const { BarChartScope, LineChartScope, DonutChartScope } = Scope; +const { BarChartScope, LineChartScope, DonutChartScope, TreemapChartScope } = + Scope; export default function configureScope( indicator, @@ -74,7 +74,7 @@ export default function configureScope( vegaSpec = DonutChartScope(scopeOptions); break; case "treemap": - vegaSpec = TreemapChartScope(..._scopeOptions); + vegaSpec = TreemapChartScope(scopeOptions); break; case "stacked": if (isMobile) { diff --git a/packages/hurumap-core/src/Scope/TreemapChartScope.js b/packages/hurumap-core/src/Scope/TreemapChartScope.js index 406e343ab..b04b4f6cc 100644 --- a/packages/hurumap-core/src/Scope/TreemapChartScope.js +++ b/packages/hurumap-core/src/Scope/TreemapChartScope.js @@ -36,7 +36,7 @@ export default function TreemapChartScope({ ], }, ]; - console.log(theme); + return merge( Scope({ primaryData, From f1cb325e8b3bb5072e8f0d369824faec7525f63c Mon Sep 17 00:00:00 2001 From: Michael Hudson Nkotagu Date: Mon, 5 Aug 2024 15:37:13 +0300 Subject: [PATCH 3/3] chore: Remove TreemapChartScope from ClimateMappedAfrica --- .../HURUmap/Chart/TreemapChartScope.js | 242 ------------------ .../HURUmap/Chart/configureScope.js | 6 +- 2 files changed, 3 insertions(+), 245 deletions(-) delete mode 100644 apps/climatemappedafrica/src/components/HURUmap/Chart/TreemapChartScope.js diff --git a/apps/climatemappedafrica/src/components/HURUmap/Chart/TreemapChartScope.js b/apps/climatemappedafrica/src/components/HURUmap/Chart/TreemapChartScope.js deleted file mode 100644 index 7f85c10b2..000000000 --- a/apps/climatemappedafrica/src/components/HURUmap/Chart/TreemapChartScope.js +++ /dev/null @@ -1,242 +0,0 @@ -import merge from "deepmerge"; - -import Scope from "./Scope"; - -import theme from "@/climatemappedafrica/theme"; - -export default function TreemapChartScope( - primaryData, - metadata, - config, - secondaryData, - primaryParentData, - secondaryParentData, - profileNames, - isCompare, - isMobile, -) { - const { primary_group: primaryGroup } = metadata; - const nestedFields = config?.nest_fields ?? [primaryGroup]; // if nest fields are undefined, make use primaryGroup - - return merge( - Scope( - primaryData, - metadata, - config, - secondaryData, - primaryParentData, - secondaryParentData, - "treemap", - [ - { - type: "nest", - keys: nestedFields, - }, - { - type: "treemap", - field: { signal: "datatype[Units]" }, - method: { signal: "layout" }, - ratio: { signal: "aspectRatio" }, - size: [ - { - signal: - "isCompare && data('secondary').length > 1 && !isMobile ? width/2 -30: width", - }, - { signal: "isCompare && isMobile ? height/2 : height" }, - ], - }, - ], - ), - { - height: isMobile && isCompare && secondaryData?.length > 1 ? 760 : 380, - signals: [ - { - name: "height", - value: isMobile && isCompare && secondaryData?.length > 1 ? 760 : 380, - }, - { - name: "isMobile", - value: isMobile, - }, - { - name: "isCompare", - value: isCompare, - }, - { - name: "nestedFields", - value: nestedFields, - }, - ], - scales: [ - { - name: "color", - type: "ordinal", - domain: { data: "primary_formatted", field: nestedFields[0] }, - range: [theme.palette.primary.main], - }, - { - name: "secondary", - type: "ordinal", - domain: { data: "secondary_formatted", field: nestedFields[0] }, - range: [theme.palette.secondary.main], - }, - { - name: "legend_primary_scale", - type: "ordinal", - domain: [profileNames.primary.toUpperCase()], - range: [theme.palette.primary.main], - }, - { - name: "legend_secondary_scale", - type: "ordinal", - domain: [profileNames.secondary.toUpperCase()], - range: [theme.palette.secondary.main], - }, - ], - - marks: [ - { - type: "group", - name: "primary_tree", - encode: { - update: { - x: { value: 0 }, - y: { signal: "chartY" }, - }, - }, - legends: isCompare - ? [ - { - orient: "top", - fill: "legend_primary_scale", - labelFontWeight: "bold", - labelColor: "#666", - labelFont: theme.typography.fontFamily, - }, - ] - : null, - marks: [ - { - type: "rect", - from: { data: "primary_formatted" }, - encode: { - enter: { - fill: { scale: "color", field: { signal: "mainGroup" } }, - stroke: { value: "#fff" }, - }, - update: { - x: { field: "x0" }, - y: { field: "y0" }, - x2: { field: "x1" }, - y2: { field: "y1" }, - tooltip: { - signal: - "{'group': datum[mainGroup] + ' ' + (isValid(datum[nestedFields[1]]) ? datum[nestedFields[1]] : '' ) + ' ' + (isValid(datum[nestedFields[2]]) ? datum[nestedFields[2]] : '') , 'count': format(datum.count, numberFormat.value)}", - }, - }, - }, - }, - { - type: "text", - from: { data: "primary_formatted" }, - encode: { - enter: { - font: { value: theme.typography.fontFamily }, - fill: { value: theme.palette.text.secondary }, - }, - update: { - align: { value: "left" }, - x: { signal: "datum.x0 + 5" }, - y: { signal: "datum.y0 + 15" }, - limit: { signal: "datum.x1 - datum.x0 - 10" }, - text: { - signal: - "[format(datum[datatype[Units]], numberFormat[Units]), datum[mainGroup], datum[nestedFields[1]] || '', datum[nestedFields[2]] || '' ]", - }, - }, - }, - }, - ], - }, - { - type: "group", - name: "secondary_tree", - encode: { - update: { - x: { - signal: - "!isMobile && data('secondary').length > 1 ? width / 2 + 15 : 0", - }, - y: { - signal: - "isMobile && data('secondary').length > 1 ? height/2 + 30: data('secondary').length > 1 ? chartY: height + 40", - }, - height: { - signal: - "isMobile && data('secondary').length > 1 ? height/2: 0", - }, - width: { - signal: - "!isMobile && data('secondary').length > 1 ? (width / 2 ) : data('secondary').length > 1 ? width : 0", - }, - }, - }, - legends: isCompare - ? [ - { - orient: "top", - fill: "legend_secondary_scale", - labelFontWeight: "bold", - labelColor: "#666", - labelFont: theme.typography.fontFamily, - labelLimit: 400, - }, - ] - : null, - marks: [ - { - type: "rect", - from: { data: "secondary_formatted" }, - encode: { - enter: { - fill: { scale: "secondary", field: { signal: "mainGroup" } }, - stroke: { value: "#fff" }, - }, - update: { - x: { field: "x0" }, - y: { field: "y0" }, - x2: { field: "x1" }, - y2: { field: "y1" }, - tooltip: { - signal: - "{'group': datum[mainGroup] + ' ' + (isValid(datum[nestedFields[1]]) ? datum[nestedFields[1]] : '' ) + ' ' + (isValid(datum[nestedFields[2]]) ? datum[nestedFields[2]] : '') , 'count': format(datum.count, numberFormat.value)}", - }, - }, - }, - }, - { - type: "text", - from: { data: "secondary_formatted" }, - encode: { - enter: { - font: { value: theme.typography.fontFamily }, - fill: { value: theme.palette.text.secondary }, - }, - update: { - align: { value: "left" }, - x: { signal: "datum.x0 + 5" }, - y: { signal: "datum.y0 + 15" }, - limit: { signal: "datum.x1 - datum.x0 - 10" }, - text: { - signal: - "[format(datum[datatype[Units]], numberFormat[Units]), datum[mainGroup], datum[nestedFields[1]] || '', datum[nestedFields[2]] || '' ]", - }, - }, - }, - }, - ], - }, - ], - }, - ); -} diff --git a/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js b/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js index 961c7fc81..f683b4a0d 100644 --- a/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js +++ b/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js @@ -2,14 +2,14 @@ import { Scope } from "@hurumap/core"; import MultiLineChartScope from "./MultiLineChartScope"; import StackedChartScope from "./StackedChartScope"; -import TreemapChartScope from "./TreemapChartScope"; import VerticalBarChartScope from "./VerticalBarChartScope"; import VerticalStackedChartScope from "./VerticalStackedChartScope"; import { hurumapArgs } from "@/climatemappedafrica/config"; import theme from "@/climatemappedafrica/theme"; -const { BarChartScope, LineChartScope, DonutChartScope } = Scope; +const { BarChartScope, LineChartScope, DonutChartScope, TreemapChartScope } = + Scope; export default function configureScope( indicator, @@ -74,7 +74,7 @@ export default function configureScope( vegaSpec = DonutChartScope(scopeOptions); break; case "treemap": - vegaSpec = TreemapChartScope(..._scopeOptions); + vegaSpec = TreemapChartScope(scopeOptions); break; case "stacked": if (isMobile) {