From 16cdcd4230342cc2268422e4e170d41aac29ab14 Mon Sep 17 00:00:00 2001 From: Jakob Schnitzer Date: Sat, 5 Feb 2022 17:11:59 +0100 Subject: [PATCH] implement journal filters as svelte component --- frontend/css/journal-table.css | 4 - frontend/src/journal/JournalFilters.svelte | 82 ++++++++++++++++ frontend/src/{journal.ts => journal/index.ts} | 95 +++++++++---------- frontend/src/stores/index.ts | 3 + frontend/src/svelte-custom-elements.ts | 2 +- src/fava/templates/_journal_table.html | 54 +---------- 6 files changed, 134 insertions(+), 106 deletions(-) create mode 100644 frontend/src/journal/JournalFilters.svelte rename frontend/src/{journal.ts => journal/index.ts} (60%) diff --git a/frontend/css/journal-table.css b/frontend/css/journal-table.css index eac14db15..6900fd7b4 100644 --- a/frontend/css/journal-table.css +++ b/frontend/css/journal-table.css @@ -1,9 +1,5 @@ /* stylelint-disable no-descending-specificity */ -.entry-filters { - justify-content: flex-end; -} - .journal { margin-top: 0.25rem; } diff --git a/frontend/src/journal/JournalFilters.svelte b/frontend/src/journal/JournalFilters.svelte new file mode 100644 index 000000000..e70016c09 --- /dev/null +++ b/frontend/src/journal/JournalFilters.svelte @@ -0,0 +1,82 @@ + + + + +
+ {#each buttons as [type, button_text, title, shortcut, supertype]} + + {/each} +
+ + diff --git a/frontend/src/journal.ts b/frontend/src/journal/index.ts similarity index 60% rename from frontend/src/journal.ts rename to frontend/src/journal/index.ts index ff82b3701..5b7d5a003 100644 --- a/frontend/src/journal.ts +++ b/frontend/src/journal/index.ts @@ -1,8 +1,14 @@ -import { delegate } from "./lib/events"; -import { log_error } from "./log"; -import router from "./router"; -import { sortableJournal } from "./sort"; -import { fql_filter } from "./stores/filters"; +import type { SvelteComponent } from "svelte"; +import { get, writable } from "svelte/store"; + +import { shallow_equal } from "../lib/equals"; +import { delegate } from "../lib/events"; +import router from "../router"; +import { sortableJournal } from "../sort"; +import { favaOptions } from "../stores"; +import { fql_filter } from "../stores/filters"; + +import JournalFilters from "./JournalFilters.svelte"; /** * Escape the value to produce a valid regex. @@ -68,57 +74,50 @@ function handleClick({ target }: MouseEvent): void { } export class FavaJournal extends HTMLElement { - constructor() { - super(); + component?: SvelteComponent; + + unsubscribe?: () => void; + + connectedCallback() { + const opts = get(favaOptions); + const defaults = [ + ...opts.journal_show, + ...opts.journal_show_transaction, + ...opts.journal_show_document, + ].sort(); const ol = this.querySelector("ol"); - const form = this.querySelector("form"); - if (!ol || !form) { + if (!ol) { throw new Error("fava-journal is missing its
    or
    "); } - sortableJournal(ol); - delegate(this, "click", "li", handleClick); - - const entryButtons = form.querySelectorAll("button"); - // Toggle entries with buttons. - entryButtons.forEach((button) => { - button.addEventListener("click", () => { - const type = button.getAttribute("data-type"); - if (!type) { - log_error("Button is missing type: ", button); - return; - } - const shouldShow = button.classList.contains("inactive"); - - button.classList.toggle("inactive", !shouldShow); - if ( - type === "transaction" || - type === "custom" || - type === "document" - ) { - form.querySelectorAll(`.${type}-toggle`).forEach((el) => { - el.classList.toggle("inactive", !shouldShow); - }); - } - ol.classList.toggle(`show-${type}`, shouldShow); + const url_show = new URL(window.location.href).searchParams.getAll("show"); + const show = writable(new Set(url_show.length ? url_show : defaults)); + this.unsubscribe = show.subscribe((show_value) => { + const classes = [...show_value].map((s) => `show-${s}`).join(" "); + ol.className = `flex-table journal ${classes}`; - // Modify get params - const filterShow: string[] = []; - entryButtons.forEach((el) => { - const datatype = el.getAttribute("data-type"); - if (datatype && !el.classList.contains("inactive")) { - filterShow.push(datatype); - } - }); - - const url = new URL(window.location.href); - url.searchParams.delete("show"); - filterShow.forEach((filter) => { + const url = new URL(window.location.href); + url.searchParams.delete("show"); + if (!shallow_equal([...show_value].sort(), defaults)) { + show_value.forEach((filter) => { url.searchParams.append("show", filter); }); - router.navigate(url.toString(), false); - }); + } + router.navigate(url.toString(), false); }); + this.component = new JournalFilters({ + target: this, + props: { show }, + anchor: ol, + }); + + sortableJournal(ol); + delegate(this, "click", "li", handleClick); + } + + disconnectedCallback(): void { + this.unsubscribe?.(); + this.component?.$destroy(); } } diff --git a/frontend/src/stores/index.ts b/frontend/src/stores/index.ts index ef14bae41..755895219 100644 --- a/frontend/src/stores/index.ts +++ b/frontend/src/stores/index.ts @@ -33,6 +33,9 @@ export const ledgerDataValidator = object({ insert_entry: array( object({ date: string, filename: string, lineno: number, re: string }) ), + journal_show: array(string), + journal_show_document: array(string), + journal_show_transaction: array(string), }), have_excel: boolean, incognito: boolean, diff --git a/frontend/src/svelte-custom-elements.ts b/frontend/src/svelte-custom-elements.ts index 90f1ecd60..49cc8985f 100644 --- a/frontend/src/svelte-custom-elements.ts +++ b/frontend/src/svelte-custom-elements.ts @@ -29,7 +29,7 @@ const components = new Map([ /** * A custom element that represents a Svelte component. * - * The tag should have a `data-component` attribute with one + * The tag should have a `type` attribute with one * of the valid values in the Map above. */ export class SvelteCustomElement extends HTMLElement { diff --git a/src/fava/templates/_journal_table.html b/src/fava/templates/_journal_table.html index 5e67532a2..d8bb3c7e3 100644 --- a/src/fava/templates/_journal_table.html +++ b/src/fava/templates/_journal_table.html @@ -1,40 +1,5 @@ {% import 'macros/_commodity_macros.html' as commodity_macros %} - -{% set entry_types = ['open', 'close', 'transaction', 'balance', 'note', 'document', 'pad', 'query', 'custom'] %} -{% set sub_types = { - 'custom': ( - ('budget', 'B', _('Budget entries')), - ), - 'document': ( - ('discovered', 'D', _('Documents with a #discovered tag')), - ('linked', 'L', _('Documents with a #linked tag')), - ), - 'transaction': ( - ('cleared', '*', _('Cleared transactions')), - ('pending', '!', _('Pending transactions')), - ('other', 'x', _('Other transactions')), - ), -} %} -{% set keyboard_shortcuts = { - 'open': 's o', - 'close': 's c', - 'balance': 's b', - 'note': 's n', - 'pad': 's p', - 'query': 's q', - 'custom': 's C', - 'budget': 's B', - - 'transaction': 's t', - 'cleared': 't c', - 'pending': 't p', - 'other': 't o', - - 'document': 's d', - 'discovered': 'd d', - 'linked': 'd l', -} %} {% set short_type = { 'balance': 'Bal', 'close': 'Close', @@ -42,11 +7,6 @@ 'note': 'Note', 'open': 'Open', } %} -{% if not request.args.get('show') %} -{% set journal_show = g.ledger.fava_options.journal_show + g.ledger.fava_options.journal_show_transaction + g.ledger.fava_options.journal_show_document %} -{% else %} -{% set journal_show = request.args.getlist('show') %} -{% endif %} {% macro account_link(name) %}{{ name }}{% endmacro %} {% macro render_metadata_indicators(metadata) -%} @@ -78,19 +38,7 @@ {% macro journal_table(entries, show_change_and_balance=False) %} {% autoescape false %} - - {% for type in entry_types %} - - {% if type in sub_types.keys() %} - {% for sub_type in sub_types[type] %} - - {% endfor %} - {% endif %} - {% endfor %} - - - -
      +
      1. {{ _('Date') }}