feat: oh look, more changes

This commit is contained in:
Herculino Trotta
2025-11-10 00:28:16 -03:00
parent 7e37948616
commit b38ed37bc5
27 changed files with 636 additions and 624 deletions

View File

@@ -159,7 +159,7 @@ class RestoreForm(forms.Form):
self.helper.form_method = "post"
self.helper.layout = Layout(
"zip_file",
HTML("<hr />"),
HTML('<hr class="hr my-3"/>'),
"users",
"accounts",
"currencies",

View File

@@ -1,73 +1,72 @@
{% load i18n %}
<div class="container px-md-3 py-3 column-gap-5">
<c-ui.fab-single-action
url="{% url 'account_group_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Account Groups' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Account Groups' %}</div>
{% endspaceless %}
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-body overflow-x-auto">
<div class="card-body">
{% if account_groups %}
<c-config.search></c-config.search>
<table class="table table-hover">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
</thead>
<tbody>
{% for account_group in account_groups %}
<tr class="account_group">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
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-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'account_group_delete' pk=account_group.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"></i></a>
{% if not account_group.owner %}
<a class="btn btn-secondary btn-sm join-item text-warning"
role="button"
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 %}
{% if user == account_group.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
</div>
</td>
<td>{{ account_group.name }}</td>
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for account_group in account_groups %}
<tr class="account_group">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
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>
{% if not account_group.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
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 %}
{% if user == account_group.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
<a class="btn btn-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'account_group_delete' pk=account_group.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"></i></a>
</div>
</td>
<td>{{ account_group.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<c-msg.empty title="{% translate "No account groups" %}" remove-padding></c-msg.empty>
{% endif %}

View File

@@ -1,95 +1,96 @@
{% load i18n %}
<c-ui.fab-single-action
url="{% url 'account_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container px-md-3 py-3 column-gap-5">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Accounts' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Accounts' %}</div>
{% endspaceless %}
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-body overflow-x-auto">
<div class="card-body">
{% if accounts %}
<c-config.search></c-config.search>
<table class="table table-hover whitespace-nowrap">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
<th scope="col">{% translate 'Group' %}</th>
<th scope="col">{% translate 'Currency' %}</th>
<th scope="col">{% translate 'Exchange Currency' %}</th>
<th scope="col">{% translate 'Is Asset' %}</th>
<th scope="col">{% translate 'Archived' %}</th>
</tr>
</thead>
<tbody>
{% for account in accounts %}
<tr class="account">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
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-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'account_delete' pk=account.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"></i></a>
{% if not account.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
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 %}
{% if user == account.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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-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 %}
<i class="fa-solid fa-eye-slash fa-fw"></i>
{% endif %}
</a>
</div>
</td>
<td>{{ account.name }}</td>
<td>{{ account.group.name }}</td>
<td>{{ account.currency }}</td>
<td>{% if account.exchange_currency %}{{ account.exchange_currency }}{% else %}-{% endif %}</td>
<td>{% if account.is_asset %}<i class="fa-solid fa-solid fa-check text-success"></i>{% endif %}</td>
<td>{% if account.is_archived %}<i class="fa-solid fa-solid fa-check text-success"></i>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
<c-config.search></c-config.search>
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
<th scope="col">{% translate 'Group' %}</th>
<th scope="col">{% translate 'Currency' %}</th>
<th scope="col">{% translate 'Exchange Currency' %}</th>
<th scope="col">{% translate 'Is Asset' %}</th>
<th scope="col">{% translate 'Archived' %}</th>
</tr>
</thead>
<tbody>
{% for account in accounts %}
<tr class="account">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
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>
{% if not account.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
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 %}
{% if user == account.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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-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 %}
<i class="fa-solid fa-eye-slash fa-fw"></i>
{% endif %}
</a>
<a class="btn btn-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'account_delete' pk=account.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"></i></a>
</div>
</td>
<td>{{ account.name }}</td>
<td>{{ account.group.name }}</td>
<td>{{ account.currency }}</td>
<td>{% if account.exchange_currency %}{{ account.exchange_currency }}{% else %}-{% endif %}</td>
<td>{% if account.is_asset %}<i class="fa-solid fa-solid fa-check text-success"></i>{% endif %}</td>
<td>{% if account.is_archived %}<i class="fa-solid fa-solid fa-check text-success"></i>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<c-msg.empty title="{% translate "No accounts" %}" remove-padding></c-msg.empty>
<c-msg.empty title="{% translate "No accounts" %}" remove-padding></c-msg.empty>
{% endif %}
</div>
</div>

View File

@@ -1,27 +1,29 @@
{% load i18n %}
<div class="container px-md-3 py-3 column-gap-5">
<c-ui.fab-single-action
url="{% url 'category_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Categories' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Categories' %}</div>
{% endspaceless %}
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-header bg-base-200 p-4">
<div role="tablist" class="tabs tabs-lifted">
<button class="tab tab-active" data-bs-toggle="tab" type="button" role="tab" aria-selected="true" hx-get="{% url 'categories_table_active' %}" hx-trigger="load, click" hx-target="#categories-table">{% translate 'Active' %}</button>
<button class="tab" hx-get="{% url 'categories_table_archived' %}" hx-target="#categories-table" data-bs-toggle="tab" type="button" role="tab" aria-selected="false">{% translate 'Archived' %}</button>
<div class="card-header bg-base-200 p-4 rounded-box">
<div role="tablist" class="tabs tabs-border">
<input type="radio" name="installment_plan_tabs" class="tab" aria-label="{% translate 'Active' %}"
checked="checked"
hx-get="{% url 'categories_table_active' %}" hx-trigger="load, click" hx-target="#categories-table"
hx-indicator="#categories-table"/>
<input type="radio" name="installment_plan_tabs" class="tab" aria-label="{% translate 'Archived' %}"
hx-get="{% url 'categories_table_archived' %}" hx-trigger="click" hx-target="#categories-table"
hx-indicator="#categories-table"/>
</div>
</div>
<div class="card-body">
<div id="categories-table"></div>
<div id="categories-table" class="show-loading"></div>
</div>
</div>
</div>

View File

@@ -6,68 +6,70 @@
<div class="show-loading" hx-get="{% url 'categories_table_archived' %}" hx-trigger="updated from:window"
hx-swap="outerHTML">
{% endif %}
{% if categories %}
<div class="overflow-x-auto">
{% if categories %}
<div>
<c-config.search></c-config.search>
<table class="table table-hover">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
<th scope="col">{% translate 'Muted' %}</th>
</tr>
</thead>
<tbody>
{% for category in categories %}
<tr class="category">
<td class="table-col-auto text-center">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-swap="innerHTML"
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-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'category_delete' category_id=category.id %}"
hx-trigger='confirmed'
hx-swap="innerHTML"
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"></i></a>
{% if not category.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
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 %}
{% if user == category.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
</div>
</td>
<td>{{ category.name }}</td>
<td>
{% if category.mute %}<i class="fa-solid fa-check text-success"></i>{% endif %}
</td>
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
<th scope="col">{% translate 'Muted' %}</th>
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for category in categories %}
<tr class="category">
<td class="table-col-auto text-center">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-swap="innerHTML"
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>
{% if not category.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
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 %}
{% if user == category.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
<a class="btn btn-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'category_delete' category_id=category.id %}"
hx-trigger='confirmed'
hx-swap="innerHTML"
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"></i></a>
</div>
</td>
<td>{{ category.name }}</td>
<td>
{% if category.mute %}<i class="fa-solid fa-check text-success"></i>{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<c-msg.empty title="{% translate "No categories" %}" remove-padding></c-msg.empty>
{% endif %}
{% else %}
<c-msg.empty title="{% translate "No categories" %}" remove-padding></c-msg.empty>
{% endif %}
</div>

View File

@@ -1,7 +1,7 @@
{% if form.non_field_errors %}
<div class="alert alert-error">
{% if form_error_title %}<h4 class="font-bold">{{ form_error_title }}</h4>{% endif %}
<ul class="m-0 list-disc list-inside">
<ul class="m-0 list-inside">
{{ form.non_field_errors|unordered_list }}
</ul>
</div>

View File

@@ -1,9 +1,8 @@
{% if formset.non_form_errors %}
<div class="alert alert-error">
{% if formset_error_title %}<h4 class="font-bold">{{ formset_error_title }}</h4>{% endif %}
<ul class="m-0 list-disc list-inside">
<ul class="m-0 list-inside">
{{ formset.non_form_errors|unordered_list }}
</ul>
</div>
{% endif %}

View File

@@ -20,7 +20,7 @@
</div>
{% endif %}
<div class="fieldset">
<input type="{{ widget.data.type }}" name="{{ widget.data.name }}" class="file-input {% if widget.data.attrs.class %} {{ widget.data.attrs.class }}{% endif %}{% if field.errors %} file-input-error{% endif %}"{% if field.field.disabled %} disabled{% endif %}{% for name, value in widget.data.attrs.items %}{% if value is not False and name != 'class' %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}>
<input type="{{ widget.data.type }}" name="{{ widget.data.name }}" class="file-input w-full {% if widget.data.attrs.class %} {{ widget.data.attrs.class }}{% endif %}{% if field.errors %} file-input-error{% endif %}"{% if field.field.disabled %} disabled{% endif %}{% for name, value in widget.data.attrs.items %}{% if value is not False and name != 'class' %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}>
{% include 'crispy-daisyui/layout/help_text_and_errors.html' %}
</div>
{% endfor %}

View File

@@ -1,7 +1,7 @@
{% if field.help_text %}
{% if help_text_inline %}
<span id="{{ field.auto_id }}_helptext" class="text-xs text-base-content/60 text-wrap">{{ field.help_text|safe}}</span>
<span id="{{ field.auto_id }}_helptext" class="label text-wrap">{{ field.help_text|safe}}</span>
{% else %}
<p {% if field.auto_id %}id="{{ field.auto_id }}_helptext" {% endif %}class="label">{{ field.help_text|safe }}</p>
<p {% if field.auto_id %}id="{{ field.auto_id }}_helptext" {% endif %}class="label text-wrap">{{ field.help_text|safe }}</p>
{% endif %}
{% endif %}

View File

@@ -4,18 +4,14 @@
{{ field }}
{% else %}
<{% if tag %}{{ tag }}{% else %}fieldset{% endif %} id="div_{{ field.auto_id }}" class="fieldset mt-2 {% if wrapper_class %} {{ wrapper_class }}{% endif %}{% if field.css_classes %} {{ field.css_classes }}{% endif %}">
<label class="label flex flex-row gap-3">
<div>
<label class="label">
{% if field.errors %}
{% crispy_field field 'class' 'toggle toggle-error toggle-sm' %}
{% else %}
{% crispy_field field 'class' 'toggle toggle-sm' %}
{% endif %}
</div>
<div>
{{ field.label }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
{% include 'crispy-daisyui/layout/help_text_and_errors.html' %}
</div>
</label>
</{% if tag %}{{ tag }}{% else %}fieldset{% endif %}>
{% endif %}

View File

@@ -1,15 +1,12 @@
{% load i18n %}
<div class="container px-md-3 py-3 column-gap-5">
<c-ui.fab-single-action
url="{% url 'currency_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Currencies' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Currencies' %}</div>
{% endspaceless %}
</div>
@@ -17,7 +14,8 @@
<div class="card-body overflow-x-auto">
{% if currencies %}
<c-config.search></c-config.search>
<table class="table table-hover">
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
@@ -56,6 +54,7 @@
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<c-msg.empty title="{% translate "No currencies" %}" remove-padding></c-msg.empty>
{% endif %}

View File

@@ -1,8 +1,8 @@
{% load currency_display %}
{% load i18n %}
<c-ui.fab-single-action
url="{% url 'dca_entry_add' strategy_id=strategy.id %}"
hx_target="#generic-offcanvas">
url="{% url 'dca_entry_add' strategy_id=strategy.id %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container-fluid">
<div class="row">
@@ -12,7 +12,8 @@
</div>
<div class="text-sm lg:text-right mt-2 lg:mt-0">
<div class="mb-2">
<span class="badge badge-secondary rounded-full">{{ strategy.payment_currency.name }}</span> x <span class="badge badge-secondary rounded-full">{{ strategy.target_currency.name }}</span>
<span class="badge badge-secondary rounded-full">{{ strategy.payment_currency.name }}</span> x <span
class="badge badge-secondary rounded-full">{{ strategy.target_currency.name }}</span>
</div>
<div>
{% if strategy.current_price %}
@@ -21,17 +22,17 @@
:prefix="strategy.payment_currency.prefix"
:suffix="strategy.payment_currency.suffix"
:decimal_places="strategy.payment_currency.decimal_places">
• {{ strategy.current_price.1|date:"SHORT_DATETIME_FORMAT" }}
• {{ strategy.current_price.1|date:"SHORT_DATETIME_FORMAT" }}
</c-amount.display>
{% else %}
{% else %}
<div class="text-error">{% trans "No exchange rate available" %}</div>
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
<div class="row g-3">
<div class="row g-3 g-3">
<div class="col-12 lg:col-6">
<div class="card bg-base-100 shadow">
<div class="card-body overflow-x-auto">
@@ -121,7 +122,7 @@
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="col-12 lg:col-6 flex flex-col gap-3">
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
<div>
<div class="card bg-base-100 shadow h-full">
@@ -207,9 +208,8 @@
</div>
</div>
</div>
<div class="grid mt-4">
<div class="col-span-12"
_="on htmx:afterSettle from #strategy-details
<div
_="on htmx:afterSettle from #strategy-details
set perfomancectx to #performanceChart.getContext('2d')
js(perfomancectx)
new Chart(perfomancectx, {
@@ -218,7 +218,9 @@
labels: [{% for entry in entries_data %}'{{ entry.entry.date|date:"SHORT_DATE_FORMAT" }}'{% if not forloop.last %}, {% endif %}{% endfor %}],
datasets: [{
label: '{% trans "P/L %" %}',
data: [{% for entry in entries_data %}{{ entry.profit_loss_percentage|floatformat:"-40u" }}{% if not forloop.last %}, {% endif %}{% endfor %}],
data: [
{% for entry in entries_data %}{{ entry.profit_loss_percentage|floatformat:"-40u" }}{% if not forloop.last %}, {% endif %}{% endfor %}],
stepped: true,
segment: {
borderColor: ctx => {
@@ -276,17 +278,15 @@
}
})
end">
<div class="card bg-base-100 shadow">
<div class="card-body">
<h5 class="card-title">{% trans "Performance Over Time" %}</h5>
<canvas id="performanceChart"></canvas>
</div>
<div class="card bg-base-100 shadow">
<div class="card-body">
<h5 class="card-title">{% trans "Performance Over Time" %}</h5>
<canvas id="performanceChart"></canvas>
</div>
</div>
</div>
<div class="grid mt-4">
<div class="col-span-12"
_="on htmx:afterSettle from #strategy-details
<div
_="on htmx:afterSettle from #strategy-details
set pricectx to #priceChart.getContext('2d')
set priceData to {{ price_comparison_data|safe }}
js(pricectx, priceData)
@@ -379,77 +379,73 @@
}
})
end">
<div class="card bg-base-100 shadow">
<div class="card-body">
<h5 class="card-title">{% trans "Entry Price vs Current Price" %}</h5>
<canvas id="priceChart"></canvas>
</div>
<div class="card bg-base-100 shadow">
<div class="card-body">
<h5 class="card-title">{% trans "Entry Price vs Current Price" %}</h5>
<canvas id="priceChart"></canvas>
</div>
</div>
</div>
<div class="grid mt-4">
<div class="col-span-12"
_="on htmx:afterSettle from #strategy-details
<div class="col-12"
_="on htmx:afterSettle from #strategy-details
set frequencyctx to #frequencyChart.getContext('2d')
js(frequencyctx)
new Chart(frequencyctx, {
type: 'line',
data: {
labels: {{ investment_frequency.labels|safe }},
datasets: [{
label: '{% trans "Days Between Investments" %}',
data: {{ investment_frequency.intervals_line|safe }},
borderColor: 'rgba(54, 162, 235, 1)',
backgroundColor: 'rgba(54, 162, 235, 0.1)',
fill: false,
tension: 0
}]
},
options: {
responsive: true,
scales: {
x: {
grid: {
display: true
},
title: {
display: false,
},
ticks: {
display: false
}
},
y: {
beginAtZero: false,
title: {
display: false
}
}
},
plugins: {
tooltip: {
mode: 'index',
intersect: false
},
legend: {
display: false,
},
title: {
display: false,
}
}
}
})
end
">
<div class="card bg-base-100 shadow">
<div class="card-body">
<h5 class="card-title">{% trans "Investment Frequency" %}</h5>
<p class="text-base-content/60">
{% trans "The straighter the blue line, the more consistent your DCA strategy is." %}
</p>
<canvas id="frequencyChart"></canvas>
</div>
type: 'line',
data: {
labels: {{ investment_frequency.labels|safe }},
datasets: [{
label: '{% trans "Days Between Investments" %}',
data: {{ investment_frequency.intervals_line|safe }},
borderColor: 'rgba(54, 162, 235, 1)',
backgroundColor: 'rgba(54, 162, 235, 0.1)',
fill: false,
tension: 0
}]
},
options: {
responsive: true,
scales: {
x: {
grid: {
display: true
},
title: {
display: false,
},
ticks: {
display: false
}
},
y: {
beginAtZero: false,
title: {
display: false
}
}
},
plugins: {
tooltip: {
mode: 'index',
intersect: false
},
legend: {
display: false,
},
title: {
display: false,
}
}
}
})
end">
<div class="card bg-base-100 shadow">
<div class="card-body">
<h5 class="card-title">{% trans "Investment Frequency" %}</h5>
<p class="text-base-content/60">
{% trans "The straighter the blue line, the more consistent your DCA strategy is." %}
</p>
<canvas id="frequencyChart"></canvas>
</div>
</div>
</div>

View File

@@ -1,27 +1,29 @@
{% load i18n %}
<div class="container px-md-3 py-3 column-gap-5">
<c-ui.fab-single-action
url="{% url 'entity_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Entities' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Entities' %}</div>
{% endspaceless %}
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-header bg-base-200 p-4">
<div role="tablist" class="tabs tabs-lifted">
<button class="tab tab-active" data-bs-toggle="tab" type="button" role="tab" aria-selected="true" hx-get="{% url 'entities_table_active' %}" hx-trigger="load, click" hx-target="#entities-table">{% translate 'Active' %}</button>
<button class="tab" hx-get="{% url 'entities_table_archived' %}" hx-target="#entities-table" data-bs-toggle="tab" type="button" role="tab" aria-selected="false">{% translate 'Archived' %}</button>
<div class="card-header bg-base-200 p-4 rounded-box">
<div role="tablist" class="tabs tabs-border">
<input type="radio" name="installment_plan_tabs" class="tab" aria-label="{% translate 'Active' %}"
checked="checked"
hx-get="{% url 'entities_table_active' %}" hx-trigger="load, click" hx-target="#entities-table"
hx-indicator="#entities-table"/>
<input type="radio" name="installment_plan_tabs" class="tab" aria-label="{% translate 'Archived' %}"
hx-get="{% url 'entities_table_archived' %}" hx-trigger="click" hx-target="#entities-table"
hx-indicator="#entities-table"/>
</div>
</div>
<div class="card-body">
<div id="entities-table"></div>
<div id="entities-table" class="show-loading"></div>
</div>
</div>
</div>

View File

@@ -7,61 +7,63 @@
hx-swap="outerHTML">
{% endif %}
{% if entities %}
<div class="overflow-x-auto">
<div>
<c-config.search></c-config.search>
<table class="table table-hover">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr class="entity">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-swap="innerHTML"
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-error btn-sm join-item"
role="button"
hx-swap="innerHTML"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'entity_delete' entity_id=entity.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"></i></a>
{% if not entity.owner %}
<a class="btn btn-secondary btn-sm join-item text-warning"
role="button"
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 %}
{% if user == entity.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
</div>
</td>
<td>{{ entity.name }}</td>
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for entity in entities %}
<tr class="entity">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-swap="innerHTML"
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>
{% if not entity.owner %}
<a class="btn btn-secondary btn-sm join-item text-warning"
role="button"
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 %}
{% if user == entity.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
<a class="btn btn-error btn-sm join-item"
role="button"
hx-swap="innerHTML"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'entity_delete' entity_id=entity.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"></i></a>
</div>
</td>
<td>{{ entity.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<c-msg.empty title="{% translate "No entities" %}" remove-padding></c-msg.empty>

View File

@@ -1,32 +1,28 @@
{% load currency_display %}
{% load i18n %}
<div class="container px-md-3 py-3 column-gap-5">
<c-ui.fab-single-action
url="{% url 'exchange_rate_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Exchange Rates' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Exchange Rates' %}</div>
{% endspaceless %}
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-header bg-base-200 p-4">
<div role="tablist" class="tabs tabs-lifted">
<button class="tab tab-active" hx-indicator="#exchange-rates-table" data-bs-toggle="tab" type="button"
role="tab" aria-controls="home-tab-pane" aria-selected="true"
hx-get="{% url 'exchange_rates_list_pair' %}" hx-trigger="load, click"
hx-target="#exchange-rates-table" aria-controls="#exchange-rates-table">{% translate 'All' %}</button>
<div class="card-header bg-base-200 p-4 rounded-box">
<div role="tablist" class="tabs tabs-border">
<input type="radio" name="exchange_rates_tabs" class="tab" aria-label="{% translate 'All' %}"
checked="checked"
hx-get="{% url 'exchange_rates_list_pair' %}" hx-trigger="load, click" hx-target="#exchange-rates-table"
hx-indicator="#exchange-rates-table" />
{% for pair in pairings %}
<button class="tab" hx-indicator="#exchange-rates-table"
hx-get="{% url 'exchange_rates_list_pair' %}"
hx-vals='{"from": "{{ pair.1 }}", "to": "{{ pair.2 }}"}'
hx-target="#exchange-rates-table" data-bs-toggle="tab" type="button" role="tab"
aria-controls="#exchange-rates-table" aria-selected="false">{{ pair.0 }}</button>
<input type="radio" name="exchange_rates_tabs" class="tab" aria-label="{{ pair.0 }}"
hx-get="{% url 'exchange_rates_list_pair' %}" hx-trigger="click" hx-target="#exchange-rates-table"
hx-indicator="#exchange-rates-table" hx-vals='{"from": "{{ pair.1 }}", "to": "{{ pair.2 }}"}' />
{% endfor %}
</div>
</div>

View File

@@ -37,9 +37,9 @@
_="install prompt_swal"><i class="fa-solid fa-trash fa-fw"></i></a>
</div>
</td>
<td class="w-1/4">{{ exchange_rate.date|date:"SHORT_DATETIME_FORMAT" }}</td>
<td class="w-1/4"><span class="badge badge-secondary rounded-full">{{ exchange_rate.from_currency.name }}</span> x <span class="badge badge-secondary rounded-full">{{ exchange_rate.to_currency.name }}</span></td>
<td class="w-1/4">1 {{ exchange_rate.from_currency.name }} ≅ {% currency_display amount=exchange_rate.rate prefix=exchange_rate.to_currency.prefix suffix=exchange_rate.to_currency.suffix decimal_places=exchange_rate.to_currency.decimal_places%}</td>
<td>{{ exchange_rate.date|date:"SHORT_DATETIME_FORMAT" }}</td>
<td><span class="badge badge-secondary rounded-full">{{ exchange_rate.from_currency.name }}</span> x <span class="badge badge-secondary rounded-full">{{ exchange_rate.to_currency.name }}</span></td>
<td>1 {{ exchange_rate.from_currency.name }} ≅ {% currency_display amount=exchange_rate.rate prefix=exchange_rate.to_currency.prefix suffix=exchange_rate.to_currency.suffix decimal_places=exchange_rate.to_currency.decimal_places string=True %}</td>
</tr>
{% endfor %}
</tbody>

View File

@@ -1,5 +1,5 @@
{% load i18n %}
<div class="offcanvas-header flex justify-between items-center border-b border-base-content/10">
<div class="offcanvas-header flex justify-between items-center border-b border-base-content/10 bg-base-300">
<h5 class="offcanvas-title font-medium">{% block title %}{% endblock %}</h5>
<button type="button" class="btn btn-ghost btn-sm btn-circle" aria-label="{% trans 'Close' %}" data-bs-dismiss="offcanvas"><i class="fa-solid fa-xmark"></i></button>
</div>

View File

@@ -3,6 +3,7 @@
init
set selects to <select/> in me
for x in selects
remove .select from x
js(it)
TomSelect(it)
end

View File

@@ -1,13 +1,13 @@
<script type="text/hyperscript">
init
call initiateTooltips()
end
on htmx:afterSettle
call initiateTooltips()
end
on tooltips
call initiateTooltips()
end
</script>
{#<script type="text/hyperscript">#}
{#init#}
{# call initiateTooltips()#}
{#end#}
{##}
{#on htmx:afterSettle#}
{# call initiateTooltips()#}
{#end#}
{# #}
{#on tooltips#}
{# call initiateTooltips()#}
{#end#}
{#</script>#}

View File

@@ -7,7 +7,7 @@
{% block title %}{% translate 'Currency Converter' %}{% endblock %}
{% block content %}
<div class="container px-md-3 py-3 column-gap-5"
<div class="container"
_="install init_tom_select
install init_datepicker">
<div class="text-3xl font-bold font-mono w-full mb-3">
@@ -57,39 +57,32 @@
<i class="fa-solid fa-rotate me-2"></i><span>{% trans 'Invert' %}</span>
</div>
</div>
<hr class="my-4">
<hr class="hr my-4">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{% for currency, data in rate_map.items %}
<div>
<c-ui.info-card color="yellow" title="{{ currency }}">
{% for rate in data.rates.values %}
<div class="flex justify-between items-baseline mt-2">
<div class="text-right font-mono">
<div class="text-base-content/60">
{# <c-amount.display#}
{# :amount="1"#}
{# :prefix="data.prefix"#}
{# :suffix="data.suffix"#}
{# :decimal_places="data.decimal_places"></c-amount.display>#}
<div class="card-data-section">
{% for rate_currency, rate in data.rates.items %}
<div class="card-data-row">
<span class="card-data-label">{{ rate_currency }}</span>
<div class="card-data-values">
{% if rate.rate %}
<c-amount.display
:amount="rate.rate"
:prefix="rate.prefix"
:suffix="rate.suffix"
:decimal_places="rate.decimal_places"></c-amount.display>
{% else %}
<span class="font-semibold">-</span>
{% endif %}
</div>
</div>
<div class="dotted-line flex-grow"></div>
{% if currency.income_projected != 0 %}
<div class="text-right font-mono text-green-400">
<c-amount.display
:amount="rate.rate"
:prefix="rate.prefix"
:suffix="rate.suffix"
:decimal_places="rate.decimal_places"></c-amount.display>
</div>
{% else %}
<div class="text-right font-mono">-</div>
{% endif %}
</div>
{% endfor %}
{% endfor %}
</div>
</c-ui.info-card>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}

View File

@@ -1,15 +1,12 @@
{% load i18n %}
<div class="container px-md-3 py-3 column-gap-5">
<c-ui.fab-single-action
url="{% url 'transaction_rule_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Rules' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Rules' %}</div>
{% endspaceless %}
</div>
@@ -17,75 +14,77 @@
<div class="card-body overflow-x-auto">
{% if transaction_rules %}
<c-config.search></c-config.search>
<table class="table table-hover">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col" class="table-col-auto"></th>
<th scope="col" class="table-col-auto">{% translate 'Order' %}</th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
</thead>
<tbody>
{% for rule in transaction_rules %}
<tr class="transaction_rule">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
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-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'transaction_rule_delete' transaction_rule_id=rule.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"></i></a>
{% if not rule.owner %}
<a class="btn btn-secondary btn-sm join-item text-warning"
role="button"
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 %}
{% if user == rule.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
</div>
</td>
<td class="table-col-auto">
<a class="no-underline"
role="button"
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 %}
<i class="fa-solid fa-toggle-off text-red-400"></i>{% endif %}
</a>
</td>
<td class="table-col-auto text-center">
<div>{{ rule.order }}</div>
</td>
<td>
<div>{{ rule.name }}</div>
<div class="text-gray-400">{{ rule.description }}</div>
</td>
<div class="overflow-x-auto">
<table class="table table-hover">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col" class="table-col-auto"></th>
<th scope="col" class="table-col-auto">{% translate 'Order' %}</th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for rule in transaction_rules %}
<tr class="transaction_rule">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
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>
{% if not rule.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
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 %}
{% if user == rule.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
<a class="btn btn-error btn-sm join-item"
role="button"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'transaction_rule_delete' transaction_rule_id=rule.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"></i></a>
</div>
</td>
<td class="table-col-auto">
<a class="no-underline"
role="button"
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 %}
<i class="fa-solid fa-toggle-off text-red-400"></i>{% endif %}
</a>
</td>
<td class="table-col-auto text-center">
<div>{{ rule.order }}</div>
</td>
<td>
<div>{{ rule.name }}</div>
<div class="text-gray-400">{{ rule.description }}</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<c-msg.empty title="{% translate "No rules" %}" remove-padding></c-msg.empty>
{% endif %}

View File

@@ -8,16 +8,16 @@
<div hx-get="{% url 'transaction_rule_view' transaction_rule_id=transaction_rule.id %}"
hx-trigger="updated from:window" hx-target="closest .offcanvas" class="show-loading">
<div class="text-2xl">{{ transaction_rule.name }}</div>
<div class="text-base text-gray-400">{{ transaction_rule.description }}</div>
<hr>
<div class="text-subtle">{{ transaction_rule.description }}</div>
<hr class="hr my-3">
<div class="my-3">
<div class="text-xl mb-2">{% translate 'If transaction...' %}</div>
<div class="card bg-base-100 shadow-xl">
<div class="card card-border shadow">
<div class="card-body">
{{ transaction_rule.trigger }}
</div>
<div class="card-footer text-end">
<a class="no-underline text-gray-400 p-1"
<a class="btn btn-ghost btn-xs"
role="button"
data-tippy-content="{% translate "Edit" %}"
hx-get="{% url 'transaction_rule_edit' transaction_rule_id=transaction_rule.id %}"
@@ -29,10 +29,11 @@
<div class="my-3">
<div class="text-xl mb-2">{% translate 'Then...' %}</div>
<div class="row g-3">
{% for action in all_actions %}
{% if action.action_type == "edit_transaction" %}
<div class="card bg-base-100 shadow-xl mb-3">
<div class="card-header bg-base-200 p-4">
<div class="card bg-base-100 card-border shadow">
<div class="card-header">
<div>
{% if action.order != 0 %}<span class="badge badge-secondary">{{ action.order }}</span>{% endif %}
<span class="badge badge-primary">{% trans 'Edit transaction' %}</span>
@@ -46,14 +47,14 @@
<div class="bg-base-200 rounded-3xl mt-3 p-2">{{ action.value }}</div>
</div>
<div class="card-footer text-end">
<a class="no-underline text-gray-400 p-1"
<a class="btn btn-ghost btn-xs"
role="button"
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"
<a class="btn btn-ghost btn-xs text-error"
role="button"
data-tippy-content="{% translate 'Delete' %}"
hx-delete="{% url 'transaction_rule_action_delete' transaction_rule_action_id=action.id %}"
@@ -68,8 +69,8 @@
</div>
</div>
{% elif action.action_type == "update_or_create_transaction" %}
<div class="card bg-base-100 shadow-xl mb-3">
<div class="card-header bg-base-200 p-4">
<div class="card shadow">
<div class="card-header">
<div>
{% if action.order != 0 %}<span class="badge badge-secondary">{{ action.order }}</span>{% endif %}
<span class="badge badge-primary">{% trans 'Update or create transaction' %}</span>
@@ -79,14 +80,14 @@
<div>{% trans 'Edit to view' %}</div>
</div>
<div class="card-footer text-end">
<a class="no-underline text-gray-400 p-1"
<a class="btn btn-ghost btn-xs"
role="button"
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"
<a class="btn btn-ghost btn-xs text-error"
role="button"
data-tippy-content="{% translate 'Delete' %}"
hx-delete="{% url 'update_or_create_transaction_rule_action_delete' pk=action.id %}"
@@ -102,16 +103,17 @@
</div>
{% endif %}
{% empty %}
<div class="card bg-base-100 shadow-xl">
<div class="card shadow">
<div class="card-body">
{% translate 'This rule has no actions' %}
</div>
</div>
{% endfor %}
<hr>
</div>
<hr class="hr my-5">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-2">
<div class="dropdown">
<button class="btn btn-outline btn-primary no-underline w-full" type="button" data-bs-toggle="dropdown"
<button class="btn btn-secondary w-full" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
<i class="fa-solid fa-flask-vial me-2"></i>{% translate 'Test' %}
</button>
@@ -134,7 +136,7 @@
</ul>
</div>
<div class="dropdown">
<button class="btn btn-outline btn-primary no-underline w-full" type="button" data-bs-toggle="dropdown"
<button class="btn btn-primary w-full" type="button" data-bs-toggle="dropdown"
aria-expanded="false">
<i class="fa-solid fa-circle-plus me-2"></i>{% translate 'Add new' %}
</button>

View File

@@ -1,27 +1,29 @@
{% load i18n %}
<div class="container px-md-3 py-3 column-gap-5">
<c-ui.fab-single-action
url="{% url 'tag_add' %}"
hx_target="#generic-offcanvas">
</c-ui.fab-single-action>
<div class="container">
<div class="text-3xl font-bold font-mono w-full mb-3">
{% spaceless %}
<div>{% translate 'Tags' %}<span>
<a class="no-underline text-2xl p-1 category-action"
role="button"
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>
</span></div>
<div>{% translate 'Tags' %}</div>
{% endspaceless %}
</div>
<div class="card bg-base-100 shadow-xl">
<div class="card-header bg-base-200 p-4">
<div role="tablist" class="tabs tabs-lifted">
<button class="tab tab-active" data-bs-toggle="tab" type="button" role="tab" aria-selected="true" hx-get="{% url 'tags_table_active' %}" hx-trigger="load, click" hx-target="#tags-table">{% translate 'Active' %}</button>
<button class="tab" hx-get="{% url 'tags_table_archived' %}" hx-target="#tags-table" data-bs-toggle="tab" type="button" role="tab" aria-selected="false">{% translate 'Archived' %}</button>
<div class="card-header bg-base-200 p-4 rounded-box">
<div role="tablist" class="tabs tabs-border">
<input type="radio" name="installment_plan_tabs" class="tab" aria-label="{% translate 'Active' %}"
checked="checked"
hx-get="{% url 'tags_table_active' %}" hx-trigger="load, click" hx-target="#tags-table"
hx-indicator="#tags-table"/>
<input type="radio" name="installment_plan_tabs" class="tab" aria-label="{% translate 'Archived' %}"
hx-get="{% url 'tags_table_archived' %}" hx-trigger="click" hx-target="#tags-table"
hx-indicator="#tags-table"/>
</div>
</div>
<div class="card-body">
<div id="tags-table"></div>
<div id="tags-table" class="show-loading"></div>
</div>
</div>
</div>

View File

@@ -7,61 +7,63 @@
hx-swap="outerHTML">
{% endif %}
{% if tags %}
<div class="overflow-x-auto">
<div>
<c-config.search></c-config.search>
<table class="table table-hover">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
</thead>
<tbody>
{% for tag in tags %}
<tr class="tag">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-swap="innerHTML"
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-error btn-sm join-item"
role="button"
hx-swap="innerHTML"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'tag_delete' tag_id=tag.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"></i></a>
{% if not tag.owner %}
<a class="btn btn-secondary btn-sm join-item text-warning"
role="button"
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 %}
{% if user == tag.owner %}
<a class="btn btn-secondary btn-sm join-item text-primary"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
</div>
</td>
<td>{{ tag.name }}</td>
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
<th scope="col">{% translate 'Name' %}</th>
</tr>
{% endfor %}
</tbody>
</table>
</thead>
<tbody>
{% for tag in tags %}
<tr class="tag">
<td class="table-col-auto">
<div class="join" role="group" aria-label="{% translate 'Actions' %}">
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-swap="innerHTML"
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>
{% if not tag.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
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 %}
{% if user == tag.owner %}
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
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 %}
<a class="btn btn-error btn-sm join-item"
role="button"
hx-swap="innerHTML"
data-tippy-content="{% translate "Delete" %}"
hx-delete="{% url 'tag_delete' tag_id=tag.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"></i></a>
</div>
</td>
<td>{{ tag.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<c-msg.empty title="{% translate "No tags" %}" remove-padding></c-msg.empty>