diff --git a/src/app/components/charts/sankey/data.ts b/src/app/components/charts/sankey/data.ts index fe76a1f15..fbf3e0da6 100644 --- a/src/app/components/charts/sankey/data.ts +++ b/src/app/components/charts/sankey/data.ts @@ -19,6 +19,7 @@ export interface SankeyChartData { export interface SankeyChartProps { data: SankeyChartData; + formatLabel?: boolean; } export interface SankeyChartTooltipProps extends SankeyChartNode { diff --git a/src/app/components/charts/sankey/index.tsx b/src/app/components/charts/sankey/index.tsx index 8e2ce24d9..2678bdfa6 100644 --- a/src/app/components/charts/sankey/index.tsx +++ b/src/app/components/charts/sankey/index.tsx @@ -1,4 +1,5 @@ import React from "react"; +import sumBy from "lodash/sumBy"; import Box from "@mui/material/Box"; import { appColors } from "app/theme"; import * as echarts from "echarts/core"; @@ -15,6 +16,10 @@ import { SankeySeriesOption, SankeyChart as EChartsSankey, } from "echarts/charts"; +import { + getFinancialValueWithMetricPrefix, + getRange, +} from "app/utils/getFinancialValueWithMetricPrefix"; echarts.use([TooltipComponent, EChartsSankey, SVGRenderer]); @@ -35,7 +40,7 @@ export const SankeyChart: React.FC = ( const totalValue = React.useMemo(() => { return props.data.links - .filter((link) => link.source === "Total budget") + .filter((link) => link.source.includes("Total")) .reduce((acc, item) => acc + item.value, 0); }, [props.data.links]); @@ -49,6 +54,8 @@ export const SankeyChart: React.FC = ( renderer: "svg", }); + const maxLevel = Math.max(...props.data.nodes.map((node) => node.level)); + const option: echarts.ComposeOption< SankeySeriesOption | TooltipComponentOption > = { @@ -61,7 +68,7 @@ export const SankeyChart: React.FC = ( type: "sankey", draggable: false, layoutIterations: 0, - right: mobile ? 0 : 250, + right: mobile || maxLevel === 2 ? 0 : 250, nodes: props.data.nodes, links: props.data.links, emphasis: { @@ -88,6 +95,30 @@ export const SankeyChart: React.FC = ( position: "right", fontWeight: "bold", color: appColors.COMMON.WHITE, + formatter: (params: any) => { + const range = getRange([{ value: params.value }], ["value"]); + return props.formatLabel + ? [ + `{name|${params.name}: }`, + `{value|US$ ${getFinancialValueWithMetricPrefix( + params.value, + range.index, + 3 + )}${range.abbr}}`, + ].join("\n") + : params.name; + }, + rich: { + name: { + fontSize: 12, + fontWeight: "bold", + color: appColors.COMMON.WHITE, + }, + value: { + fontSize: 12, + color: appColors.COMMON.WHITE, + }, + }, }, lineStyle: { color: @@ -103,6 +134,40 @@ export const SankeyChart: React.FC = ( show: !mobile, position: "left", color: appColors.COMMON.WHITE, + formatter: (params: any) => { + const range = getRange([{ value: params.value }], ["value"]); + return props.formatLabel + ? [ + `{name|${params.name}: }`, + `{value|US$ ${getFinancialValueWithMetricPrefix( + params.value, + range.index, + 3 + )}${range.abbr}}`, + `\n`, + `{perc|${((params.value / totalValue) * 100) + .toFixed(2) + .replace(".00", "")}% of total}`, + ].join("") + : params.name; + }, + rich: { + name: { + fontSize: 12, + fontWeight: "bold", + color: appColors.COMMON.WHITE, + }, + value: { + fontSize: 12, + color: appColors.COMMON.WHITE, + }, + perc: { + fontSize: 10, + align: "right", + padding: [5, 0, 0, 0], + color: appColors.COMMON.WHITE, + }, + }, }, lineStyle: { color: @@ -112,8 +177,32 @@ export const SankeyChart: React.FC = ( { depth: 2, label: { - position: "right", color: appColors.COMMON.BLACK, + position: maxLevel === 2 ? "left" : "right", + formatter: (params: any) => { + const range = getRange([{ value: params.value }], ["value"]); + return props.formatLabel + ? [ + `{name|${params.name}: }`, + `{value|US$ ${getFinancialValueWithMetricPrefix( + params.value, + range.index, + 3 + )}${range.abbr}}`, + ].join("") + : params.name; + }, + rich: { + name: { + fontSize: 12, + fontWeight: "bold", + color: appColors.COMMON.BLACK, + }, + value: { + fontSize: 12, + color: appColors.COMMON.BLACK, + }, + }, }, lineStyle: { color: appColors.SANKEY_CHART.LINK_COLORS[2], @@ -151,6 +240,10 @@ export const SankeyChart: React.FC = ( formatter: (params: any) => { const data = params.data; if (data.source && data.target) { + const sourceTotal = sumBy( + props.data.links.filter((node) => node.source === data.source), + "value" + ); return ReactDOMServer.renderToString( = ( {formatFinancialValue(data.value)} - {data.source} -{">"} {data.target} -
- {((data.value / totalValue) * 100) + {data.target} -{" "} + {((data.value / sourceTotal) * 100) .toFixed(2) .replace(".00", "")} - % of total budget + % of {data.source}
); diff --git a/src/app/components/table/data.ts b/src/app/components/table/data.ts index dc1c4e931..ffc977ae2 100644 --- a/src/app/components/table/data.ts +++ b/src/app/components/table/data.ts @@ -7891,3 +7891,18 @@ export const TABLE_VARIATION_15_DATA: { ], }, ]; + +export const TABLE_VARIATION_16_COLUMNS: ColumnDefinition[] = [ + { + title: "Disbursement Area", + field: "name", + width: "50%", + formatter: cellBGColorFormatter, + }, + { + title: "Amount (US$)", + field: "amount", + width: "50%", + formatter: financialFormatter, + }, +]; diff --git a/src/app/pages/datasets/common/chart-block/data.ts b/src/app/pages/datasets/common/chart-block/data.ts index 78b2fffda..d4a499ce5 100644 --- a/src/app/pages/datasets/common/chart-block/data.ts +++ b/src/app/pages/datasets/common/chart-block/data.ts @@ -21,5 +21,7 @@ export interface DatasetChartBlockProps { handleDropdownChange?: (value: string) => void; removeFilter: (value: string, types: string[]) => void; toggleFilter: (checked: boolean, value: string, type: string) => void; + titleVariant?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "body1" | "body2"; dropdownItems: { value: string; label: string; icon?: React.ReactElement }[]; + subtitleVariant?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "body1" | "body2"; } diff --git a/src/app/pages/datasets/common/chart-block/index.tsx b/src/app/pages/datasets/common/chart-block/index.tsx index 468923277..c116edc6c 100644 --- a/src/app/pages/datasets/common/chart-block/index.tsx +++ b/src/app/pages/datasets/common/chart-block/index.tsx @@ -119,10 +119,12 @@ export const DatasetChartBlock: React.FC = ( return ( - + {props.title} - {props.subtitle} + + {props.subtitle} + = ( }} > - + {props.filterGroups.length > 0 && ( + + )} {filterPopover} {/*