From 51f42feca33268254ace1bdd8b9a978880c97c5c Mon Sep 17 00:00:00 2001 From: Max R Date: Fri, 22 May 2026 12:39:12 -0400 Subject: [PATCH 1/3] add labls --- manager_for_ynab/sankey/__init__.py | 26 +++++++++++++++++++++++--- tests/sankey/test.py | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/manager_for_ynab/sankey/__init__.py b/manager_for_ynab/sankey/__init__.py index 38b9106..378f14d 100644 --- a/manager_for_ynab/sankey/__init__.py +++ b/manager_for_ynab/sankey/__init__.py @@ -31,13 +31,19 @@ _LABEL_FORMATTER = "function(params) { return params.data.label; }" _TOOLTIP_FORMATTER = """ function(params) { + const amount = Number(params.data.amount).toLocaleString(undefined, { style: 'currency', currency: 'USD' }); + if (params.dataType === 'edge') { const source = params.data.source_label; const target = params.data.target_label; - const amount = Number(params.data.amount).toLocaleString(undefined, { style: 'currency', currency: 'USD' }); return `${source} → ${target}: ${amount}`; } + + if (params.data.amount != null) { + return `${params.data.label}: ${amount}`; + } + return params.data.label; } """ @@ -351,6 +357,18 @@ def sorted_categories(group: SankeyNode) -> list[SankeyNode]: def build_echarts_html(data: SankeyData, *, start: date, end: date) -> str: min_link_value = max(float(value) for value in data.values) * _MIN_LINK_VALUE_RATIO + + node_amounts = [Decimal(0) for _ in data.keys] + for source, target, value in zip( + data.sources, data.targets, data.values, strict=True + ): + node_amounts[target] += value + if node_amounts[source] == 0: + node_amounts[source] = value + + def build_node(index: int, key: str, label: str) -> dict[str, float | str]: + return {"name": key, "label": label, "amount": float(node_amounts[index])} + return ( charts.Sankey( init_opts=options.InitOpts(width="100%", height=f"{_MIN_FIGURE_HEIGHT}px") @@ -358,8 +376,10 @@ def build_echarts_html(data: SankeyData, *, start: date, end: date) -> str: .add( "", nodes=[ - {"name": key, "label": label} - for key, label in zip(data.keys, data.labels, strict=True) + build_node(index, key, label) + for index, (key, label) in enumerate( + zip(data.keys, data.labels, strict=True) + ) ], links=[ { diff --git a/tests/sankey/test.py b/tests/sankey/test.py index f04945f..056f092 100644 --- a/tests/sankey/test.py +++ b/tests/sankey/test.py @@ -400,6 +400,26 @@ def test_build_echarts_html_uses_node_keys_and_labels(): assert "params.data.target_label" in html assert "params.data.amount" in html assert "currency: 'USD'" in html + assert ( + '"name": "income:Employer",\n "label": "Employer",\n "amount": 500.0' + in html + ) + assert ( + '"name": "ready_to_assign",\n "label": "Ready to Assign",\n "amount": 500.0' + in html + ) + assert ( + '"name": "income",\n "label": "Income",\n "amount": 500.0' + in html + ) + assert ( + '"name": "category_group:taxes-group",\n "label": "Taxes",\n "amount": 120.0' + in html + ) + assert ( + '"name": "category:taxes-category",\n "label": "Taxes",\n "amount": 120.0' + in html + ) assert "height:1000px" in html assert "layoutIterations" in html From f6915b164d929ff8b99e47e6a3d553435a14e0bf Mon Sep 17 00:00:00 2001 From: Max R Date: Fri, 22 May 2026 12:43:27 -0400 Subject: [PATCH 2/3] cleanup --- manager_for_ynab/sankey/__init__.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/manager_for_ynab/sankey/__init__.py b/manager_for_ynab/sankey/__init__.py index 378f14d..cb51aad 100644 --- a/manager_for_ynab/sankey/__init__.py +++ b/manager_for_ynab/sankey/__init__.py @@ -358,7 +358,7 @@ def sorted_categories(group: SankeyNode) -> list[SankeyNode]: def build_echarts_html(data: SankeyData, *, start: date, end: date) -> str: min_link_value = max(float(value) for value in data.values) * _MIN_LINK_VALUE_RATIO - node_amounts = [Decimal(0) for _ in data.keys] + node_amounts: dict[int, Decimal] = defaultdict(Decimal) for source, target, value in zip( data.sources, data.targets, data.values, strict=True ): @@ -366,9 +366,6 @@ def build_echarts_html(data: SankeyData, *, start: date, end: date) -> str: if node_amounts[source] == 0: node_amounts[source] = value - def build_node(index: int, key: str, label: str) -> dict[str, float | str]: - return {"name": key, "label": label, "amount": float(node_amounts[index])} - return ( charts.Sankey( init_opts=options.InitOpts(width="100%", height=f"{_MIN_FIGURE_HEIGHT}px") @@ -376,7 +373,7 @@ def build_node(index: int, key: str, label: str) -> dict[str, float | str]: .add( "", nodes=[ - build_node(index, key, label) + {"name": key, "label": label, "amount": float(node_amounts[index])} for index, (key, label) in enumerate( zip(data.keys, data.labels, strict=True) ) From 36bc394b5f5eb9c798e122b6c590f94264418b58 Mon Sep 17 00:00:00 2001 From: Max R Date: Fri, 22 May 2026 12:44:11 -0400 Subject: [PATCH 3/3] cleanup --- manager_for_ynab/sankey/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/manager_for_ynab/sankey/__init__.py b/manager_for_ynab/sankey/__init__.py index cb51aad..7f3b79f 100644 --- a/manager_for_ynab/sankey/__init__.py +++ b/manager_for_ynab/sankey/__init__.py @@ -358,13 +358,13 @@ def sorted_categories(group: SankeyNode) -> list[SankeyNode]: def build_echarts_html(data: SankeyData, *, start: date, end: date) -> str: min_link_value = max(float(value) for value in data.values) * _MIN_LINK_VALUE_RATIO - node_amounts: dict[int, Decimal] = defaultdict(Decimal) + amounts: dict[int, Decimal] = defaultdict(Decimal) for source, target, value in zip( data.sources, data.targets, data.values, strict=True ): - node_amounts[target] += value - if node_amounts[source] == 0: - node_amounts[source] = value + amounts[target] += value + if amounts[source] == 0: + amounts[source] = value return ( charts.Sankey( @@ -373,8 +373,8 @@ def build_echarts_html(data: SankeyData, *, start: date, end: date) -> str: .add( "", nodes=[ - {"name": key, "label": label, "amount": float(node_amounts[index])} - for index, (key, label) in enumerate( + {"name": key, "label": label, "amount": float(amounts[i])} + for i, (key, label) in enumerate( zip(data.keys, data.labels, strict=True) ) ],