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

fmt #93

Merged
merged 1 commit into from
Jan 26, 2025
Merged

fmt #93

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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ max_line_length = 120
indent_size = 2

[*.ts]
indent_size = 4
indent_size = 2

[Makefile]
indent_style = tab
46 changes: 23 additions & 23 deletions frontend/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,34 @@ 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);
}
// 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, helpers, panel };
Panels[panel.type](ctx, elem);
// 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, helpers, panel };
Panels[panel.type](ctx, elem);
}
}

export default {
onExtensionPageLoad(ext: any) {
const boostrapJSON = (document.querySelector("#favaDashboardsBootstrap") as HTMLScriptElement)?.text;
if (!boostrapJSON) return;
onExtensionPageLoad(ext: any) {
const boostrapJSON = (document.querySelector("#favaDashboardsBootstrap") as HTMLScriptElement)?.text;
if (!boostrapJSON) return;

const bootstrap: Bootstrap = JSON.parse(boostrapJSON);
const utils: Utils = new Function(bootstrap.utils)();
renderDashboard(ext, bootstrap.dashboard, bootstrap.ledger, utils);
},
const bootstrap: Bootstrap = JSON.parse(boostrapJSON);
const utils: Utils = new Function(bootstrap.utils)();
renderDashboard(ext, bootstrap.dashboard, bootstrap.ledger, utils);
},
};
110 changes: 52 additions & 58 deletions frontend/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,75 @@
* @deprecated
*/
export const iterateMonths = (dateFirst: string, dateLast: string) => {
console.warn(
"helpers.iterateMonths() is deprecated, please define this function in utils.inline in dashboards.yaml",
);
console.warn("helpers.iterateMonths() is deprecated, please define this function in utils.inline in dashboards.yaml");

const months: { year: number; month: number }[] = [];
let [year, month] = dateFirst.split("-").map((x) => parseInt(x));
let [lastYear, lastMonth] = dateLast.split("-").map((x) => parseInt(x));
const months: { year: number; month: number }[] = [];
let [year, month] = dateFirst.split("-").map((x) => parseInt(x));
let [lastYear, lastMonth] = dateLast.split("-").map((x) => parseInt(x));

while (year < lastYear || (year === lastYear && month <= lastMonth)) {
months.push({ year, month });
if (month == 12) {
year++;
month = 1;
} else {
month++;
}
while (year < lastYear || (year === lastYear && month <= lastMonth)) {
months.push({ year, month });
if (month == 12) {
year++;
month = 1;
} else {
month++;
}
return months;
}
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",
);
console.warn("helpers.iterateMonths() is deprecated, please define this function in utils.inline in dashboards.yaml");

const years: number[] = [];
let year = parseInt(dateFirst.split("-")[0]);
let lastYear = parseInt(dateLast.split("-")[0]);
const years: number[] = [];
let year = parseInt(dateFirst.split("-")[0]);
let lastYear = parseInt(dateLast.split("-")[0]);

for (; year <= lastYear; year++) {
years.push(year);
}
return years;
for (; year <= lastYear; year++) {
years.push(year);
}
return years;
};

interface AccountTreeNode {
name: string;
children: AccountTreeNode[];
value: number;
name: string;
children: AccountTreeNode[];
value: number;
}

/**
* @deprecated
*/
export const buildAccountTree = (
rows: any[],
valueFn: (row: any) => number,
nameFn: (parts: string[], i: number) => string,
rows: any[],
valueFn: (row: any) => number,
nameFn: (parts: string[], i: number) => string,
) => {
console.warn(
"helpers.iterateMonths() is deprecated, please define this function in utils.inline in dashboards.yaml",
);
console.warn("helpers.iterateMonths() is deprecated, please define this function in utils.inline in dashboards.yaml");

nameFn = nameFn ?? ((parts: string[], i: number) => parts.slice(0, i + 1).join(":"));
nameFn = nameFn ?? ((parts: string[], i: number) => parts.slice(0, i + 1).join(":"));

const accountTree: { children: AccountTreeNode[] } = { children: [] };
for (let row of rows) {
const accountParts = row.account.split(":");
let node = accountTree;
for (let i = 0; i < accountParts.length; i++) {
const account = nameFn(accountParts, i);
let child = node.children.find((c) => c.name == account);
if (!child) {
child = { name: account, children: [], value: 0 };
node.children.push(child);
}
const accountTree: { children: AccountTreeNode[] } = { children: [] };
for (let row of rows) {
const accountParts = row.account.split(":");
let node = accountTree;
for (let i = 0; i < accountParts.length; i++) {
const account = nameFn(accountParts, i);
let child = node.children.find((c) => c.name == account);
if (!child) {
child = { name: account, children: [], value: 0 };
node.children.push(child);
}

child.value += valueFn(row);
node = child;
}
child.value += valueFn(row);
node = child;
}
return accountTree;
}
return accountTree;
};

// https://github.com/beancount/fava/blob/fb59849ccd4535f808d295594e6db7d8a5d249a6/frontend/src/stores/url.ts#L5-L12
Expand All @@ -86,16 +80,16 @@ const urlSyncedParams = ["account", "charts", "conversion", "filter", "interval"
* add current Fava filter parameters to url
*/
export const urlFor = (url: string) => {
url = url.replaceAll("#", "%23");
url = url.replaceAll("#", "%23");

const currentURL = new URL(window.location.href);
const newURL = new URL(url, window.location.href);
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)!);
}
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();
return newURL.toString();
};
108 changes: 54 additions & 54 deletions frontend/src/panels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,75 +3,75 @@ import { render_d3sankey } from "./sankey";
import { PanelCtx } from "./types";

function runFunction(src: string, args: Record<string, any>): Promise<any> {
const AsyncFunction = async function () {}.constructor;
const params = Object.entries(args);
const fn = AsyncFunction(
params.map(([k, _]) => k),
src,
);
return fn(...params.map(([_, v]) => v));
const AsyncFunction = async function () {}.constructor;
const params = Object.entries(args);
const fn = AsyncFunction(
params.map(([k, _]) => k),
src,
);
return fn(...params.map(([_, v]) => v));
}

function runScript(ctx: PanelCtx) {
return runFunction(ctx.panel.script!, {
...ctx,
// pass 'fava' for backwards compatibility
fava: ctx.ledger,
});
return runFunction(ctx.panel.script!, {
...ctx,
// pass 'fava' for backwards compatibility
fava: ctx.ledger,
});
}

export async function html(ctx: PanelCtx, elem: HTMLDivElement) {
try {
elem.innerHTML = await runScript(ctx);
} catch (e: any) {
elem.innerHTML = e;
}
try {
elem.innerHTML = await runScript(ctx);
} catch (e: any) {
elem.innerHTML = e;
}
}

export async function echarts(ctx: PanelCtx, elem: HTMLDivElement) {
let options: echartslib.EChartsOption;
try {
options = await runScript(ctx);
} catch (e: any) {
elem.innerHTML = e;
return;
}
let options: echartslib.EChartsOption;
try {
options = await runScript(ctx);
} catch (e: any) {
elem.innerHTML = e;
return;
}

// use SVG renderer during HTML e2e tests, to compare snapshots
const renderer = window.navigator.userAgent === "puppeteer-html" ? "svg" : undefined;
const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
const theme = isDarkMode ? "dark" : undefined;
const chart = echartslib.init(elem, theme, { renderer });
if (options.onClick) {
chart.on("click", (options as any).onClick);
delete options.onClick;
}
if (options.onDblClick) {
chart.on("dblclick", (options as any).onDblClick);
delete options.onDblClick;
}
if (theme === "dark" && options.backgroundColor === undefined) {
options.backgroundColor = "transparent";
}
if (window.navigator.userAgent.includes("puppeteer")) {
// disable animations during e2e tests
options.animation = false;
}
chart.setOption(options);
// use SVG renderer during HTML e2e tests, to compare snapshots
const renderer = window.navigator.userAgent === "puppeteer-html" ? "svg" : undefined;
const isDarkMode = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
const theme = isDarkMode ? "dark" : undefined;
const chart = echartslib.init(elem, theme, { renderer });
if (options.onClick) {
chart.on("click", (options as any).onClick);
delete options.onClick;
}
if (options.onDblClick) {
chart.on("dblclick", (options as any).onDblClick);
delete options.onDblClick;
}
if (theme === "dark" && options.backgroundColor === undefined) {
options.backgroundColor = "transparent";
}
if (window.navigator.userAgent.includes("puppeteer")) {
// disable animations during e2e tests
options.animation = false;
}
chart.setOption(options);
}

export async function d3_sankey(ctx: PanelCtx, elem: HTMLDivElement) {
let options: any;
try {
options = await runScript(ctx);
} catch (e: any) {
elem.innerHTML = e;
return;
}
let options: any;
try {
options = await runScript(ctx);
} catch (e: any) {
elem.innerHTML = e;
return;
}

render_d3sankey(elem, options);
render_d3sankey(elem, options);
}

export async function jinja2(ctx: PanelCtx, elem: HTMLDivElement) {
elem.innerHTML = ctx.panel.template ?? "";
elem.innerHTML = ctx.panel.template ?? "";
}
Loading
Loading