mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2025-12-21 13:00:12 -06:00
feat: another batch
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -4,4 +4,5 @@
|
||||
"*.css": "tailwindcss"
|
||||
},
|
||||
"tailwindCSS.experimental.configFile": "frontend/src/styles/tailwind.css",
|
||||
"djlint.profile": "django",
|
||||
}
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Account Groups' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'account_group_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
@@ -32,15 +31,13 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'account_group_edit' pk=account_group.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'account_group_delete' pk=account_group.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
@@ -51,8 +48,7 @@
|
||||
{% if not account_group.owner %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-warning"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Take ownership" %}"
|
||||
data-tippy-content="{% translate "Take ownership" %}"
|
||||
hx-get="{% url 'account_group_take_ownership' pk=account_group.id %}">
|
||||
<i class="fa-solid fa-crown fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -61,8 +57,7 @@
|
||||
role="button"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Share" %}"
|
||||
data-tippy-content="{% translate "Share" %}"
|
||||
hx-get="{% url 'account_group_share_settings' pk=account_group.id %}">
|
||||
<i class="fa-solid fa-share fa-fw"></i></a>
|
||||
{% endif %}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Accounts' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'account_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
@@ -37,15 +36,13 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'account_edit' pk=account.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'account_delete' pk=account.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
@@ -56,8 +53,7 @@
|
||||
{% if not account.owner %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-primary"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Take ownership" %}"
|
||||
data-tippy-content="{% translate "Take ownership" %}"
|
||||
hx-get="{% url 'account_take_ownership' pk=account.id %}">
|
||||
<i class="fa-solid fa-crown fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -66,16 +62,14 @@
|
||||
role="button"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Share" %}"
|
||||
data-tippy-content="{% translate "Share" %}"
|
||||
hx-get="{% url 'account_share_settings' pk=account.id %}">
|
||||
<i class="fa-solid fa-share fa-fw"></i></a>
|
||||
{% endif %}
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
hx-get="{% url 'account_toggle_untracked' pk=account.id %}"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% if account.is_untracked_by %}{% translate "Track" %}{% else %}{% translate "Untrack" %}{% endif %}">
|
||||
data-tippy-content="{% if account.is_untracked_by %}{% translate "Track" %}{% else %}{% translate "Untrack" %}{% endif %}">
|
||||
{% if account.is_untracked_by %}
|
||||
<i class="fa-solid fa-eye fa-fw"></i>
|
||||
{% else %}
|
||||
|
||||
@@ -39,23 +39,23 @@
|
||||
{% for transaction in date.transactions %}
|
||||
{% if transaction.is_paid %}
|
||||
{% if transaction.type == "IN" and not transaction.account.is_asset %}
|
||||
<i class="fa-solid fa-circle-check text-success" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
<i class="fa-solid fa-circle-check text-success" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
{% elif transaction.type == "IN" and transaction.account.is_asset %}
|
||||
<i class="fa-solid fa-circle-check text-success/80" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
<i class="fa-solid fa-circle-check text-success/80" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
{% elif transaction.type == "EX" and not transaction.account.is_asset %}
|
||||
<i class="fa-solid fa-circle-check text-error" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
<i class="fa-solid fa-circle-check text-error" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
{% elif transaction.type == "EX" and transaction.account.is_asset %}
|
||||
<i class="fa-solid fa-circle-check text-error/80" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
<i class="fa-solid fa-circle-check text-error/80" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if transaction.type == "IN" and not transaction.account.is_asset %}
|
||||
<i class="fa-regular fa-circle text-success" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
<i class="fa-regular fa-circle text-success" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
{% elif transaction.type == "IN" and transaction.account.is_asset %}
|
||||
<i class="fa-regular fa-circle text-success/80" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
<i class="fa-regular fa-circle text-success/80" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Income' %}{% endif %}"></i>
|
||||
{% elif transaction.type == "EX" and not transaction.account.is_asset %}
|
||||
<i class="fa-regular fa-circle text-error" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
<i class="fa-regular fa-circle text-error" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
{% elif transaction.type == "EX" and transaction.account.is_asset %}
|
||||
<i class="fa-regular fa-circle text-error/80" data-bs-toggle="tooltip" data-bs-title="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
<i class="fa-regular fa-circle text-error/80" data-tippy-content="{% if transaction.description %}{{ transaction.description }}{% else %}{% trans 'Expense' %}{% endif %}"></i>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Categories' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'category_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
|
||||
@@ -24,16 +24,14 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'category_edit' category_id=category.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'category_delete' category_id=category.id %}"
|
||||
hx-trigger='confirmed'
|
||||
hx-swap="innerHTML"
|
||||
@@ -45,8 +43,7 @@
|
||||
{% if not category.owner %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-primary"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Take ownership" %}"
|
||||
data-tippy-content="{% translate "Take ownership" %}"
|
||||
hx-get="{% url 'category_take_ownership' category_id=category.id %}">
|
||||
<i class="fa-solid fa-crown fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -55,8 +52,7 @@
|
||||
role="button"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Share" %}"
|
||||
data-tippy-content="{% translate "Share" %}"
|
||||
hx-get="{% url 'category_share_settings' pk=category.id %}">
|
||||
<i class="fa-solid fa-share fa-fw"></i></a>
|
||||
{% endif %}
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
<a href="{% url url %}"
|
||||
class="lg:text-sm flex items-center no-underline p-2 rounded-box sidebar-item {% active_link views=active css_class="sidebar-active" %}"
|
||||
{% if tooltip %}
|
||||
data-bs-placement="right"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{{ tooltip }}"
|
||||
data-tippy-placement="right"
|
||||
data-tippy-content="{{ tooltip }}"
|
||||
{% endif %}>
|
||||
<i class="{{ icon }} fa-fw"></i>
|
||||
<span
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
hx-boost="false"
|
||||
class="lg:text-sm flex items-center no-underline p-2 rounded-3xl sidebar-item {% active_link views=active css_class="sidebar-active" %}"
|
||||
{% if tooltip %}
|
||||
data-bs-placement="right"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{{ tooltip }}"
|
||||
data-tippy-placement="right"
|
||||
data-tippy-content="{{ tooltip }}"
|
||||
{% endif %}>
|
||||
|
||||
<i class="{{ icon }} fa-fw"></i>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load markdown %}
|
||||
{% load i18n %}
|
||||
<div
|
||||
class="transaction {% if transaction.type == "EX" %}expense{% else %}income{% endif %} group/transaction relative hover:z-10">
|
||||
class="transaction {% if transaction.type == "EX" %}expense{% else %}income{% endif %} group/transaction relative group-hover/transaction:z-50 hover:z-50">
|
||||
<div class="flex my-1">
|
||||
{% if not disable_selection or not dummy %}
|
||||
<label class="px-3 flex! items-center justify-center">
|
||||
@@ -135,36 +135,33 @@
|
||||
</div>
|
||||
</div>
|
||||
{% if not dummy %}
|
||||
<div>
|
||||
<div class="z-1000">
|
||||
{# Item actions#}
|
||||
<div
|
||||
class="transaction-actions absolute! left-1/2 top-0 -translate-x-1/2 -translate-y-1/2 invisible group-hover/transaction:visible! flex flex-row card bg-base-300">
|
||||
class="card transaction-actions absolute! left-1/2 -translate-x-1/2 -translate-y-1/2 top-0 invisible group-hover/transaction:visible! flex flex-row bg-base-300">
|
||||
<div class="card-body p-1 shadow-lg flex flex-row gap-1">
|
||||
{% if not transaction.deleted %}
|
||||
<div class="tooltip" data-tip="{% translate "Edit" %}">
|
||||
<a class="btn btn-neutral btn-sm transaction-action"
|
||||
role="button"
|
||||
hx-get="{% url 'transaction_edit' transaction_id=transaction.id %}"
|
||||
hx-target="#generic-offcanvas" hx-swap="innerHTML">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
</div>
|
||||
<div class="tooltip" data-tip="{% translate "Delete" %}">
|
||||
<a class="btn btn-neutral btn-sm transaction-action"
|
||||
role="button"
|
||||
hx-delete="{% url 'transaction_delete' transaction_id=transaction.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
data-title="{% translate "Are you sure?" %}"
|
||||
data-text="{% translate "You won't be able to revert this!" %}"
|
||||
data-confirm-text="{% translate "Yes, delete it!" %}"
|
||||
_="install prompt_swal"><i class="fa-solid fa-trash fa-fw text-red-500"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="dropdown dropdown-end">
|
||||
<button type="button" tabindex="0" role="button" class="btn btn-neutral btn-sm transaction-action">
|
||||
<a class="btn btn-neutral btn-sm transaction-action"
|
||||
role="button"
|
||||
hx-get="{% url 'transaction_edit' transaction_id=transaction.id %}"
|
||||
hx-target="#generic-offcanvas" hx-swap="innerHTML"
|
||||
data-tippy-content="{% translate "Edit" %}">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-neutral btn-sm transaction-action"
|
||||
role="button"
|
||||
hx-delete="{% url 'transaction_delete' transaction_id=transaction.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
data-bypass-on-ctrl="true"
|
||||
data-title="{% translate "Are you sure?" %}"
|
||||
data-text="{% translate "You won't be able to revert this!" %}"
|
||||
data-confirm-text="{% translate "Yes, delete it!" %}"
|
||||
_="install prompt_swal"><i class="fa-solid fa-trash fa-fw text-error"></i>
|
||||
</a>
|
||||
<button class="btn btn-neutral btn-sm transaction-action" data-bs-toggle="dropdown" data-bs-container="body" aria-expanded="false">
|
||||
<i class="fa-solid fa-ellipsis fa-fw"></i>
|
||||
</button>
|
||||
<ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-200 rounded-box w-72 z-[1]">
|
||||
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-md-start menu w-max">
|
||||
{% if transaction.account.is_untracked_by %}
|
||||
<li>
|
||||
<a class="disabled flex items-center" aria-disabled="true">
|
||||
@@ -218,7 +215,6 @@
|
||||
hx-get="{% url 'transaction_clone' transaction_id=transaction.id %}"><i
|
||||
class="fa-solid fa-clone fa-fw mr-2"></i>{% translate 'Duplicate' %}</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="tooltip" data-tip="{% translate "Restore" %}">
|
||||
<a class="btn btn-secondary btn-sm transaction-action"
|
||||
|
||||
@@ -43,16 +43,14 @@
|
||||
<button class="btn btn-secondary btn-sm"
|
||||
hx-get="{% url 'transactions_bulk_undelete' %}"
|
||||
hx-include=".transaction"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Restore' %}">
|
||||
data-tippy-content="{% translate 'Restore' %}">
|
||||
<i class="fa-solid fa-trash-arrow-up fa-fw"></i>
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm"
|
||||
hx-get="{% url 'transactions_bulk_delete' %}"
|
||||
hx-include=".transaction"
|
||||
hx-trigger="confirmed"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Delete' %}"
|
||||
data-tippy-content="{% translate 'Delete' %}"
|
||||
data-bypass-on-ctrl="true"
|
||||
data-title="{% translate "Are you sure?" %}"
|
||||
data-text="{% translate "You won't be able to revert this!" %}"
|
||||
|
||||
@@ -48,8 +48,7 @@
|
||||
hx-get="{% url 'transactions_bulk_edit' %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-include=".transaction"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Edit' %}">
|
||||
data-tippy-content="{% translate 'Edit' %}">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</button>
|
||||
<div class="dropdown dropdown-top dropdown-end">
|
||||
@@ -78,16 +77,14 @@
|
||||
<button class="btn btn-secondary btn-sm"
|
||||
hx-get="{% url 'transactions_bulk_clone' %}"
|
||||
hx-include=".transaction"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Duplicate' %}">
|
||||
data-tippy-content="{% translate 'Duplicate' %}">
|
||||
<i class="fa-solid fa-clone fa-fw"></i>
|
||||
</button>
|
||||
<button class="btn btn-secondary btn-sm"
|
||||
hx-get="{% url 'transactions_bulk_delete' %}"
|
||||
hx-include=".transaction"
|
||||
hx-trigger="confirmed"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Delete' %}"
|
||||
data-tippy-content="{% translate 'Delete' %}"
|
||||
data-bypass-on-ctrl="true"
|
||||
data-title="{% translate "Are you sure?" %}"
|
||||
data-text="{% translate "You won't be able to revert this!" %}"
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Currencies' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'currency_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
@@ -34,15 +33,13 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'currency_edit' pk=currency.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'currency_delete' pk=currency.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
<div class="card-title text-xl">{% trans "Entries" %}<span>
|
||||
<a class="no-underline p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'dca_entry_add' strategy_id=strategy.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i>
|
||||
@@ -63,16 +62,14 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'dca_entry_edit' entry_id=entry.id strategy_id=entry.strategy.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'dca_entry_delete' entry_id=entry.id strategy_id=entry.strategy.id %}"
|
||||
hx-trigger='confirmed'
|
||||
hx-swap="innerHTML"
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Dollar Cost Average Strategies' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'dca_strategy_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
@@ -32,16 +31,14 @@
|
||||
<div class="card-footer bg-base-200 p-4 text-right">
|
||||
<a class="no-underline text-base-content/60 p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'dca_strategy_edit' strategy_id=strategy.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i>
|
||||
</a>
|
||||
<a class="text-error no-underline p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'dca_strategy_delete' strategy_id=strategy.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
@@ -54,8 +51,7 @@
|
||||
{% if not strategy.owner %}
|
||||
<a class="text-primary no-underline p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Take ownership" %}"
|
||||
data-tippy-content="{% translate "Take ownership" %}"
|
||||
hx-get="{% url 'dca_strategy_take_ownership' strategy_id=strategy.id %}">
|
||||
<i class="fa-solid fa-crown fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -63,8 +59,7 @@
|
||||
<a class="text-primary no-underline p-1"
|
||||
role="button"
|
||||
hx-target="#generic-offcanvas"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Share" %}"
|
||||
data-tippy-content="{% translate "Share" %}"
|
||||
hx-get="{% url 'dca_strategy_share_settings' pk=strategy.id %}">
|
||||
<i class="fa-solid fa-share fa-fw"></i></a>
|
||||
{% endif %}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Entities' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'entity_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
|
||||
@@ -24,16 +24,14 @@
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'entity_edit' entity_id=entity.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'entity_delete' entity_id=entity.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
@@ -44,8 +42,7 @@
|
||||
{% if not entity.owner %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-warning"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Take ownership" %}"
|
||||
data-tippy-content="{% translate "Take ownership" %}"
|
||||
hx-get="{% url 'entity_take_ownership' entity_id=entity.id %}">
|
||||
<i class="fa-solid fa-crown fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -54,8 +51,7 @@
|
||||
role="button"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Share" %}"
|
||||
data-tippy-content="{% translate "Share" %}"
|
||||
hx-get="{% url 'entity_share_settings' pk=entity.id %}">
|
||||
<i class="fa-solid fa-share fa-fw"></i></a>
|
||||
{% endif %}
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
<div>{% translate 'Exchange Rates' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'exchange_rate_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
|
||||
@@ -19,16 +19,14 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'exchange_rate_edit' pk=exchange_rate.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'exchange_rate_delete' pk=exchange_rate.id %}"
|
||||
hx-trigger='confirmed'
|
||||
hx-swap="innerHTML"
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
<div>{% translate 'Automatic Exchange Rates' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'automatic_exchange_rate_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
@@ -42,15 +41,13 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'automatic_exchange_rate_edit' pk=service.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'automatic_exchange_rate_delete' pk=service.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
|
||||
@@ -19,16 +19,14 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'exchange_rate_edit' pk=exchange_rate.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'exchange_rate_delete' pk=exchange_rate.id %}"
|
||||
hx-trigger='confirmed'
|
||||
hx-swap="innerHTML"
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
<div class="text-3xl font-bold font-mono w-full mb-3">
|
||||
{% spaceless %}
|
||||
<div>{% translate 'Import Profiles' %}<span>
|
||||
<span class="dropdown" data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}">
|
||||
<span class="dropdown" data-tippy-content="{% translate "Add" %}">
|
||||
<a class="no-underline text-2xl p-1" role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-title="{% translate "Add" %}" aria-expanded="false">
|
||||
@@ -42,29 +41,25 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'import_profile_edit' profile_id=profile.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-success"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Runs" %}"
|
||||
data-tippy-content="{% translate "Runs" %}"
|
||||
hx-get="{% url 'import_profile_runs_list' profile_id=profile.id %}"
|
||||
hx-target="#persistent-generic-offcanvas-left">
|
||||
<i class="fa-solid fa-person-running fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-primary"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Import" %}"
|
||||
data-tippy-content="{% translate "Import" %}"
|
||||
hx-get="{% url 'import_run_add' profile_id=profile.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-file-import fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'import_profile_delete' profile_id=profile.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
|
||||
@@ -92,14 +92,12 @@
|
||||
<div class="card-footer bg-base-200 p-4 text-base-content/70">
|
||||
<a class="no-underline text-info"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Logs" %}"
|
||||
data-tippy-content="{% translate "Logs" %}"
|
||||
hx-get="{% url 'import_run_log' profile_id=profile.id run_id=run.id %}"
|
||||
hx-target="#generic-offcanvas"><i class="fa-solid fa-file-lines"></i></a>
|
||||
<a class="no-underline text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'import_run_delete' profile_id=profile.id run_id=run.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
|
||||
@@ -152,9 +152,8 @@
|
||||
<a class="dropdown-item"
|
||||
href="{% url 'admin:index' %}"
|
||||
hx-boost="false"
|
||||
data-bs-placement="right"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Only use this if you know what you're doing" %}">
|
||||
data-tippy-placement="right"
|
||||
data-tippy-content="{% translate "Only use this if you know what you're doing" %}">
|
||||
{% translate 'Django Admin' %}
|
||||
</a>
|
||||
</li>
|
||||
@@ -171,7 +170,7 @@
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
<div class="nav-link lg:text-2xl! cursor-pointer"
|
||||
data-bs-toggle="tooltip" data-bs-placement="left" data-bs-title="{% trans "Calculator" %}"
|
||||
data-tippy-placement="left" data-tippy-content="{% trans "Calculator" %}"
|
||||
_="on click trigger show on #calculator">
|
||||
<i class="fa-solid fa-calculator"></i>
|
||||
<span class="d-lg-none d-inline">{% trans "Calculator" %}</span>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<div id="persistent-generic-offcanvas" class="offcanvas offcanvas-end offcanvas-size-xl z-1100!"
|
||||
data-bs-backdrop="static"
|
||||
tabindex="-1"
|
||||
_="on htmx:afterSettle call bootstrap.Offcanvas.getOrCreateInstance(me).show() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call bootstrap.Offcanvas.getOrCreateInstance(me).hide()
|
||||
on force_hide_offcanvas call bootstrap.Offcanvas.getOrCreateInstance(me).hide() end
|
||||
_="on htmx:afterSettle call Offcanvas.getOrCreateInstance(me).show() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call Offcanvas.getOrCreateInstance(me).hide()
|
||||
on force_hide_offcanvas call Offcanvas.getOrCreateInstance(me).hide() end
|
||||
on hidden.bs.offcanvas set my innerHTML to '' end">
|
||||
</div>
|
||||
<div id="persistent-generic-offcanvas-left" class="offcanvas offcanvas-start offcanvas-size-xl z-1100!"
|
||||
data-bs-backdrop="static"
|
||||
tabindex="-1"
|
||||
_="on htmx:afterSettle call bootstrap.Offcanvas.getOrCreateInstance(me).show() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call bootstrap.Offcanvas.getOrCreateInstance(me).hide()
|
||||
on force_hide_offcanvas call bootstrap.Offcanvas.getOrCreateInstance(me).hide() end
|
||||
_="on htmx:afterSettle call Offcanvas.getOrCreateInstance(me).show() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call Offcanvas.getOrCreateInstance(me).hide()
|
||||
on force_hide_offcanvas call Offcanvas.getOrCreateInstance(me).hide() end
|
||||
on hidden.bs.offcanvas set my innerHTML to '' end">
|
||||
</div>
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
<div id="generic-offcanvas" class="offcanvas offcanvas-end offcanvas-size-xl z-1100!"
|
||||
data-bs-backdrop="static"
|
||||
tabindex="-1"
|
||||
_="on htmx:afterSettle call bootstrap.Offcanvas.getOrCreateInstance(me).show() end
|
||||
on hide_offcanvas call bootstrap.Offcanvas.getOrCreateInstance(me).hide() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call bootstrap.Offcanvas.getOrCreateInstance(me).hide()
|
||||
_="on htmx:afterSettle call Offcanvas.getOrCreateInstance(me).show() end
|
||||
on hide_offcanvas call Offcanvas.getOrCreateInstance(me).hide() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call Offcanvas.getOrCreateInstance(me).hide()
|
||||
on hidden.bs.offcanvas set my innerHTML to '' end">
|
||||
</div>
|
||||
<div id="generic-offcanvas-left" class="offcanvas offcanvas-start offcanvas-size-xl z-1100!"
|
||||
data-bs-backdrop="static"
|
||||
tabindex="-1"
|
||||
_="on htmx:afterSettle call bootstrap.Offcanvas.getOrCreateInstance(me).show() end
|
||||
on hide_offcanvas call bootstrap.Offcanvas.getOrCreateInstance(me).hide() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call bootstrap.Offcanvas.getOrCreateInstance(me).hide()
|
||||
_="on htmx:afterSettle call Offcanvas.getOrCreateInstance(me).show() end
|
||||
on hide_offcanvas call Offcanvas.getOrCreateInstance(me).hide() end
|
||||
on htmx:beforeOnLoad[detail.boosted] call Offcanvas.getOrCreateInstance(me).hide()
|
||||
on hidden.bs.offcanvas set my innerHTML to '' end">
|
||||
</div>
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
<script type="text/hyperscript">
|
||||
def initTooltips(t)
|
||||
-- Initialize new tooltips
|
||||
for tooltipTriggerEl in <[data-bs-toggle="tooltip"]/> in t
|
||||
call bootstrap.Tooltip.getOrCreateInstance(tooltipTriggerEl)
|
||||
end
|
||||
end
|
||||
|
||||
init
|
||||
call initTooltips(body)
|
||||
call initiateTooltips()
|
||||
end
|
||||
|
||||
on htmx:afterSettle
|
||||
call initTooltips(body)
|
||||
call initiateTooltips()
|
||||
end
|
||||
|
||||
on tooltips
|
||||
call initTooltips(body)
|
||||
call initiateTooltips()
|
||||
end
|
||||
</script>
|
||||
|
||||
@@ -278,8 +278,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div class="btn-group w-full sidebar-item" role="group">
|
||||
<button type="button" class="btn btn-secondary btn-sm w-full" data-bs-toggle="tooltip"
|
||||
data-bs-title="{% trans "Calculator" %}"
|
||||
<button type="button" class="btn btn-secondary btn-sm w-full" data-tippy-content="{% trans "Calculator" %}"
|
||||
_="on click trigger show on #calculator">
|
||||
<i class="fa-solid fa-calculator fa-fw"></i>
|
||||
</button>
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Installment Plans' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'installment_plan_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
|
||||
@@ -25,24 +25,21 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'installment_plan_edit' installment_plan_id=installment_plan.id %}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Installments" %}"
|
||||
data-tippy-content="{% translate "Installments" %}"
|
||||
hx-get="{% url 'installment_plan_transactions' installment_plan_id=installment_plan.id %}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#persistent-generic-offcanvas-left">
|
||||
<i class="fa-solid fa-eye fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-info"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Refresh" %}"
|
||||
data-tippy-content="{% translate "Refresh" %}"
|
||||
hx-get="{% url 'installment_plan_refresh' installment_plan_id=installment_plan.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-trigger='confirmed'
|
||||
@@ -54,8 +51,7 @@
|
||||
<i class="fa-solid fa-arrows-rotate fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'installment_plan_delete' installment_plan_id=installment_plan.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
|
||||
@@ -3,83 +3,73 @@
|
||||
{% load formats %}
|
||||
{% load i18n %}
|
||||
{% load title %}
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="wygiwyh_dark">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>
|
||||
{% filter site_title %}
|
||||
{% block title %}
|
||||
{% endblock title %}
|
||||
{% endfilter %}
|
||||
</title>
|
||||
|
||||
{% include 'includes/head/favicons.html' %}
|
||||
{% progressive_web_app_meta %}
|
||||
|
||||
{# {% include 'includes/styles.html' %}#}
|
||||
{% block extra_styles %}{% endblock %}
|
||||
|
||||
{% include 'includes/scripts.html' %}
|
||||
|
||||
{% block extra_js_head %}{% endblock %}
|
||||
</head>
|
||||
<body class="font-mono">
|
||||
<div class="fixed top-4 right-4 z-50">
|
||||
<label class="swap swap-rotate">
|
||||
<!-- this hidden checkbox controls the state -->
|
||||
<input type="checkbox" class="theme-controller text-base-content text-sm" value="wygiwyh_light" />
|
||||
|
||||
<!-- sun icon -->
|
||||
<svg
|
||||
class="swap-off h-10 w-10 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
|
||||
</svg>
|
||||
|
||||
<!-- moon icon -->
|
||||
<svg
|
||||
class="swap-on h-10 w-10 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
|
||||
</svg>
|
||||
</label>
|
||||
</div>
|
||||
<div _="install hide_amounts
|
||||
install htmx_error_handler
|
||||
{% block body_hyperscript %}{% endblock %}"
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
|
||||
|
||||
{% include 'includes/mobile_navbar.html' %}
|
||||
{% include 'includes/sidebar.html' %}
|
||||
|
||||
<main>
|
||||
{% settings "DEMO" as demo_mode %}
|
||||
{% if demo_mode %}
|
||||
<div class="px-3 m-0" id="demo-mode-alert" hx-preserve>
|
||||
<div class="alert alert-warning my-3" role="alert">
|
||||
<strong>{% trans 'This is a demo!' %}</strong> {% trans 'Any data you add here will be wiped in 24hrs or less' %}
|
||||
<button type="button" class="btn btn-sm btn-ghost absolute right-2 top-2" onclick="this.parentElement.style.display='none'" aria-label="Close">✕</button>
|
||||
</div>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>
|
||||
{% filter site_title %}
|
||||
{% block title %}
|
||||
{% endblock title %}
|
||||
{% endfilter %}
|
||||
</title>
|
||||
{% include 'includes/head/favicons.html' %}
|
||||
{% progressive_web_app_meta %}
|
||||
{# {% include 'includes/styles.html' %}#}
|
||||
{% block extra_styles %}{% endblock %}
|
||||
{% include 'includes/scripts.html' %}
|
||||
{% block extra_js_head %}{% endblock %}
|
||||
</head>
|
||||
<body class="font-mono">
|
||||
<div class="fixed top-4 right-4 z-50">
|
||||
<label class="swap swap-rotate">
|
||||
<!-- this hidden checkbox controls the state -->
|
||||
<input type="checkbox"
|
||||
class="theme-controller text-base-content text-sm"
|
||||
value="wygiwyh_light" />
|
||||
<!-- sun icon -->
|
||||
<svg class="swap-off h-10 w-10 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24">
|
||||
<path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z" />
|
||||
</svg>
|
||||
<!-- moon icon -->
|
||||
<svg class="swap-on h-10 w-10 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24">
|
||||
<path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z" />
|
||||
</svg>
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="content">
|
||||
{% block content %}{% endblock %}
|
||||
<div _="install hide_amounts install htmx_error_handler
|
||||
{% block body_hyperscript %}{% endblock %}"
|
||||
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
|
||||
{% include 'includes/mobile_navbar.html' %}
|
||||
{% include 'includes/sidebar.html' %}
|
||||
<main class="my-4 px-3">
|
||||
{% settings "DEMO" as demo_mode %}
|
||||
{% if demo_mode %}
|
||||
<div class="px-3 m-0" id="demo-mode-alert" hx-preserve>
|
||||
<div class="alert alert-warning my-3" role="alert">
|
||||
<strong>{% trans "This is a demo!" %}</strong> {% trans "Any data you add here will be wiped in 24hrs or less" %}
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-ghost absolute right-2 top-2"
|
||||
onclick="this.parentElement.style.display='none'"
|
||||
aria-label="Close">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="content">
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
</div>
|
||||
{% include "includes/offcanvas.html" %}
|
||||
{% include "includes/toasts.html" %}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{% include 'includes/offcanvas.html' %}
|
||||
{% include 'includes/toasts.html' %}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
{% include 'includes/tools/calculator.html' %}
|
||||
|
||||
{% block extra_js_body %}{% endblock %}
|
||||
</body>
|
||||
{% include "includes/tools/calculator.html" %}
|
||||
{% block extra_js_body %}
|
||||
{% endblock extra_js_body %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -13,9 +13,8 @@
|
||||
<h5 class="title flex-grow"></h5>
|
||||
<button class="btn btn-secondary btn-sm text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
_="on click remove the closest .card to me then trigger update on #items then call bootstrap.Tooltip.getOrCreateInstance(me).dispose()">
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
_="on click remove the closest .card to me then trigger update on #items then trigger tooltips on body">
|
||||
<i class="fa-solid fa-trash fa-fw"></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -56,16 +55,14 @@
|
||||
then
|
||||
|
||||
// Remove existing highlight classes from all unit prices
|
||||
for unitPriceEl in <.unit-price/>
|
||||
remove .bg-error from the closest .card to unitPriceEl
|
||||
remove .bg-error from unitPriceEl's classList
|
||||
remove .bg-success from the closest .card to unitPriceEl
|
||||
remove .bg-success from unitPriceEl's classList
|
||||
for unitPriceEl in <*.unit-price/>
|
||||
remove .bg-error\/20 from the closest .card to unitPriceEl
|
||||
remove .bg-success\/20 from the closest .card to unitPriceEl
|
||||
end
|
||||
|
||||
// Get all unit prices and find min/max
|
||||
set unitPrices to <card:not(#card-placeholder) .unit-price/>
|
||||
set unitPricesAmounts to <.tw:card:not(#card-placeholder) .unit-price/> @data-amount
|
||||
set unitPrices to <.card:not(#card-placeholder) .unit-price/>
|
||||
set unitPricesAmounts to <.card:not(#card-placeholder) .unit-price/> @data-amount
|
||||
js(unitPricesAmounts)
|
||||
unitPricesAmounts = unitPricesAmounts.filter(element => element !== '0')
|
||||
return Math.min(...unitPricesAmounts)
|
||||
@@ -81,12 +78,12 @@
|
||||
for unitPriceEl in unitPrices
|
||||
set amount to parseFloat(unitPriceEl.getAttribute('data-amount'))
|
||||
if amount == minAmount
|
||||
add .bg-success to the closest .card to unitPriceEl
|
||||
add .bg-success\/20 to the closest .card to unitPriceEl
|
||||
add .bg-opacity-20 to the closest .card to unitPriceEl
|
||||
continue
|
||||
end
|
||||
if amount == maxAmount
|
||||
add .bg-error to the closest .card to unitPriceEl
|
||||
add .bg-error\/20 to the closest .card to unitPriceEl
|
||||
add .bg-opacity-20 to the closest .card to unitPriceEl
|
||||
end
|
||||
end
|
||||
@@ -146,13 +143,13 @@
|
||||
|
||||
<div class="grid lg:grid-cols-[2fr_1fr] gap-3 mt-3">
|
||||
<div>
|
||||
<button class="btn btn-outline btn-primary w-full"
|
||||
<button class="btn btn-primary w-full"
|
||||
_="on click
|
||||
get #card-placeholder
|
||||
set newCard to it.cloneNode(true)
|
||||
remove @id from newCard
|
||||
remove .hidden from newCard then
|
||||
set itemCount to <#items[class='card'] />'s length
|
||||
set itemCount to <#items .card />'s length
|
||||
if itemCount < 26
|
||||
set letter to String.fromCharCode(65 + itemCount)
|
||||
else
|
||||
@@ -160,13 +157,13 @@
|
||||
end
|
||||
set newCard.querySelector('.title').innerHTML to `{% trans "Item" %} ${letter}`
|
||||
put newCard as HTML at the end of #items
|
||||
trigger tooltips on body
|
||||
trigger tooltips on body
|
||||
end">
|
||||
{% trans 'Add' %}
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-outline btn-error w-full"
|
||||
<button class="btn btn-error w-full"
|
||||
_="on click
|
||||
for el in <.item-price, .item-amount />
|
||||
set card to the closest .card to el
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{% for x in transactions_by_date %}
|
||||
<div id="{{ x.grouper|slugify }}" class="transactions-divider"
|
||||
_="on htmx:afterSwap from #transactions if sessionStorage.getItem(my id) is null then sessionStorage.setItem(my id, 'true')">
|
||||
<div class="mt-3 mb-1 w-full text-base border-b border-b-base-content/30 transactions-divider-title">
|
||||
<div class="mt-3 mb-1 w-full border-b border-b-base-content/30 transactions-divider-title">
|
||||
<a class="no-underline inline-block w-full"
|
||||
role="button"
|
||||
data-bs-toggle="collapse"
|
||||
@@ -17,7 +17,7 @@
|
||||
{{ x.grouper }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="collapse transactions-divider-collapse overflow-visible" id="c-{{ x.grouper|slugify }}-collapse"
|
||||
<div class="collapse transactions-divider-collapse overflow-visible isolation-auto" id="c-{{ x.grouper|slugify }}-collapse"
|
||||
_="on shown.bs.collapse sessionStorage.setItem(the closest parent @id, 'true')
|
||||
on hidden.bs.collapse sessionStorage.setItem(the closest parent @id, 'false')
|
||||
on htmx:afterSettle from #transactions or toggle
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
|
||||
{% block content %}
|
||||
<div class="container gap-y-3">
|
||||
<div class="row ">
|
||||
<div class="row mt-7 mb-5">
|
||||
<div class="col-12 lg:col-4">
|
||||
{# Date picker#}
|
||||
<div class="col-span-1 xl:col-span-4 flex flex-row items-center">
|
||||
<div class="flex flex-row items-center">
|
||||
<div class="text-base h-full flex items-center btn btn-ghost">
|
||||
<a role="button"
|
||||
hx-boost="true"
|
||||
|
||||
@@ -4,101 +4,121 @@
|
||||
{% load i18n %}
|
||||
{% load month_name %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}{% if type == "current" %}{% translate 'Current Net Worth' %}{% else %}{% translate 'Projected Net Worth' %}{% endif %}{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
{% if type == "current" %}
|
||||
{% translate "Current Net Worth" %}
|
||||
{% else %}
|
||||
{% translate "Projected Net Worth" %}
|
||||
{% endif %}
|
||||
{% endblock title %}
|
||||
{% block content %}
|
||||
<div hx-trigger="every 60m, updated from:window" hx-include="#view-type" class="show-loading" hx-get=""
|
||||
<div hx-trigger="every 60m, updated from:window"
|
||||
hx-include="#view-type"
|
||||
class="show-loading"
|
||||
hx-get=""
|
||||
hx-target="body">
|
||||
<div class="h-full text-center mb-4 pt-2">
|
||||
<div class="join" role="group" id="view-type" _="on change trigger updated">
|
||||
<div class="h-full text-center mb-4 pt-2 w-full">
|
||||
<div class="tabs tabs-box mx-auto w-fit"
|
||||
id="view-type"
|
||||
_="on change trigger updated">
|
||||
<input type="radio"
|
||||
class="join-item btn btn-outline btn-primary rounded-full"
|
||||
name="view_type"
|
||||
aria-label="{% trans 'Current' %}"
|
||||
autocomplete="off"
|
||||
class="tab"
|
||||
aria-label="{% trans "Current" %}"
|
||||
value="current"
|
||||
{% if type == "current" %}checked{% endif %}>
|
||||
|
||||
{% if type == "current" %}checked{% endif %} />
|
||||
<input type="radio"
|
||||
class="join-item btn btn-outline btn-primary rounded-full"
|
||||
name="view_type"
|
||||
aria-label="{% trans 'Projected' %}"
|
||||
autocomplete="off"
|
||||
class="tab"
|
||||
aria-label="{% trans "Projected" %}"
|
||||
value="projected"
|
||||
{% if type == "projected" %}checked{% endif %}>
|
||||
{% if type == "projected" %}checked{% endif %} />
|
||||
</div>
|
||||
{% comment %} <div class="gap-3" role="group" id="view-type" _="on change trigger updated">
|
||||
<input type="radio" class="btn btn-outline btn-primary rounded-full" name="view_type" aria-label="{% trans "Current" %}" autocomplete="off" value="current" {% if type == "current" %}checked{% endif %} />
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i>{% trans "Current" %}
|
||||
</input />
|
||||
<input type="radio" class="btn btn-outline btn-primary rounded-full" name="view_type" aria-label="{% trans "Projected" %}" autocomplete="off" value="projected" {% if type == "projected" %}checked{% endif %} />
|
||||
</div> {% endcomment %}
|
||||
</div>
|
||||
<div class="container px-md-3 py-3"
|
||||
_="init call initializeAccountChart() then initializeCurrencyChart() then initializeMonthlyDifferenceChart() end">
|
||||
<div class="row gap-y-3">
|
||||
<div class="col lg:col-5">
|
||||
<div>
|
||||
<c-ui.info-card color="yellow" icon="fa-solid fa-coins" title="{% trans 'By currency' %}"
|
||||
title_css_classes="cursor-pointer"
|
||||
_="on click showAllDatasetsCurrency()">
|
||||
{% for currency in currency_net_worth.values %}
|
||||
<div class="flex justify-between mt-2">
|
||||
<div class="flex items-baseline w-full">
|
||||
<div class="currency-name text-start font-mono text-base-content cursor-pointer"
|
||||
_="on click showOnlyCurrencyDataset('{{ currency.currency.name }}')">
|
||||
{{ currency.currency.name }}
|
||||
</div>
|
||||
<div class="dotted-line flex-grow"></div>
|
||||
<div>
|
||||
<c-amount.display
|
||||
:amount="currency.total_final"
|
||||
:prefix="currency.currency.prefix"
|
||||
:suffix="currency.currency.suffix"
|
||||
:decimal_places="currency.currency.decimal_places"
|
||||
color="{% if currency.total_final > 0 %}green{% elif currency.total_final < 0 %}red{% endif %}"
|
||||
text-end></c-amount.display>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if currency.exchanged and currency.exchanged.total_final %}
|
||||
<div>
|
||||
<c-amount.display
|
||||
:amount="currency.exchanged.total_final"
|
||||
:prefix="currency.exchanged.currency.prefix"
|
||||
:suffix="currency.exchanged.currency.suffix"
|
||||
:decimal_places="currency.exchanged.currency.decimal_places"
|
||||
text-end
|
||||
color="grey"></c-amount.display>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<c-ui.info-card color="yellow" icon="fa-solid fa-coins" title="{% trans "By currency" %}" title_css_classes="cursor-pointer" _="on click showAllDatasetsCurrency()">
|
||||
<ul class="menu bg-base-100 w-full rounded-box">
|
||||
{% for currency in currency_net_worth.values %}
|
||||
<li>
|
||||
{% if currency.consolidated and currency.consolidated.total_final != currency.total_final %}
|
||||
<div class="flex items-baseline w-full">
|
||||
<div class="account-name text-start font-mono text-base-content/60">
|
||||
<span class="hierarchy-line-icon"></span>{% trans 'Consolidated' %}</div>
|
||||
<div class="dotted-line flex-grow"></div>
|
||||
<div class="">
|
||||
<c-amount.display
|
||||
:amount="currency.consolidated.total_final"
|
||||
:prefix="currency.consolidated.currency.prefix"
|
||||
:suffix="currency.consolidated.currency.suffix"
|
||||
:decimal_places="currency.consolidated.currency.decimal_places"
|
||||
color="{% if currency.consolidated.total_final > 0 %}green{% elif currency.consolidated.total_final < 0 %}red{% endif %}"
|
||||
text-end></c-amount.display>
|
||||
</div>
|
||||
</div>
|
||||
<a class="cursor-pointer flex justify-between items-center w-full"
|
||||
_="on click showOnlyCurrencyDataset('{{ currency.currency.name }}')">
|
||||
<span class="currency-name text-start font-mono flex-shrink text-ellipsis">{{ currency.currency.name }}</span>
|
||||
<span class="text-end flex-shrink-0">
|
||||
<div>
|
||||
<c-amount.display :amount="currency.total_final" :prefix="currency.currency.prefix" :suffix="currency.currency.suffix" :decimal_places="currency.currency.decimal_places" color="{% if currency.total_final > 0 %}green{% elif currency.total_final < 0 %}red{% endif %}" text-end></c-amount.display>
|
||||
</div>
|
||||
{% if currency.exchanged and currency.exchanged.total_final %}
|
||||
<div>
|
||||
<c-amount.display :amount="currency.exchanged.total_final" :prefix="currency.exchanged.currency.prefix" :suffix="currency.exchanged.currency.suffix" :decimal_places="currency.exchanged.currency.decimal_places" text-end color="grey"></c-amount.display>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a class="text-base-content/60">
|
||||
<span class="text-start font-mono flex-shrink">{% trans "Consolidated" %}</span>
|
||||
<span class="text-end flex-shrink-0">
|
||||
<c-amount.display :amount="currency.consolidated.total_final" :prefix="currency.consolidated.currency.prefix" :suffix="currency.consolidated.currency.suffix" :decimal_places="currency.consolidated.currency.decimal_places" color="{% if currency.consolidated.total_final > 0 %}green{% elif currency.consolidated.total_final < 0 %}red{% endif %}" text-end></c-amount.display>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<a class="cursor-pointer flex justify-between items-center w-full"
|
||||
_="on click showOnlyCurrencyDataset('{{ currency.currency.name }}')">
|
||||
<span class="currency-name text-start font-mono flex-shrink">{{ currency.currency.name }}</span>
|
||||
<span class="text-end flex-shrink-0">
|
||||
<div>
|
||||
<c-amount.display :amount="currency.total_final" :prefix="currency.currency.prefix" :suffix="currency.currency.suffix" :decimal_places="currency.currency.decimal_places" color="{% if currency.total_final > 0 %}green{% elif currency.total_final < 0 %}red{% endif %}" text-end></c-amount.display>
|
||||
</div>
|
||||
{% if currency.exchanged and currency.exchanged.total_final %}
|
||||
<div>
|
||||
<c-amount.display :amount="currency.exchanged.total_final" :prefix="currency.exchanged.currency.prefix" :suffix="currency.exchanged.currency.suffix" :decimal_places="currency.exchanged.currency.decimal_places" text-end color="grey"></c-amount.display>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</c-ui.info-card>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</c-ui.info-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col lg:col-7">
|
||||
<div class="card bg-base-100">
|
||||
<div class="card-body">
|
||||
<div role="tablist" class="tabs tabs-border w-full" id="myTab">
|
||||
<input type="radio" name="networth_tabs" role="tab" class="tab" aria-label="{% trans 'Evolution' %}" id="tab-evolution" checked="checked" />
|
||||
<input type="radio"
|
||||
name="networth_tabs"
|
||||
role="tab"
|
||||
class="tab"
|
||||
aria-label="{% trans 'Evolution' %}"
|
||||
id="tab-evolution"
|
||||
checked="checked" />
|
||||
<div role="tabpanel" class="tab-content p-4" id="evolution-tab-pane">
|
||||
<div class="chart-container relative min-h-[40vh] h-full w-full">
|
||||
<canvas id="currencyBalanceChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="radio" name="networth_tabs" role="tab" class="tab" aria-label="{% trans 'Difference' %}" id="tab-diff" />
|
||||
<input type="radio"
|
||||
name="networth_tabs"
|
||||
role="tab"
|
||||
class="tab"
|
||||
aria-label="{% trans 'Difference' %}"
|
||||
id="tab-diff" />
|
||||
<div role="tabpanel" class="tab-content p-4" id="diff-tab-pane">
|
||||
<div class="chart-container relative min-h-[40vh] h-full w-full">
|
||||
<canvas id="monthlyDifferenceChart"></canvas>
|
||||
@@ -109,82 +129,66 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="hr my-6">
|
||||
<hr class="hr my-6" />
|
||||
<div class="row gap-y-3">
|
||||
<div class="col lg:col-5">
|
||||
<div>
|
||||
<c-ui.info-card color="blue" icon="fa-solid fa-wallet" title="{% trans 'By account' %}"
|
||||
title_css_classes="cursor-pointer"
|
||||
_="on click showAllDatasetsAccount()">
|
||||
{% regroup account_net_worth.values by account.group as account_data %}
|
||||
{% for data in account_data %}
|
||||
{% if data.grouper %}
|
||||
<div class="flex justify-between mt-2">
|
||||
<div class="flex items-baseline w-full">
|
||||
<div class="text-start font-mono text-base-content"><span class="badge badge-primary">
|
||||
{{ data.grouper }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
{% for account in data.list %}
|
||||
<div class="flex justify-between mt-2">
|
||||
<div class="flex items-baseline w-full">
|
||||
<div class="account-name text-start font-mono text-base-content cursor-pointer"
|
||||
<div>
|
||||
<c-ui.info-card color="blue" icon="fa-solid fa-wallet" title="{% trans "By account" %}" title_css_classes="cursor-pointer" _="on click showAllDatasetsAccount()">
|
||||
<ul class="menu bg-base-100 w-full rounded-box">
|
||||
{% regroup account_net_worth.values by account.group as account_data %}
|
||||
{% for data in account_data %}
|
||||
{% if data.grouper %}
|
||||
<li>
|
||||
<details open>
|
||||
<summary class="font-mono">
|
||||
<span class="badge badge-primary">{{ data.grouper }}</span>
|
||||
</summary>
|
||||
<ul>
|
||||
{% for account in data.list %}
|
||||
<li>
|
||||
<a class="cursor-pointer flex justify-between items-center w-full"
|
||||
_="on click showOnlyAccountDataset('{{ account.account.name }}')">
|
||||
<span class="hierarchy-line-icon"></span>{{ account.account.name }}</div>
|
||||
<div class="dotted-line flex-grow"></div>
|
||||
<div class="">
|
||||
<c-amount.display
|
||||
:amount="account.total_final"
|
||||
:prefix="account.currency.prefix"
|
||||
:suffix="account.currency.suffix"
|
||||
:decimal_places="account.currency.decimal_places"
|
||||
color="{% if account.total_final > 0 %}green{% elif account.total_final < 0 %}red{% endif %}"></c-amount.display>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if account.exchanged and account.exchanged.total_final %}
|
||||
<c-amount.display
|
||||
:amount="account.exchanged.total_final"
|
||||
:prefix="account.exchanged.currency.prefix"
|
||||
:suffix="account.exchanged.currency.suffix"
|
||||
:decimal_places="account.exchanged.currency.decimal_places"
|
||||
color="grey"
|
||||
text-end></c-amount.display>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for account in data.list %}
|
||||
<div class="flex justify-between mt-2">
|
||||
<div class="flex items-baseline w-full">
|
||||
<div class="account-name text-start font-mono text-base-content cursor-pointer"
|
||||
_="on click showOnlyAccountDataset('{{ account.account.name }}')">
|
||||
{{ account.account.name }}
|
||||
</div>
|
||||
<div class="dotted-line flex-grow"></div>
|
||||
<span class="account-name text-start font-mono flex-shrink text-ellipsis">{{ account.account.name }}</span>
|
||||
<span class="text-end flex-shrink-0">
|
||||
<div>
|
||||
<c-amount.display :amount="account.total_final" :prefix="account.currency.prefix" :suffix="account.currency.suffix" :decimal_places="account.currency.decimal_places" color="{% if account.total_final > 0 %}green{% elif account.total_final < 0 %}red{% endif %}"></c-amount.display>
|
||||
</div>
|
||||
{% if account.exchanged and account.exchanged.total_final %}
|
||||
<div>
|
||||
<c-amount.display :amount="account.exchanged.total_final" :prefix="account.exchanged.currency.prefix" :suffix="account.exchanged.currency.suffix" :decimal_places="account.exchanged.currency.decimal_places" color="grey" text-end></c-amount.display>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
{% else %}
|
||||
{% for account in data.list %}
|
||||
<li>
|
||||
<a class="cursor-pointer flex justify-between items-center w-full"
|
||||
_="on click showOnlyAccountDataset('{{ account.account.name }}')">
|
||||
<span class="account-name text-start font-mono flex-shrink">{{ account.account.name }}</span>
|
||||
<span class="text-end flex-shrink-0">
|
||||
<div>
|
||||
<c-amount.display
|
||||
:amount="account.total_final"
|
||||
:prefix="account.currency.prefix"
|
||||
:suffix="account.currency.suffix"
|
||||
:decimal_places="account.currency.decimal_places"
|
||||
color="{% if account.total_final > 0 %}green{% elif account.total_final < 0 %}red{% endif %}"></c-amount.display>
|
||||
<c-amount.display :amount="account.total_final" :prefix="account.currency.prefix" :suffix="account.currency.suffix" :decimal_places="account.currency.decimal_places" color="{% if account.total_final > 0 %}green{% elif account.total_final < 0 %}red{% endif %}"></c-amount.display>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if account.exchanged and account.exchanged.total_final %}
|
||||
<c-amount.display
|
||||
:amount="account.exchanged.total_final"
|
||||
:prefix="account.exchanged.currency.prefix"
|
||||
:suffix="account.exchanged.currency.suffix"
|
||||
:decimal_places="account.exchanged.currency.decimal_places"
|
||||
color="grey"
|
||||
text-end></c-amount.display>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</c-ui.info-card>
|
||||
</div>
|
||||
{% if account.exchanged and account.exchanged.total_final %}
|
||||
<div>
|
||||
<c-amount.display :amount="account.exchanged.total_final" :prefix="account.exchanged.currency.prefix" :suffix="account.exchanged.currency.suffix" :decimal_places="account.exchanged.currency.decimal_places" color="grey" text-end></c-amount.display>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</c-ui.info-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col lg:col-7">
|
||||
<div class="chart-container relative min-h-[40vh] h-full card bg-base-100">
|
||||
@@ -195,7 +199,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var currencyChart;
|
||||
|
||||
@@ -258,7 +261,6 @@
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="accountBalanceChartScript">
|
||||
var accountChart;
|
||||
|
||||
@@ -323,7 +325,6 @@
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="monthlyDifferenceChartScript">
|
||||
var monthlyDifferenceChart;
|
||||
|
||||
@@ -363,7 +364,10 @@
|
||||
stacked: true,
|
||||
ticks: {
|
||||
display: false,
|
||||
format: {maximumFractionDigits: 40, minimumFractionDigits: 0}
|
||||
format: {
|
||||
maximumFractionDigits: 40,
|
||||
minimumFractionDigits: 0
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -371,7 +375,6 @@
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="text/hyperscript">
|
||||
def showOnlyAccountDataset(datasetName)
|
||||
for dataset in accountChart.data.datasets
|
||||
@@ -416,4 +419,4 @@
|
||||
</script>
|
||||
</div>
|
||||
<c-ui.transactions_fab></c-ui.transactions_fab>
|
||||
{% endblock %}
|
||||
{% endblock content %}
|
||||
|
||||
@@ -22,16 +22,14 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'quick_transaction_edit' quick_transaction_id=qt.id %}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'quick_transaction_delete' quick_transaction_id=qt.id %}"
|
||||
hx-trigger='confirmed'
|
||||
hx-swap="innerHTML"
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
<div>{% translate 'Quick Transactions' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'quick_transaction_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Recurring Transactions' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'recurring_transaction_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
|
||||
@@ -27,16 +27,14 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'recurring_transaction_edit' recurring_transaction_id=recurring_transaction.id %}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Transactions" %}"
|
||||
data-tippy-content="{% translate "Transactions" %}"
|
||||
hx-get="{% url 'recurring_transaction_transactions' recurring_transaction_id=recurring_transaction.id %}"
|
||||
hx-swap="innerHTML"
|
||||
hx-target="#persistent-generic-offcanvas-left">
|
||||
@@ -45,8 +43,7 @@
|
||||
{% if recurring_transaction.is_paused %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-info"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Unpause" %}"
|
||||
data-tippy-content="{% translate "Unpause" %}"
|
||||
hx-get="{% url 'recurring_transaction_toggle_pause' recurring_transaction_id=recurring_transaction.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
@@ -59,8 +56,7 @@
|
||||
{% else %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-info"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Pause" %}"
|
||||
data-tippy-content="{% translate "Pause" %}"
|
||||
hx-get="{% url 'recurring_transaction_toggle_pause' recurring_transaction_id=recurring_transaction.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-trigger='confirmed'
|
||||
@@ -74,8 +70,7 @@
|
||||
{% endif %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-info"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Finish" %}"
|
||||
data-tippy-content="{% translate "Finish" %}"
|
||||
hx-get="{% url 'recurring_transaction_finish' recurring_transaction_id=recurring_transaction.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-trigger='confirmed'
|
||||
@@ -89,8 +84,7 @@
|
||||
{% endif %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'recurring_transaction_delete' recurring_transaction_id=recurring_transaction.id %}"
|
||||
hx-trigger='confirmed'
|
||||
hx-swap="innerHTML"
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Rules' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'transaction_rule_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
@@ -34,15 +33,13 @@
|
||||
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "View" %}"
|
||||
data-tippy-content="{% translate "View" %}"
|
||||
hx-get="{% url 'transaction_rule_view' transaction_rule_id=rule.id %}"
|
||||
hx-target="#persistent-generic-offcanvas-left">
|
||||
<i class="fa-solid fa-eye fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'transaction_rule_delete' transaction_rule_id=rule.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
@@ -53,8 +50,7 @@
|
||||
{% if not rule.owner %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-warning"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Take ownership" %}"
|
||||
data-tippy-content="{% translate "Take ownership" %}"
|
||||
hx-get="{% url 'transaction_rule_take_ownership' transaction_rule_id=rule.id %}">
|
||||
<i class="fa-solid fa-crown fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -63,8 +59,7 @@
|
||||
role="button"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Share" %}"
|
||||
data-tippy-content="{% translate "Share" %}"
|
||||
hx-get="{% url 'transaction_rule_share_settings' pk=rule.id %}">
|
||||
<i class="fa-solid fa-share fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -73,8 +68,7 @@
|
||||
<td class="w-auto">
|
||||
<a class="no-underline"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="
|
||||
data-tippy-content="
|
||||
{% if rule.active %}{% translate "Deactivate" %}{% else %}{% translate "Activate" %}{% endif %}"
|
||||
hx-get="{% url 'transaction_rule_toggle_activity' transaction_rule_id=rule.id %}">
|
||||
{% if rule.active %}<i class="fa-solid fa-toggle-on text-green-400"></i>{% else %}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
<div class="card-footer text-end">
|
||||
<a class="no-underline text-gray-400 p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'transaction_rule_edit' transaction_rule_id=transaction_rule.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
@@ -49,16 +48,14 @@
|
||||
<div class="card-footer text-end">
|
||||
<a class="no-underline text-gray-400 p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Edit' %}"
|
||||
data-tippy-content="{% translate 'Edit' %}"
|
||||
hx-get="{% url 'transaction_rule_action_edit' transaction_rule_action_id=action.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i>
|
||||
</a>
|
||||
<a class="text-error no-underline p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Delete' %}"
|
||||
data-tippy-content="{% translate 'Delete' %}"
|
||||
hx-delete="{% url 'transaction_rule_action_delete' transaction_rule_action_id=action.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
@@ -84,16 +81,14 @@
|
||||
<div class="card-footer text-end">
|
||||
<a class="no-underline text-gray-400 p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Edit' %}"
|
||||
data-tippy-content="{% translate 'Edit' %}"
|
||||
hx-get="{% url 'update_or_create_transaction_rule_action_edit' pk=action.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i>
|
||||
</a>
|
||||
<a class="text-error no-underline p-1"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate 'Delete' %}"
|
||||
data-tippy-content="{% translate 'Delete' %}"
|
||||
hx-delete="{% url 'update_or_create_transaction_rule_action_delete' pk=action.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
<div>{% translate 'Tags' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'tag_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
|
||||
@@ -24,16 +24,14 @@
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'tag_edit' tag_id=tag.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-error"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-title="{% translate "Delete" %}"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'tag_delete' tag_id=tag.id %}"
|
||||
hx-trigger='confirmed'
|
||||
data-bypass-on-ctrl="true"
|
||||
@@ -44,8 +42,7 @@
|
||||
{% if not tag.owner %}
|
||||
<a class="btn btn-secondary btn-sm join-item text-warning"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Take ownership" %}"
|
||||
data-tippy-content="{% translate "Take ownership" %}"
|
||||
hx-get="{% url 'tag_take_ownership' tag_id=tag.id %}">
|
||||
<i class="fa-solid fa-crown fa-fw"></i></a>
|
||||
{% endif %}
|
||||
@@ -54,8 +51,7 @@
|
||||
role="button"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Share" %}"
|
||||
data-tippy-content="{% translate "Share" %}"
|
||||
hx-get="{% url 'tag_share_settings' pk=tag.id %}">
|
||||
<i class="fa-solid fa-share fa-fw"></i></a>
|
||||
{% endif %}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
{{ x.grouper }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="collapse transactions-divider-collapse overflow-visible" id="c-{{ x.grouper|slugify }}-collapse"
|
||||
<div class="collapse transactions-divider-collapse overflow-visible isolation-auto" id="c-{{ x.grouper|slugify }}-collapse"
|
||||
_="on shown.bs.collapse sessionStorage.setItem(the closest parent @id, 'true')
|
||||
on hidden.bs.collapse sessionStorage.setItem(the closest parent @id, 'false')
|
||||
on htmx:afterSettle from #transactions or toggle
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
<div>{% translate 'Users' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Add" %}"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'user_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
@@ -39,16 +38,14 @@
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
hx-swap="innerHTML"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Edit" %}"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'user_edit' pk=user.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
{% if request.user|can_hijack:user and request.user != user %}
|
||||
<a class="btn btn-info btn-sm join-item"
|
||||
role="button"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-title="{% translate "Impersonate" %}"
|
||||
data-tippy-content="{% translate "Impersonate" %}"
|
||||
hx-post="{% url 'hijack:acquire' %}"
|
||||
hx-vals='{"user_pk":"{{user.id}}"}'
|
||||
hx-swap="none"
|
||||
|
||||
10
frontend/package-lock.json
generated
10
frontend/package-lock.json
generated
@@ -31,6 +31,7 @@
|
||||
"sass": "^1.93.3",
|
||||
"sweetalert2": "^11.26.3",
|
||||
"tailwindcss": "^4.1.16",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tom-select": "^2.4.3",
|
||||
"tw-bootstrap-grid": "^1.3.1",
|
||||
"vite": "7.1.12"
|
||||
@@ -1574,6 +1575,15 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/tippy.js": {
|
||||
"version": "6.3.7",
|
||||
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
|
||||
"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"sass": "^1.93.3",
|
||||
"sweetalert2": "^11.26.3",
|
||||
"tailwindcss": "^4.1.16",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tom-select": "^2.4.3",
|
||||
"tw-bootstrap-grid": "^1.3.1",
|
||||
"vite": "7.1.12"
|
||||
|
||||
14
frontend/src/bootstrap.js
vendored
14
frontend/src/bootstrap.js
vendored
@@ -1,10 +1,16 @@
|
||||
// Import all of Bootstrap's JS
|
||||
import * as bootstrap from 'bootstrap'; // eslint-disable-line no-unused-vars
|
||||
window.bootstrap = bootstrap;
|
||||
import './js/_tooltip.js';
|
||||
import 'bootstrap/js/dist/dropdown';
|
||||
import Toast from 'bootstrap/js/dist/toast';
|
||||
import 'bootstrap/js/dist/dropdown';
|
||||
import 'bootstrap/js/dist/collapse';
|
||||
import Offcanvas from 'bootstrap/js/dist/offcanvas';
|
||||
|
||||
window.Offcanvas = Offcanvas;
|
||||
|
||||
|
||||
function initiateToasts() {
|
||||
const toastElList = document.querySelectorAll('.toasty');
|
||||
const toastList = [...toastElList].map(toastEl => new bootstrap.Toast(toastEl)); // eslint-disable-line no-undef
|
||||
const toastList = [...toastElList].map(toastEl => new Toast(toastEl)); // eslint-disable-line no-undef
|
||||
|
||||
for (let i = 0; i < toastList.length; i++) {
|
||||
if (toastList[i].isShown() === false) {
|
||||
|
||||
21
frontend/src/js/_tooltip.js
Normal file
21
frontend/src/js/_tooltip.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import tippy from 'tippy.js';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
import 'tippy.js/themes/light-border.css';
|
||||
|
||||
|
||||
function initiateTooltips() {
|
||||
const currentDataTheme = document.documentElement.getAttribute('data-theme') || '';
|
||||
let theme;
|
||||
|
||||
if (currentDataTheme.endsWith('_dark')) {
|
||||
theme = 'light-border';
|
||||
} else if (currentDataTheme.endsWith('_light')) {
|
||||
theme = 'dark';
|
||||
}
|
||||
|
||||
tippy('[data-tippy-content]', {
|
||||
theme: theme
|
||||
});
|
||||
}
|
||||
|
||||
window.initiateTooltips = initiateTooltips;
|
||||
@@ -4,10 +4,9 @@
|
||||
|
||||
// Standalone component implementations
|
||||
@use "offcanvas";
|
||||
@use "dropdown";
|
||||
@use "transitions";
|
||||
|
||||
// Bootstrap utilities (if needed)
|
||||
// @import "bootstrap/scss/bootstrap-utilities";
|
||||
|
||||
// Bootstrap-specific utility classes
|
||||
.dropdown-toggle.dropdown-toggle-no-icon::after {
|
||||
|
||||
402
frontend/src/styles/_dropdown.scss
Normal file
402
frontend/src/styles/_dropdown.scss
Normal file
@@ -0,0 +1,402 @@
|
||||
// Dropdown component - Standalone implementation
|
||||
// Decoupled from Bootstrap 5, integrated with DaisyUI colors
|
||||
|
||||
@use "sass:list";
|
||||
@use "sass:map";
|
||||
|
||||
// Variables
|
||||
$dropdown-min-width: 10rem !default;
|
||||
$dropdown-padding-x: 0.5rem !default;
|
||||
$dropdown-padding-y: 0.5rem !default;
|
||||
$dropdown-spacer: 0.125rem !default;
|
||||
$dropdown-font-size: 1rem !default;
|
||||
$dropdown-border-radius: 0.375rem !default;
|
||||
$dropdown-border-width: 1px !default;
|
||||
$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;
|
||||
$dropdown-divider-margin-y: 0.5rem !default;
|
||||
$dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !default;
|
||||
$dropdown-item-padding-y: 0.25rem !default;
|
||||
$dropdown-item-padding-x: 1rem !default;
|
||||
$dropdown-header-padding-x: 1rem !default;
|
||||
$dropdown-header-padding-y: 0.5rem !default;
|
||||
$dropdown-z-index: 1000 !default;
|
||||
|
||||
// Caret variables
|
||||
$caret-width: 0.3em !default;
|
||||
$caret-vertical-align: 0.255em !default;
|
||||
$caret-spacing: 0.255em !default;
|
||||
$enable-caret: true !default;
|
||||
|
||||
// Font
|
||||
$font-weight-normal: 400 !default;
|
||||
$font-size-sm: 0.875rem !default;
|
||||
|
||||
// Breakpoints
|
||||
$breakpoints: (
|
||||
xs: 0,
|
||||
sm: 576px,
|
||||
md: 768px,
|
||||
lg: 992px,
|
||||
xl: 1200px,
|
||||
xxl: 1400px) !default;
|
||||
|
||||
// Mixins
|
||||
@mixin media-breakpoint-up($name) {
|
||||
$min: map.get($breakpoints, $name
|
||||
);
|
||||
|
||||
@if $min and $min >0 {
|
||||
@media (min-width: $min) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
// Caret mixins
|
||||
@mixin caret-down($width: $caret-width) {
|
||||
border-top: $width solid;
|
||||
border-right: $width solid transparent;
|
||||
border-bottom: 0;
|
||||
border-left: $width solid transparent;
|
||||
}
|
||||
|
||||
@mixin caret-up($width: $caret-width) {
|
||||
border-top: 0;
|
||||
border-right: $width solid transparent;
|
||||
border-bottom: $width solid;
|
||||
border-left: $width solid transparent;
|
||||
}
|
||||
|
||||
@mixin caret-end($width: $caret-width) {
|
||||
border-top: $width solid transparent;
|
||||
border-right: 0;
|
||||
border-bottom: $width solid transparent;
|
||||
border-left: $width solid;
|
||||
}
|
||||
|
||||
@mixin caret-start($width: $caret-width) {
|
||||
border-top: $width solid transparent;
|
||||
border-right: $width solid;
|
||||
border-bottom: $width solid transparent;
|
||||
}
|
||||
|
||||
@mixin caret($direction: down,
|
||||
$width: $caret-width,
|
||||
$spacing: $caret-spacing,
|
||||
$vertical-align: $caret-vertical-align) {
|
||||
@if $enable-caret {
|
||||
&::after {
|
||||
display: inline-block;
|
||||
margin-left: $spacing;
|
||||
vertical-align: $vertical-align;
|
||||
content: "";
|
||||
|
||||
@if $direction ==down {
|
||||
@include caret-down($width);
|
||||
}
|
||||
|
||||
@else if $direction ==up {
|
||||
@include caret-up($width);
|
||||
}
|
||||
|
||||
@else if $direction ==end {
|
||||
@include caret-end($width);
|
||||
}
|
||||
}
|
||||
|
||||
@if $direction ==start {
|
||||
&::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&::before {
|
||||
display: inline-block;
|
||||
margin-right: $spacing;
|
||||
vertical-align: $vertical-align;
|
||||
content: "";
|
||||
@include caret-start($width);
|
||||
}
|
||||
}
|
||||
|
||||
&:empty::after {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin border-radius($radius: $dropdown-border-radius) {
|
||||
border-radius: $radius;
|
||||
}
|
||||
|
||||
@mixin border-top-radius($radius) {
|
||||
border-top-left-radius: $radius;
|
||||
border-top-right-radius: $radius;
|
||||
}
|
||||
|
||||
@mixin border-bottom-radius($radius) {
|
||||
border-bottom-left-radius: $radius;
|
||||
border-bottom-right-radius: $radius;
|
||||
}
|
||||
|
||||
@mixin gradient-bg($color) {
|
||||
background-color: $color;
|
||||
}
|
||||
|
||||
@mixin box-shadow($shadow) {
|
||||
box-shadow: $shadow;
|
||||
}
|
||||
|
||||
@mixin font-size($size) {
|
||||
font-size: $size;
|
||||
}
|
||||
|
||||
// Breakpoint infix function
|
||||
@function breakpoint-infix($name, $breakpoints) {
|
||||
@if $name ==xs {
|
||||
@return "";
|
||||
}
|
||||
|
||||
@return "-#{$name}";
|
||||
}
|
||||
|
||||
// The dropdown wrapper (`<div>`)
|
||||
.dropup,
|
||||
.dropend,
|
||||
.dropdown,
|
||||
.dropstart,
|
||||
.dropup-center,
|
||||
.dropdown-center {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
white-space: nowrap;
|
||||
|
||||
// Generate the caret automatically
|
||||
@include caret();
|
||||
}
|
||||
|
||||
// The dropdown menu
|
||||
.dropdown-menu {
|
||||
// CSS variables using DaisyUI colors
|
||||
--dropdown-z-index: #{$dropdown-z-index};
|
||||
--dropdown-min-width: #{$dropdown-min-width};
|
||||
--dropdown-padding-x: #{$dropdown-padding-x};
|
||||
--dropdown-padding-y: #{$dropdown-padding-y};
|
||||
--dropdown-spacer: #{$dropdown-spacer};
|
||||
--dropdown-font-size: #{$dropdown-font-size};
|
||||
--dropdown-color: var(--color-base-content);
|
||||
--dropdown-bg: var(--color-base-300);
|
||||
--dropdown-border-color: var(--color-base-300);
|
||||
--dropdown-border-radius: #{$dropdown-border-radius};
|
||||
--dropdown-border-width: #{$dropdown-border-width};
|
||||
--dropdown-inner-border-radius: #{$dropdown-inner-border-radius};
|
||||
--dropdown-divider-bg: var(--color-base-300);
|
||||
--dropdown-divider-margin-y: #{$dropdown-divider-margin-y};
|
||||
--dropdown-box-shadow: #{$dropdown-box-shadow};
|
||||
--dropdown-link-color: var(--color-base-content);
|
||||
--dropdown-link-hover-color: var(--color-base-content);
|
||||
--dropdown-link-hover-bg: var(--color-base-200);
|
||||
--dropdown-link-active-color: var(--color-primary-content);
|
||||
--dropdown-link-active-bg: var(--color-primary);
|
||||
--dropdown-link-disabled-color: var(--color-base-content, #adb5bd);
|
||||
--dropdown-item-padding-x: #{$dropdown-item-padding-x};
|
||||
--dropdown-item-padding-y: #{$dropdown-item-padding-y};
|
||||
--dropdown-header-color: var(--color-base-content);
|
||||
--dropdown-header-padding-x: #{$dropdown-header-padding-x};
|
||||
--dropdown-header-padding-y: #{$dropdown-header-padding-y};
|
||||
|
||||
position: absolute;
|
||||
z-index: var(--dropdown-z-index);
|
||||
display: none; // none by default, but block on "open" of the menu
|
||||
min-width: var(--dropdown-min-width);
|
||||
padding: var(--dropdown-padding-y) var(--dropdown-padding-x);
|
||||
margin: 0; // Override default margin of ul
|
||||
color: var(--dropdown-color);
|
||||
text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)
|
||||
list-style: none;
|
||||
background-color: var(--dropdown-bg);
|
||||
background-clip: padding-box;
|
||||
border: var(--dropdown-border-width) solid var(--dropdown-border-color);
|
||||
@include border-radius(var(--dropdown-border-radius));
|
||||
@include box-shadow(var(--dropdown-box-shadow));
|
||||
|
||||
&[data-bs-popper] {
|
||||
top: 100%;
|
||||
left: 0;
|
||||
margin-top: var(--dropdown-spacer);
|
||||
}
|
||||
|
||||
@if $dropdown-padding-y ==0 {
|
||||
|
||||
>.dropdown-item:first-child,
|
||||
>li:first-child .dropdown-item {
|
||||
@include border-top-radius(var(--dropdown-inner-border-radius));
|
||||
}
|
||||
|
||||
>.dropdown-item:last-child,
|
||||
>li:last-child .dropdown-item {
|
||||
@include border-bottom-radius(var(--dropdown-inner-border-radius));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive positioning
|
||||
@each $breakpoint in map.keys($breakpoints) {
|
||||
@include media-breakpoint-up($breakpoint) {
|
||||
$infix: breakpoint-infix($breakpoint, $breakpoints);
|
||||
|
||||
.dropdown-menu#{$infix}-start {
|
||||
--bs-position: start;
|
||||
|
||||
&[data-bs-popper] {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu#{$infix}-end {
|
||||
--bs-position: end;
|
||||
|
||||
&[data-bs-popper] {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allow for dropdowns to go bottom up (aka, dropup-menu)
|
||||
.dropup {
|
||||
.dropdown-menu[data-bs-popper] {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
margin-top: 0;
|
||||
margin-bottom: var(--dropdown-spacer);
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
@include caret(up);
|
||||
}
|
||||
}
|
||||
|
||||
.dropend {
|
||||
.dropdown-menu[data-bs-popper] {
|
||||
top: 0;
|
||||
right: auto;
|
||||
left: 100%;
|
||||
margin-top: 0;
|
||||
margin-left: var(--dropdown-spacer);
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
@include caret(end);
|
||||
|
||||
&::after {
|
||||
vertical-align: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropstart {
|
||||
.dropdown-menu[data-bs-popper] {
|
||||
top: 0;
|
||||
right: 100%;
|
||||
left: auto;
|
||||
margin-top: 0;
|
||||
margin-right: var(--dropdown-spacer);
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
@include caret(start);
|
||||
|
||||
&::before {
|
||||
vertical-align: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dividers (basically an `<hr>`) within the dropdown
|
||||
.dropdown-divider {
|
||||
height: 0;
|
||||
margin: var(--dropdown-divider-margin-y) 0;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid var(--dropdown-divider-bg);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// Links, buttons, and more within the dropdown menu
|
||||
.dropdown-item {
|
||||
display: block;
|
||||
width: 100%; // For `<button>`s
|
||||
padding: var(--dropdown-item-padding-y) var(--dropdown-item-padding-x);
|
||||
clear: both;
|
||||
font-weight: $font-weight-normal;
|
||||
color: var(--dropdown-link-color);
|
||||
text-align: inherit; // For `<button>`s
|
||||
text-decoration: none;
|
||||
white-space: nowrap; // prevent links from randomly breaking onto new lines
|
||||
background-color: transparent; // For `<button>`s
|
||||
border: 0; // For `<button>`s
|
||||
@include border-radius(0);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: var(--dropdown-link-hover-color);
|
||||
@include gradient-bg(var(--dropdown-link-hover-bg));
|
||||
}
|
||||
|
||||
&.active,
|
||||
&:active {
|
||||
color: var(--dropdown-link-active-color);
|
||||
text-decoration: none;
|
||||
@include gradient-bg(var(--dropdown-link-active-bg));
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
&:disabled {
|
||||
color: var(--dropdown-link-disabled-color);
|
||||
pointer-events: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// Dropdown section headers
|
||||
.dropdown-header {
|
||||
display: block;
|
||||
padding: var(--dropdown-header-padding-y) var(--dropdown-header-padding-x);
|
||||
margin-bottom: 0; // for use with heading elements
|
||||
color: var(--dropdown-header-color);
|
||||
white-space: nowrap; // as with > li > a
|
||||
}
|
||||
|
||||
// Dropdown text
|
||||
.dropdown-item-text {
|
||||
display: block;
|
||||
padding: var(--dropdown-item-padding-y) var(--dropdown-item-padding-x);
|
||||
color: var(--dropdown-link-color);
|
||||
}
|
||||
|
||||
// Dark dropdowns
|
||||
.dropdown-menu-dark {
|
||||
--dropdown-color: #dee2e6;
|
||||
--dropdown-bg: #343a40;
|
||||
--dropdown-border-color: var(--color-base-300);
|
||||
--dropdown-box-shadow: #{$dropdown-box-shadow};
|
||||
--dropdown-link-color: #dee2e6;
|
||||
--dropdown-link-hover-color: #fff;
|
||||
--dropdown-divider-bg: var(--color-base-300);
|
||||
--dropdown-link-hover-bg: rgba(255, 255, 255, 0.15);
|
||||
--dropdown-link-active-color: var(--color-primary-content);
|
||||
--dropdown-link-active-bg: var(--color-primary);
|
||||
--dropdown-link-disabled-color: #adb5bd;
|
||||
--dropdown-header-color: #adb5bd;
|
||||
}
|
||||
Reference in New Issue
Block a user