diff --git a/frontend/src/api/validators.ts b/frontend/src/api/validators.ts
index 842a1e5de..3b105054a 100644
--- a/frontend/src/api/validators.ts
+++ b/frontend/src/api/validators.ts
@@ -107,6 +107,7 @@ export const ledgerDataValidator = object({
payees: array(string),
precisions: record(number),
sidebar_links: array(tuple(string, string)),
+ filter_presets: array(tuple(string, string, string)),
tags: array(string),
upcoming_events_count: number,
user_queries: array(object({ name: string, query_string: string })),
diff --git a/frontend/src/sidebar/AdvancedFilterPresetLink.svelte b/frontend/src/sidebar/AdvancedFilterPresetLink.svelte
new file mode 100644
index 000000000..ffc749ba7
--- /dev/null
+++ b/frontend/src/sidebar/AdvancedFilterPresetLink.svelte
@@ -0,0 +1,51 @@
+
+
+{label}
+
+
diff --git a/frontend/src/sidebar/FilterPresets.svelte b/frontend/src/sidebar/FilterPresets.svelte
new file mode 100644
index 000000000..94979e0ea
--- /dev/null
+++ b/frontend/src/sidebar/FilterPresets.svelte
@@ -0,0 +1,57 @@
+
+
+
+
+ ๐
+
+ {#each time_presets as [_, value, label], index}
+ {#if index > 0}
+ ยท
+ {/if}
+
+ {/each}
+
+
+
+
๐
+
+ {#each advanced_presets as [_, value, label], index}
+ {#if index > 0}
+
ยท
+ {/if}
+
+ {/each}
+
+
+
+
diff --git a/frontend/src/sidebar/Header.svelte b/frontend/src/sidebar/Header.svelte
index 26759ba44..436286086 100644
--- a/frontend/src/sidebar/Header.svelte
+++ b/frontend/src/sidebar/Header.svelte
@@ -3,12 +3,14 @@
import router from "../router";
import { ledger_title, ledgerData } from "../stores";
import FilterForm from "./FilterForm.svelte";
+ import FilterPresets from "./FilterPresets.svelte";
import HeaderIcon from "./HeaderIcon.svelte";
import { has_changes } from "./page-title";
import PageTitle from "./PageTitle.svelte";
let other_ledgers = $derived($ledgerData.other_ledgers);
let has_dropdown = $derived(other_ledgers.length);
+ let has_filter_presets = $derived($ledgerData.filter_presets.length > 0);
@@ -38,6 +40,9 @@
+ {#if has_filter_presets}
+
+ {/if}
diff --git a/src/fava/core/misc.py b/src/fava/core/misc.py
index 7149a77a2..618dfac5c 100644
--- a/src/fava/core/misc.py
+++ b/src/fava/core/misc.py
@@ -40,10 +40,13 @@ def __init__(self, ledger: FavaLedger) -> None:
self.sidebar_links: SidebarLinks = []
#: Upcoming events in the next few days.
self.upcoming_events: Sequence[Event] = []
+ #: User-defined filter presets.
+ self.filter_presets: Sequence[tuple[str, str, str]] = []
def load_file(self) -> None: # noqa: D102
custom_entries = self.ledger.all_entries_by_type.Custom
self.sidebar_links = sidebar_links(custom_entries)
+ self.filter_presets = filter_presets(custom_entries)
self.upcoming_events = upcoming_events(
self.ledger.all_entries_by_type.Event,
@@ -76,6 +79,25 @@ def sidebar_links(custom_entries: Sequence[Custom]) -> SidebarLinks:
]
+def filter_presets(
+ custom_entries: Sequence[Custom],
+) -> Sequence[tuple[str, str, str]]:
+ """Parse custom entries for filter presets.
+
+ They have the following format:
+
+ 2016-04-01 custom "fava-filter-preset" "time" "month" "Current Month"
+ 2016-04-01 custom "fava-filter-preset" "advanced" "-#tag" "Exclude #tag"
+ """
+ filter_preset_entries = [
+ entry for entry in custom_entries if entry.type == "fava-filter-preset"
+ ]
+ return [
+ (entry.values[0].value, entry.values[1].value, entry.values[2].value)
+ for entry in filter_preset_entries
+ ]
+
+
def upcoming_events(
events: Sequence[Event], max_delta: int
) -> Sequence[Event]:
diff --git a/src/fava/internal_api.py b/src/fava/internal_api.py
index b9a5a055c..7a8f1e237 100644
--- a/src/fava/internal_api.py
+++ b/src/fava/internal_api.py
@@ -75,6 +75,7 @@ class LedgerData:
extensions: Sequence[ExtensionDetails]
sidebar_links: Sequence[tuple[str, str]]
other_ledgers: Sequence[tuple[str, str]]
+ filter_presets: Sequence[tuple[str, str, str]]
def get_errors() -> list[SerialisedError]:
@@ -128,6 +129,7 @@ def get_ledger_data() -> LedgerData:
for (file_slug, ledger) in current_app.config["LEDGERS"].items()
if file_slug != g.beancount_file_slug
],
+ ledger.misc.filter_presets,
)
diff --git a/tests/__snapshots__/test_application-test_client_side_reports b/tests/__snapshots__/test_application-test_client_side_reports
index 9b736cf58..624c8f667 100644
--- a/tests/__snapshots__/test_application-test_client_side_reports
+++ b/tests/__snapshots__/test_application-test_client_side_reports
@@ -936,6 +936,7 @@
"uptodate_indicator_grey_lookback_days": 60,
"use_external_editor": false
},
+ "filter_presets": [],
"have_excel": true,
"incognito": false,
"links": [
diff --git a/tests/__snapshots__/test_internal_api-test_get_ledger_data.json b/tests/__snapshots__/test_internal_api-test_get_ledger_data.json
index 39dc71d69..5facdd68e 100644
--- a/tests/__snapshots__/test_internal_api-test_get_ledger_data.json
+++ b/tests/__snapshots__/test_internal_api-test_get_ledger_data.json
@@ -924,6 +924,7 @@
"uptodate_indicator_grey_lookback_days": 60,
"use_external_editor": false
},
+ "filter_presets": [],
"have_excel": true,
"incognito": false,
"links": [