From 0409677110910ad0191f9d3c2ba4cd211f598fac Mon Sep 17 00:00:00 2001 From: Vasily Medyanikov Date: Fri, 25 Apr 2025 14:48:33 +0200 Subject: [PATCH] Feature: filter presets --- frontend/src/api/validators.ts | 1 + .../sidebar/AdvancedFilterPresetLink.svelte | 51 +++++++++++++++++ frontend/src/sidebar/FilterPresets.svelte | 57 +++++++++++++++++++ frontend/src/sidebar/Header.svelte | 5 ++ .../src/sidebar/TimeFilterPresetLink.svelte | 37 ++++++++++++ src/fava/core/misc.py | 22 +++++++ src/fava/internal_api.py | 2 + .../test_application-test_client_side_reports | 1 + ...est_internal_api-test_get_ledger_data.json | 1 + 9 files changed, 177 insertions(+) create mode 100644 frontend/src/sidebar/AdvancedFilterPresetLink.svelte create mode 100644 frontend/src/sidebar/FilterPresets.svelte create mode 100644 frontend/src/sidebar/TimeFilterPresetLink.svelte 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": [