From ff2e247c6797b8b7341eb9129cd9707e646a9605 Mon Sep 17 00:00:00 2001 From: Kevin Koech Date: Thu, 1 Aug 2024 13:23:34 +0300 Subject: [PATCH 1/3] @hurumap/DonutChart --- .../HURUmap/Chart/configureScope.js | 18 +++++- .../HURUmap/Chart/configureScope.js | 18 +++++- .../src/Scope}/DonutChartScope.js | 57 ++++++++++--------- packages/hurumap-core/src/Scope/index.js | 2 + 4 files changed, 62 insertions(+), 33 deletions(-) rename {apps/pesayetu/src/components/HURUmap/Chart => packages/hurumap-core/src/Scope}/DonutChartScope.js (92%) diff --git a/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js b/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js index 1c8376c72..7feac6f60 100644 --- a/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js +++ b/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js @@ -1,6 +1,5 @@ import { Scope } from "@hurumap/core"; -import DonutChartScope from "./DonutChartScope"; import LineChartScope from "./LineChartScope"; import MultiLineChartScope from "./MultiLineChartScope"; import StackedChartScope from "./StackedChartScope"; @@ -11,7 +10,7 @@ import VerticalStackedChartScope from "./VerticalStackedChartScope"; import { hurumapArgs } from "@/climatemappedafrica/config"; import theme from "@/climatemappedafrica/theme"; -const { BarChartScope } = Scope; +const { BarChartScope, DonutChartScope } = Scope; export default function configureScope( indicator, @@ -42,6 +41,19 @@ export default function configureScope( isCompare, isMobile, ]; + const donutScopeOptions = { + primaryData: indicator?.data, + metadata: indicator?.metadata, + config: configuration, + secondaryData: secondaryIndicator?.data ?? null, + primaryParentData: showParent ? indicator?.parentData : [{}], + secondaryParentData: showParent ? secondaryIndicator?.parentData : [{}], + profileNames, + isCompare, + isMobile, + theme, + args: hurumapArgs, + }; switch (chartType) { case "line": if (configuration?.stacked_field) { @@ -51,7 +63,7 @@ export default function configureScope( } break; case "donut": - vegaSpec = DonutChartScope(...scopeOptions); + vegaSpec = DonutChartScope(donutScopeOptions); break; case "treemap": vegaSpec = TreemapChartScope(...scopeOptions); diff --git a/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js b/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js index cc0be0067..539434ff8 100644 --- a/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js +++ b/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js @@ -1,6 +1,5 @@ import { Scope } from "@hurumap/core"; -import DonutChartScope from "./DonutChartScope"; import LineChartScope from "./LineChartScope"; import MultiLineChartScope from "./MultiLineChartScope"; import StackedChartScope from "./StackedChartScope"; @@ -11,7 +10,7 @@ import VerticalStackedChartScope from "./VerticalStackedChartScope"; import { hurumapArgs } from "@/pesayetu/config"; import theme from "@/pesayetu/theme"; -const { BarChartScope } = Scope; +const { BarChartScope, DonutChartScope } = Scope; export default function configureScope( indicator, @@ -42,6 +41,19 @@ export default function configureScope( isCompare, isMobile, ]; + const donutScopeOptions = { + primaryData: indicator?.data, + metadata: indicator?.metadata, + config: configuration, + secondaryData: secondaryIndicator?.data ?? null, + primaryParentData: showParent ? indicator?.parentData : [{}], + secondaryParentData: showParent ? secondaryIndicator?.parentData : [{}], + profileNames, + isCompare, + isMobile, + theme, + args: hurumapArgs, + }; switch (chartType) { case "line": if (configuration?.stacked_field) { @@ -51,7 +63,7 @@ export default function configureScope( } break; case "donut": - vegaSpec = DonutChartScope(...scopeOptions); + vegaSpec = DonutChartScope(donutScopeOptions); break; case "treemap": vegaSpec = TreemapChartScope(...scopeOptions); diff --git a/apps/pesayetu/src/components/HURUmap/Chart/DonutChartScope.js b/packages/hurumap-core/src/Scope/DonutChartScope.js similarity index 92% rename from apps/pesayetu/src/components/HURUmap/Chart/DonutChartScope.js rename to packages/hurumap-core/src/Scope/DonutChartScope.js index 2ee30ddb3..53d0ecb13 100644 --- a/apps/pesayetu/src/components/HURUmap/Chart/DonutChartScope.js +++ b/packages/hurumap-core/src/Scope/DonutChartScope.js @@ -1,10 +1,8 @@ -import merge from "deepmerge"; +import deepmerge from "deepmerge"; import Scope from "./Scope"; -import theme from "@/pesayetu/theme"; - -export default function DonutChartScope( +export default function DonutChartScope({ primaryData, metadata, config, @@ -14,7 +12,9 @@ export default function DonutChartScope( profileNames, isCompare, isMobile, -) { + theme, + args, +}) { const { primary_group: primaryGroup } = metadata; const secondaryLegend = isCompare @@ -30,34 +30,37 @@ export default function DonutChartScope( ] : []; - return merge( - Scope( + const transform = [ + { + type: "formula", + expr: "format(datum[datatype[Units]], numberFormat[Units]) + ' ' + datum[mainGroup]", + as: "custom_label", + }, + { + type: "pie", + field: { signal: "datatype[Units]" }, + startAngle: { signal: "startAngle" }, + endAngle: { signal: "endAngle" }, + sort: { signal: "sort" }, + }, + { + type: "collect", + sort: { field: "count", order: "descending" }, + }, + ]; + return deepmerge( + Scope({ primaryData, metadata, config, secondaryData, primaryParentData, secondaryParentData, - "donut", - [ - { - type: "formula", - expr: "format(datum[datatype[Units]], numberFormat[Units]) + ' ' + datum[mainGroup]", - as: "custom_label", - }, - { - type: "pie", - field: { signal: "datatype[Units]" }, - startAngle: { signal: "startAngle" }, - endAngle: { signal: "endAngle" }, - sort: { signal: "sort" }, - }, - { - type: "collect", - sort: { field: "count", order: "descending" }, - }, - ], - ), + chartType: "donut", + transform, + theme, + args, + }), { height: isMobile && isCompare && secondaryData?.length > 1 ? 380 : 180, width: 700, diff --git a/packages/hurumap-core/src/Scope/index.js b/packages/hurumap-core/src/Scope/index.js index 9cbb70f75..596db59b1 100644 --- a/packages/hurumap-core/src/Scope/index.js +++ b/packages/hurumap-core/src/Scope/index.js @@ -1,7 +1,9 @@ import BarChartScope from "./BarChartScope"; +import DonutChartScope from "./DonutChartScope"; import Scope from "./Scope"; export default { Scope, BarChartScope, + DonutChartScope, }; From ad04337568f8c202f93e80a0519cb93d6cb6d832 Mon Sep 17 00:00:00 2001 From: Kevin Koech Date: Thu, 1 Aug 2024 14:30:09 +0300 Subject: [PATCH 2/3] @hurumap/DonutChart --- .../HURUmap/Chart/DonutChartScope.js | 313 ------------------ 1 file changed, 313 deletions(-) delete mode 100644 apps/climatemappedafrica/src/components/HURUmap/Chart/DonutChartScope.js diff --git a/apps/climatemappedafrica/src/components/HURUmap/Chart/DonutChartScope.js b/apps/climatemappedafrica/src/components/HURUmap/Chart/DonutChartScope.js deleted file mode 100644 index ce13d35bd..000000000 --- a/apps/climatemappedafrica/src/components/HURUmap/Chart/DonutChartScope.js +++ /dev/null @@ -1,313 +0,0 @@ -import merge from "deepmerge"; - -import Scope from "./Scope"; - -import theme from "@/climatemappedafrica/theme"; - -export default function DonutChartScope( - primaryData, - metadata, - config, - secondaryData, - primaryParentData, - secondaryParentData, - profileNames, - isCompare, - isMobile, -) { - const { primary_group: primaryGroup } = metadata; - - const secondaryLegend = isCompare - ? [ - { - orient: "top", - fill: "legend_secondary_scale", - labelFontWeight: "bold", - labelLimit: 400, - labelColor: "#666", - labelFont: theme.typography.fontFamily, - }, - ] - : []; - - return merge( - Scope( - primaryData, - metadata, - config, - secondaryData, - primaryParentData, - secondaryParentData, - "donut", - [ - { - type: "formula", - expr: "format(datum[datatype[Units]], numberFormat[Units]) + ' ' + datum[mainGroup]", - as: "custom_label", - }, - { - type: "pie", - field: { signal: "datatype[Units]" }, - startAngle: { signal: "startAngle" }, - endAngle: { signal: "endAngle" }, - sort: { signal: "sort" }, - }, - { - type: "collect", - sort: { field: "count", order: "descending" }, - }, - ], - ), - { - height: isMobile && isCompare && secondaryData?.length > 1 ? 380 : 180, - width: 700, - signals: [ - { - name: "height", - value: isMobile && isCompare && secondaryData?.length > 1 ? 380 : 180, - }, - { - name: "isMobile", - value: isMobile, - }, - { - name: "isCompare", - value: isCompare, - }, - { - name: "donutSize", - value: 360, - }, - ], - scales: [ - { - name: "color", - type: "ordinal", - range: "category", - domain: { - data: "primary_formatted", - field: primaryGroup, - }, - }, - { - name: "secondary", - type: "ordinal", - range: "secondary", - domain: { - data: "secondary_formatted", - field: primaryGroup, - }, - }, - { - name: "legend_primary_scale", - type: "ordinal", - domain: [isCompare ? profileNames.primary.toUpperCase() : ""], - range: [isCompare ? theme.palette.primary.main : "transparent"], - }, - { - name: "legend_secondary_scale", - type: "ordinal", - domain: [profileNames.secondary.toUpperCase()], - range: [theme.palette.secondary.main], - }, - { - name: "empty_legend", - type: "ordinal", - domain: [""], - range: ["transparent"], - }, - { - name: "legend_labels", - type: "linear", - domain: { data: "primary_formatted", field: "custom_label" }, - range: "category", - }, - ], - marks: [ - { - type: "group", - name: "primary_pie", - encode: { - update: { - x: { value: 0 }, - y: { signal: "chartY" }, - height: { - signal: - "isMobile && isCompare && data('secondary').length > 1 ? height/2: height", - }, - width: { - signal: - "isMobile && data('secondary').length > 1 ? width : width/2", - }, - }, - }, - legends: [ - { - orient: "top", - fill: "legend_primary_scale", - labelFontWeight: "bold", - labelColor: "#666", - labelFont: theme.typography.fontFamily, - }, - { - fill: "color", - stroke: "color", - orient: "none", - symbolType: "circle", - direction: "vertical", - labelFont: theme.typography.fontFamily, - legendX: { signal: "donutSize/2 + 40" }, - legendY: 40, - labelOffset: 12, - rowPadding: 8, - encode: { - labels: { - interactive: true, - update: { - fontSize: { value: 11 }, - fill: { value: theme.palette.chart.text.primary }, - limit: { - signal: - "isMobile || data('secondary').length > 1 ? '150' : '380'", - }, - }, - }, - symbols: { - enter: { - fillOpacity: { - value: 1, - }, - }, - }, - }, - }, - ], - marks: [ - { - type: "arc", - from: { data: "primary_formatted" }, - encode: { - enter: { - x: { signal: "donutSize/4" }, - y: { - signal: - "isMobile && data('secondary').length > 1 ? height /4 : height/2", - }, - }, - update: { - fill: { scale: "color", field: { signal: "mainGroup" } }, - x: { signal: "donutSize/4" }, - y: { - signal: - "isMobile && data('secondary').length > 1 ? height /4 : height/2", - }, - startAngle: { field: "startAngle" }, - endAngle: { field: "endAngle" }, - padAngle: { signal: "padAngle" }, - innerRadius: { signal: "innerRadius" }, - outerRadius: { signal: "donutSize / 4" }, - cornerRadius: { signal: "cornerRadius" }, - tooltip: { - signal: - "{'group': datum[mainGroup], 'count': format(datum[datatype[Units]], numberFormat[Units])}", - }, - }, - }, - }, - ], - }, - { - type: "group", - name: "secondary_pie", - encode: { - update: { - x: { - signal: - "!isMobile && data('secondary').length > 1 ? width / 2 + 30 : 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: - secondaryData?.length > 1 - ? [ - ...secondaryLegend, - { - fill: "secondary", - stroke: "secondary", - orient: "none", - symbolType: "circle", - direction: "vertical", - labelFont: theme.typography.fontFamily, - legendX: { signal: "donutSize / 2 + 40" }, - legendY: 40, - labelOffset: 12, - rowPadding: 8, - encode: { - labels: { - interactive: true, - update: { - fontSize: { value: 11 }, - fill: { value: theme.palette.chart.text.primary }, - }, - }, - symbols: { - enter: { - fillOpacity: { - value: 1, - }, - }, - }, - }, - }, - ] - : secondaryLegend, - marks: [ - { - type: "arc", - from: { data: "secondary_formatted" }, - encode: { - enter: { - x: { signal: "donutSize/4" }, - y: { - signal: - "isMobile && data('secondary').length > 1 ? height /4 : height/2", - }, - }, - update: { - fill: { scale: "secondary", field: primaryGroup }, - x: { signal: "donutSize/4" }, - y: { - signal: - "isMobile && data('secondary').length > 1 ? height /4 : height/2", - }, - startAngle: { field: "startAngle" }, - endAngle: { field: "endAngle" }, - padAngle: { signal: "padAngle" }, - innerRadius: { signal: "innerRadius" }, - outerRadius: { signal: "donutSize / 4 " }, - cornerRadius: { signal: "cornerRadius" }, - tooltip: { - signal: - "{'group': datum[mainGroup], 'count': format(datum[datatype[Units]], numberFormat[Units])}", - }, - }, - }, - }, - ], - }, - ], - }, - ); -} From 59dbd221cb62bd958e461f57f5fccffa85e99bcd Mon Sep 17 00:00:00 2001 From: Kevin Koech Date: Fri, 2 Aug 2024 10:53:30 +0300 Subject: [PATCH 3/3] Donut Chart --- .../HURUmap/Chart/configureScope.js | 34 +++++++------------ .../HURUmap/Chart/configureScope.js | 34 +++++++------------ 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js b/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js index 7feac6f60..8dcb06bb5 100644 --- a/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js +++ b/apps/climatemappedafrica/src/components/HURUmap/Chart/configureScope.js @@ -30,7 +30,13 @@ export default function configureScope( let vegaSpec; const chartType = configuration?.chart_type?.toLowerCase(); - const scopeOptions = [ + /** + * @deprecated Use scopeOptions for implementing new charts + * This will be completely removed once all charts scopes + * are moved to Hurumap package + */ + // eslint-disable-next-line no-underscore-dangle + const _scopeOptions = [ indicator?.data, indicator?.metadata, configuration, @@ -41,7 +47,7 @@ export default function configureScope( isCompare, isMobile, ]; - const donutScopeOptions = { + const scopeOptions = { primaryData: indicator?.data, metadata: indicator?.metadata, config: configuration, @@ -57,16 +63,16 @@ export default function configureScope( switch (chartType) { case "line": if (configuration?.stacked_field) { - vegaSpec = MultiLineChartScope(...scopeOptions); + vegaSpec = MultiLineChartScope(..._scopeOptions); } else { - vegaSpec = LineChartScope(...scopeOptions); + vegaSpec = LineChartScope(..._scopeOptions); } break; case "donut": - vegaSpec = DonutChartScope(donutScopeOptions); + vegaSpec = DonutChartScope(scopeOptions); break; case "treemap": - vegaSpec = TreemapChartScope(...scopeOptions); + vegaSpec = TreemapChartScope(..._scopeOptions); break; case "stacked": if (isMobile) { @@ -105,21 +111,7 @@ export default function configureScope( isCompare, ); } else { - const barChartArgs = { - primaryData: indicator?.data, - metadata: indicator?.metadata, - config: configuration, - secondaryData: secondaryIndicator?.data ?? null, - primaryParentData: showParent ? indicator?.parentData : [{}], - secondaryParentData: showParent - ? secondaryIndicator?.parentData - : [{}], - profileNames, - isCompare, - theme, - args: hurumapArgs, - }; - vegaSpec = BarChartScope(barChartArgs); + vegaSpec = BarChartScope(scopeOptions); } break; } diff --git a/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js b/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js index 539434ff8..5b549099d 100644 --- a/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js +++ b/apps/pesayetu/src/components/HURUmap/Chart/configureScope.js @@ -30,7 +30,13 @@ export default function configureScope( let vegaSpec; const chartType = configuration?.chart_type?.toLowerCase(); - const scopeOptions = [ + /** + * @deprecated Use scopeOptions for implementing new charts + * This will be completely removed once all charts scopes + * are moved to Hurumap package + */ + // eslint-disable-next-line no-underscore-dangle + const _scopeOptions = [ indicator?.data, indicator?.metadata, configuration, @@ -41,7 +47,7 @@ export default function configureScope( isCompare, isMobile, ]; - const donutScopeOptions = { + const scopeOptions = { primaryData: indicator?.data, metadata: indicator?.metadata, config: configuration, @@ -57,16 +63,16 @@ export default function configureScope( switch (chartType) { case "line": if (configuration?.stacked_field) { - vegaSpec = MultiLineChartScope(...scopeOptions); + vegaSpec = MultiLineChartScope(..._scopeOptions); } else { - vegaSpec = LineChartScope(...scopeOptions); + vegaSpec = LineChartScope(..._scopeOptions); } break; case "donut": - vegaSpec = DonutChartScope(donutScopeOptions); + vegaSpec = DonutChartScope(scopeOptions); break; case "treemap": - vegaSpec = TreemapChartScope(...scopeOptions); + vegaSpec = TreemapChartScope(..._scopeOptions); break; case "stacked": if (isMobile) { @@ -105,21 +111,7 @@ export default function configureScope( isCompare, ); } else { - const barChartArgs = { - primaryData: indicator?.data, - metadata: indicator?.metadata, - config: configuration, - secondaryData: secondaryIndicator?.data ?? null, - primaryParentData: showParent ? indicator?.parentData : [{}], - secondaryParentData: showParent - ? secondaryIndicator?.parentData - : [{}], - profileNames, - isCompare, - theme, - args: hurumapArgs, - }; - vegaSpec = BarChartScope(barChartArgs); + vegaSpec = BarChartScope(scopeOptions); } break; }