mirror of
https://github.com/we-promise/sure.git
synced 2026-07-12 04:45:19 +00:00
feat(cashflow): deep-link category labels to filtered transactions (#2083)
* feat(cashflow): deep-link category labels to filtered transactions Clicking a category's text label in the dashboard cashflow Sankey chart now navigates to the transactions page filtered by that category and the cashflow's active period date range. The colored node bar keeps its existing zoom-into-subcategories behavior; structural nodes (Cash Flow, Surplus) do not navigate. URL-building lives in a pure, unit-tested utils/transactions_filter_url module (mirroring utils/sankey_zoom) pinned in the importmap. Period dates are threaded from the dashboard view into the Stimulus controller via data values. This matches the existing donut chart's click-to-filter behavior. * Update app/javascript/controllers/sankey_chart_controller.js Co-authored-by: Guillem Arias Fauste <gariasf@proton.me> Signed-off-by: Will Wilson <will@willwilson.uk> --------- Signed-off-by: Will Wilson <will@willwilson.uk> Co-authored-by: Guillem Arias Fauste <gariasf@proton.me>
This commit is contained in:
@@ -3,6 +3,10 @@ import * as d3 from "d3";
|
||||
import { sankey } from "d3-sankey";
|
||||
import { CHART_TOOLTIP_CLASSES } from "utils/chart_tooltip";
|
||||
import { sankeyNodeHasChildren, zoomSankeyData } from "utils/sankey_zoom";
|
||||
import {
|
||||
buildCategoryTransactionsUrl,
|
||||
isNavigableCategoryNode,
|
||||
} from "utils/transactions_filter_url";
|
||||
|
||||
// Connects to data-controller="sankey-chart"
|
||||
export default class extends Controller {
|
||||
@@ -13,6 +17,8 @@ export default class extends Controller {
|
||||
nodeWidth: { type: Number, default: 15 },
|
||||
nodePadding: { type: Number, default: 20 },
|
||||
currencySymbol: { type: String, default: "$" },
|
||||
startDate: String,
|
||||
endDate: String,
|
||||
};
|
||||
|
||||
// Visual constants
|
||||
@@ -163,6 +169,22 @@ export default class extends Controller {
|
||||
this.#draw({ animate: true });
|
||||
}
|
||||
|
||||
#navigateToTransactions(d) {
|
||||
if (!isNavigableCategoryNode(d.id)) {
|
||||
// Structural node (Cash Flow / Surplus): keep current zoom behavior.
|
||||
this.#zoomIn(d);
|
||||
return;
|
||||
}
|
||||
|
||||
Turbo.visit(
|
||||
buildCategoryTransactionsUrl({
|
||||
name: d.name,
|
||||
startDate: this.startDateValue,
|
||||
endDate: this.endDateValue,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// Dynamic padding prevents padding from dominating when there are many nodes
|
||||
#calculateNodePadding(nodeCount, height) {
|
||||
const margin = this.constructor.EXTENT_MARGIN;
|
||||
@@ -495,6 +517,7 @@ export default class extends Controller {
|
||||
nodeGroups
|
||||
.selectAll("text")
|
||||
.style("cursor", (d) =>
|
||||
isNavigableCategoryNode(d.id) ||
|
||||
sankeyNodeHasChildren(this.#visibleData(), d.id)
|
||||
? "pointer"
|
||||
: "default",
|
||||
@@ -514,7 +537,7 @@ export default class extends Controller {
|
||||
.on("mousemove", (event) => this.#updateTooltipPosition(event))
|
||||
.on("click", (event, d) => {
|
||||
event.stopPropagation();
|
||||
this.#zoomIn(d);
|
||||
this.#navigateToTransactions(d);
|
||||
})
|
||||
.on("mouseleave", () => {
|
||||
resetHover();
|
||||
|
||||
Reference in New Issue
Block a user