Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

persist fava filters in urls #41

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ The following variables and functions are available:
* `ledger.ccy`: shortcut for the first configured operating currency of the ledger
* `ledger.accounts`: declared accounts of the ledger
* `ledger.commodities`: declared commodities of the ledger
* `helpers.urlFor(url)`: add current Fava filter parameters to url
* `utils`: the return value of the `utils` code of the dashboard configuration

**Jinja2 panels:**
Expand Down
49 changes: 24 additions & 25 deletions example/dashboards.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,8 @@ dashboards:
const query = panel.queries.find((q) => q.name === event.seriesName);
if (query) {
const [month, year] = event.name.split("/");
const link = query.link.replaceAll("#", "%23").replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(link);
const link = query.link.replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(helpers.urlFor(link));
}
},
};
Expand Down Expand Up @@ -223,8 +223,8 @@ dashboards:
],
onClick: (event) => {
const [month, year] = event.name.split("/");
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(link);
const link = panel.queries[0].link.replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -290,8 +290,8 @@ dashboards:
],
onClick: (event) => {
const [month, year] = event.name.split("/");
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(link);
const link = panel.queries[0].link.replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -584,8 +584,8 @@ dashboards:
[clickEvt]: (event) => {
const account = "Income" + event.treePathInfo.map((i) => i.name).join(":");
const time = new URLSearchParams(window.location.search).get("time") ?? "";
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{account}", account).replace("{time}", time);
window.open(link);
const link = panel.queries[0].link.replace("{account}", account).replace("{time}", time);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -633,14 +633,14 @@ dashboards:
[clickEvt]: (event) => {
const account = "Expenses" + event.treePathInfo.map((i) => i.name).join(":");
const time = new URLSearchParams(window.location.search).get("time") ?? "";
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{account}", account).replace("{time}", time);
window.open(link);
const link = panel.queries[0].link.replace("{account}", account).replace("{time}", time);
window.open(helpers.urlFor(link));
},
};

- title: Recurring, Regular and Irregular Expenses 🔁
width: 50%
link: /beancount/income_statement/?filter=#recurring
link: /beancount/income_statement/
queries:
- name: Recurring
bql: |
Expand Down Expand Up @@ -703,8 +703,8 @@ dashboards:
const query = panel.queries.find((q) => q.name === event.seriesName);
if (query) {
const [month, year] = event.name.split("/");
const link = query.link.replaceAll("#", "%23").replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(link);
const link = query.link.replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(helpers.urlFor(link));
}
},
};
Expand Down Expand Up @@ -754,8 +754,8 @@ dashboards:
],
onClick: (event) => {
const [month, year] = event.name.split("/");
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(link);
const link = panel.queries[0].link.replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -825,10 +825,9 @@ dashboards:
})),
onClick: (event) => {
const link = panel.queries[0].link
.replaceAll("#", "%23")
.replace("{account}", accounts[event.dataIndex])
.replace("{time}", event.seriesName);
window.open(link);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -898,8 +897,8 @@ dashboards:
},
],
onClick: (event) => {
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{time}", event.name);
window.open(link);
const link = panel.queries[0].link.replace("{time}", event.name);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -961,8 +960,8 @@ dashboards:
},
],
onClick: (event) => {
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{travel}", event.name);
window.open(link);
const link = panel.queries[0].link.replace("{travel}", event.name);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -1040,8 +1039,8 @@ dashboards:
onClick: (event, node) => {
if (node.name === "Savings") return;
const time = new URLSearchParams(window.location.search).get("time") ?? "";
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{account}", node.name).replace("{time}", time);
window.open(link);
const link = panel.queries[0].link.replace("{account}", node.name).replace("{time}", time);
window.open(helpers.urlFor(link));
},
};

Expand Down Expand Up @@ -1152,8 +1151,8 @@ dashboards:
onClick: (event) => {
if (event.seriesName === "Projection") return;
const [month, year] = event.name.split("/");
const link = panel.queries[0].link.replaceAll("#", "%23").replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(link);
const link = panel.queries[0].link.replace("{time}", `${year}-${month.padStart(2, "0")}`);
window.open(helpers.urlFor(link));
},
};

Expand Down
13 changes: 12 additions & 1 deletion frontend/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import { Bootstrap, Dashboard, Ledger, Utils } from "./types";
import * as Panels from "./panels";
import * as helpers from "./helpers";
import { urlFor } from "./helpers";

function renderDashboard(ext: any, dashboard: Dashboard, ledger: Ledger, utils: Utils) {
// add Fava filter parameters to panel links
for (const elem of document.querySelectorAll(".panel a")) {
const link = elem as HTMLAnchorElement;
if (!link.getAttribute("href").includes("://")) {
link.href = urlFor(link.href);
}
}

// render panel
for (let i = 0; i < dashboard.panels.length; i++) {
const panel = dashboard.panels[i];
if (!panel.type || !(panel.type in Panels)) {
continue;
}

const elem = document.getElementById(`panel${i}`) as HTMLDivElement;
const ctx = { ext, ledger, utils, panel };
const ctx = { ext, ledger, utils, helpers, panel };
Panels[panel.type](ctx, elem);
}
}
Expand Down
30 changes: 30 additions & 0 deletions frontend/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/**
* @deprecated
*/
export const iterateMonths = (dateFirst: string, dateLast: string) => {
console.warn(
"helpers.iterateMonths() is deprecated, please define this function in utils.inline in dashboards.yaml",
Expand All @@ -19,6 +22,9 @@ export const iterateMonths = (dateFirst: string, dateLast: string) => {
return months;
};

/**
* @deprecated
*/
export const iterateYears = (dateFirst: string, dateLast: string) => {
console.warn(
"helpers.iterateMonths() is deprecated, please define this function in utils.inline in dashboards.yaml",
Expand All @@ -40,6 +46,9 @@ interface AccountTreeNode {
value: number;
}

/**
* @deprecated
*/
export const buildAccountTree = (
rows: any[],
valueFn: (row: any) => number,
Expand Down Expand Up @@ -69,3 +78,24 @@ export const buildAccountTree = (
}
return accountTree;
};

// https://github.com/beancount/fava/blob/fb59849ccd4535f808d295594e6db7d8a5d249a6/frontend/src/stores/url.ts#L5-L12
const urlSyncedParams = ["account", "charts", "conversion", "filter", "interval", "time"];

/**
* add current Fava filter parameters to url
*/
export const urlFor = (url: string) => {
url = url.replaceAll("#", "%23");

const currentURL = new URL(window.location.href);
const newURL = new URL(url, window.location.href);

for (const param of urlSyncedParams) {
if (currentURL.searchParams.has(param) && !newURL.searchParams.has(param)) {
newURL.searchParams.set(param, currentURL.searchParams.get(param)!);
}
}

return newURL.toString();
};
4 changes: 1 addition & 3 deletions frontend/src/panels.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as echartslib from "echarts";
import * as helpers from "./helpers";
import { render_d3sankey } from "./sankey";
import { PanelCtx } from "./types";

Expand All @@ -16,9 +15,8 @@ function runFunction(src: string, args: Record<string, any>): Promise<any> {
function runScript(ctx: PanelCtx) {
return runFunction(ctx.panel.script!, {
...ctx,
// pass 'fava' and 'helpers' for backwards compatibility
// pass 'fava' for backwards compatibility
fava: ctx.ledger,
helpers,
});
}

Expand Down
25 changes: 15 additions & 10 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as helpers from "./helpers";

export interface Bootstrap {
dashboard: Dashboard;
ledger: Ledger;
Expand All @@ -10,16 +12,19 @@ export interface Dashboard {
}

export interface PanelCtx {
// Fava [`ExtensionContext`](https://github.com/beancount/fava/blob/main/frontend/src/extensions.ts)
/** Fava [`ExtensionContext`](https://github.com/beancount/fava/blob/main/frontend/src/extensions.ts) */
ext: any;

// metadata of the Beancount ledger
/** metadata of the Beancount ledger */
ledger: Ledger;

// return value of the `utils` code of the dashboard configuration
/** various helper functions */
helpers: typeof helpers;

/** return value of the `utils` code of the dashboard configuration */
utils: Utils;

// current (augmented) panel definition. The results of the BQL queries can be accessed with `panel.queries[i].result`.
/** current (augmented) panel definition. The results of the BQL queries can be accessed with `panel.queries[i].result`. */
panel: Panel;
}

Expand All @@ -33,22 +38,22 @@ interface Panel {
}

export interface Ledger {
// first date in the current date filter
/** first date in the current date filter */
dateFirst: string;

// last date in the current date filter
/** last date in the current date filter */
dateLast: string;

// configured operating currencies of the ledger
/** configured operating currencies of the ledger */
operatingCurrencies: string[];

// shortcut for the first configured operating currency of the ledger
/** shortcut for the first configured operating currency of the ledger */
ccy: string;

// declared accounts of the ledger
/** declared accounts of the ledger */
accounts: any[];

// declared commodities of the ledger
/** declared commodities of the ledger */
commodities: any[];
}

Expand Down
Loading
Loading