-
Notifications
You must be signed in to change notification settings - Fork 293
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
Expose TreeTable to extensions #1695
Comments
Hi, thanks for opening this issue. As also seen in #1721, this seems to be a useful component for extensions :) As a "quick fix", I've re-added the old css and js so you could still use the old ones for a while (however, I haven't re-added the template code so you'd need to copy paste that). I think there's basically two ways that the new component(s) could be exposed to the frontend: 1) providing them to Javascript extensions (https://svelte.dev/docs/client-side-component-api) or 2) wrapping them in a custom HTML element (just like it is already done for the charts) where the data for the component would be provided as JSON in this custom element. (doing both also be an option) Could you describe your use case a bit? Are you using them to render a Fava |
I would like to also be able to access the tree table. In my use case, I render the balance sheet with only accounts under certain criteria. |
It's definitely not that simple as just copy and paste, as a lot of code was deleted as part of that change. I had to go through a lot of hoops before it started working again. To save people some time, this is my _tree_table.html{% macro account_name(ledger, account_name) -%}
<a href="{{ url_for('account', name=account_name) }}" class="account">
{{- account_name.split(':')[-1] -}}
</a>
{%- if ledger.accounts[account_name].uptodate_status %}
{{ indicator(ledger, account_name) }}
{{ last_account_activity(ledger, account_name) }}
{% endif %}
{% endmacro %}
{% macro render_currency(ledger, currency) -%}
<span title="{{ ledger.commodities.name(currency) }}">{{ currency }}</span>
{%- endmacro %}
{% macro render_diff_and_number(balance, cost, currency, invert=False) %}
{% set num = balance.pop(currency, 0) %}
{% set num2 = -num if invert else num %}
<span class="number">{{ num2|format_currency(currency) }}</span>
{% if currency in cost %}
{% set cost_num = cost.pop(currency, 0) %}
{% set diff = num - cost_num %}
{% if invert %}
{% set diff = -diff %}
{% endif %}
{%- if diff -%}
<br>
<span class="diff{{ ' positive' if diff > 0 else ' negative' }}" title="{{ cost_num|format_currency(currency, invert=invert) }} {{ currency }}">({{ diff|format_currency(currency) }})</span>
{%- endif -%}
{%- endif -%}
{%- endmacro %}
{% macro tree(account_node, invert=False, ledger=None) %}
{% set ledger = ledger or g.ledger %}
<tree-table>
<ol class="flex-table tree-table{{ ' two-currencies' if ledger.options.operating_currency|length > 1 else '' }}" title="{{ _('Hold Shift while clicking to expand all children.\nHold Ctrl or Cmd while clicking to expand one level.') }}">
<li class="head">
<p>
<span class="account-cell"><button type="button" class="link expand-all hidden" title="{{ _('Expand all accounts') }}">{{ _('Expand all') }}</button></span>
{% for currency in ledger.options.operating_currency %}
<span class="num">{{ currency }}</span>
{% endfor %}
<span class="num other">{{ _('Other') }}</span>
</p>
</li>
{% set end_date = g.filtered.end_date %}
{% for account in ([account_node] if account_node.name else account_node.children) if extension.should_show(account) recursive %}
{% set balance = extension.cost_or_value(account.balance, end_date) %}
{% set balance_children = extension.cost_or_value(account.balance_children, end_date) %}
{% set cost = extension.cost(account.balance) if g.conversion == 'at_value' else {} %}
{% set cost_children = extension.cost(account.balance_children) if g.conversion == 'at_value' else {} %}
<li{{ ' class=toggled' if extension.collapse_account(account.name) else '' }}>
<p{{ ' class=has-balance' if not balance.is_empty() else '' }}>
<span class="account-cell depth-{{ loop.depth0 }} droptarget{{ ' has-children' if account.children else '' }}" data-account-name="{{ account.name }}">
{{ account_name(ledger, account.name) }}
</span>
{% for currency in ledger.options.operating_currency %}
<span class="num">
<span class="balance">{{ render_diff_and_number(balance, cost, currency, invert=invert) }}</span>
<span class="balance-children">{{ render_diff_and_number(balance_children, cost_children, currency, invert=invert) }}</span>
</span>
{% endfor %}
<span class="num other">
<span class="balance">
{% for currency in balance.keys()|sort %}
{{ render_diff_and_number(balance, cost, currency, invert=invert) }} {{ render_currency(ledger, currency) }}<br>
{% endfor %}
</span>
<span class="balance-children">
{% for currency in balance_children.keys()|sort %}
{{ render_diff_and_number(balance_children, cost_children, currency, invert=invert) }} {{ render_currency(ledger, currency) }}<br>
{% endfor %}
</span>
</span>
</p>
{% if account.children %}
<ol>{{- loop(account.children|sort(attribute='name')) -}} </ol>
{% endif %}
</li>
{% endfor %}
</ol>
</tree-table>
{% endmacro %} And because many of the filters referenced in the macro has been removed, I have also had to add the following methods into my extension class to be used by the template: __init__.py def should_show(self, account: TreeNode) -> bool:
"""Determine whether the account should be shown."""
from fava.context import g
if not account.balance_children.is_empty() or any(
self.should_show(a) for a in account.children
):
return True
ledger = g.ledger
filtered = g.filtered
if account.name not in ledger.accounts:
return False
fava_options = ledger.fava_options
if not fava_options.show_closed_accounts and filtered.account_is_closed(
account.name,
):
return False
if (
not fava_options.show_accounts_with_zero_balance
and account.balance.is_empty()
):
return False
if (
not fava_options.show_accounts_with_zero_transactions
and not account.has_txns
):
return False
return True
def collapse_account(self, account_name: str) -> bool:
"""Return true if account should be collapsed."""
from fava.context import g
collapse_patterns = g.ledger.fava_options.collapse_pattern
return any(pattern.match(account_name) for pattern in collapse_patterns)
def cost(self, inventory: CounterInventory) -> SimpleCounterInventory:
"""Get the cost of an inventory."""
return inventory.reduce(get_cost)
def cost_or_value(
self,
inventory: CounterInventory,
date: date | None = None,
) -> SimpleCounterInventory:
"""Get the cost or value of an inventory."""
from fava.context import g
return cost_or_value(inventory, g.conversion, g.ledger.prices, date) Hope this would be useful. But it is definitely better if we can just use the same tree table used in the builtin report. |
Version 1.26 moved much of the UI generation from templates into svelte/javascript. Before, I could include some of the template helpers (eg for treetables) in my own extension templates, but now that it's in svelte there doesn't seem to be a good way of making my own TreeTables aside from copying-and-pasting code and CSS styles.
Is it possible to expose TreeTables in a way that extensions can more easily use them?
The text was updated successfully, but these errors were encountered: