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,23 +1,21 @@
{% 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">
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
@@ -35,6 +33,22 @@
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" %}"
@@ -45,22 +59,6 @@
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>
@@ -68,6 +66,7 @@
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<c-msg.empty title="{% translate "No account groups" %}" remove-padding></c-msg.empty>
{% endif %}

View File

@@ -1,23 +1,21 @@
{% 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">
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
@@ -40,25 +38,15 @@
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"
<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 text-primary"
<a class="btn btn-secondary btn-sm join-item"
role="button"
hx-target="#generic-offcanvas"
hx-swap="innerHTML"
@@ -69,13 +57,25 @@
<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 %}">
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>
@@ -88,6 +88,7 @@
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<c-msg.empty title="{% translate "No accounts" %}" remove-padding></c-msg.empty>
{% endif %}

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,10 +6,11 @@
<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">
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th scope="col" class="table-col-auto"></th>
@@ -29,6 +30,22 @@
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" %}"
@@ -40,22 +57,6 @@
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>
@@ -67,7 +68,8 @@
</tbody>
</table>
</div>
{% else %}
</div>
{% else %}
<c-msg.empty title="{% translate "No categories" %}" remove-padding></c-msg.empty>
{% endif %}
{% 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

@@ -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 %}
@@ -31,7 +32,7 @@
</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,8 +208,7 @@
</div>
</div>
</div>
<div class="grid mt-4">
<div class="col-span-12"
<div
_="on htmx:afterSettle from #strategy-details
set perfomancectx to #performanceChart.getContext('2d')
js(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 => {
@@ -283,9 +285,7 @@
</div>
</div>
</div>
</div>
<div class="grid mt-4">
<div class="col-span-12"
<div
_="on htmx:afterSettle from #strategy-details
set pricectx to #priceChart.getContext('2d')
set priceData to {{ price_comparison_data|safe }}
@@ -386,9 +386,7 @@
</div>
</div>
</div>
</div>
<div class="grid mt-4">
<div class="col-span-12"
<div class="col-12"
_="on htmx:afterSettle from #strategy-details
set frequencyctx to #frequencyChart.getContext('2d')
js(frequencyctx)
@@ -439,9 +437,8 @@
}
}
}
})
end
">
})
end">
<div class="card bg-base-100 shadow">
<div class="card-body">
<h5 class="card-title">{% trans "Investment Frequency" %}</h5>
@@ -454,5 +451,4 @@
</div>
</div>
</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,9 +7,10 @@
hx-swap="outerHTML">
{% endif %}
{% if entities %}
<div class="overflow-x-auto">
<div>
<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>
@@ -28,6 +29,22 @@
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"
@@ -39,22 +56,6 @@
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>
@@ -63,6 +64,7 @@
</tbody>
</table>
</div>
</div>
{% else %}
<c-msg.empty title="{% translate "No entities" %}" remove-padding></c-msg.empty>
{% endif %}

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,36 +57,29 @@
<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>
</div>
<div class="dotted-line flex-grow"></div>
{% if currency.income_projected != 0 %}
<div class="text-right font-mono text-green-400">
<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>
</div>
{% else %}
<div class="text-right font-mono">-</div>
<span class="font-semibold">-</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</c-ui.info-card>
</div>
{% endfor %}

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,6 +14,7 @@
<div class="card-body overflow-x-auto">
{% if transaction_rules %}
<c-config.search></c-config.search>
<div class="overflow-x-auto">
<table class="table table-hover">
<thead>
<tr>
@@ -37,6 +35,22 @@
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" %}"
@@ -47,22 +61,6 @@
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">
@@ -86,6 +84,7 @@
{% 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,9 +7,10 @@
hx-swap="outerHTML">
{% endif %}
{% if tags %}
<div class="overflow-x-auto">
<div>
<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>
@@ -28,6 +29,22 @@
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"
@@ -39,22 +56,6 @@
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>
@@ -63,6 +64,7 @@
</tbody>
</table>
</div>
</div>
{% else %}
<c-msg.empty title="{% translate "No tags" %}" remove-padding></c-msg.empty>
{% endif %}

View File

@@ -1,4 +1,4 @@
import tippy from 'tippy.js';
import { delegate } from 'tippy.js';
import 'tippy.js/dist/tippy.css';
import 'tippy.js/themes/light-border.css';
@@ -13,10 +13,15 @@ function initiateTooltips() {
theme = 'dark';
}
tippy('[data-tippy-content]', {
delegate(document.body, {
target: '[data-tippy-content]',
theme: theme,
zIndex: 1050,
zIndex: 1100,
content(reference) {
return reference.getAttribute('data-tippy-content');
},
});
}
window.initiateTooltips = initiateTooltips;
// Call it once on page load
initiateTooltips();

View File

@@ -9,7 +9,7 @@ $offcanvas-z-index: 1090 !default;
$offcanvas-backdrop-z-index: 1040 !default;
$offcanvas-width: 400px !default;
$offcanvas-height: 30vh !default;
$offcanvas-padding: 0.5rem !default;
$offcanvas-padding: 1rem !default;
$offcanvas-transition-duration: 0.3s !default;
$offcanvas-backdrop-opacity: 0.5 !default;
@@ -66,7 +66,7 @@ $breakpoints: (
--offcanvas-padding-x: #{$offcanvas-padding};
--offcanvas-padding-y: #{$offcanvas-padding};
--offcanvas-color: var(--color-base-content);
--offcanvas-bg: var(--color-base-300);
--offcanvas-bg: var(--root-bg);
--offcanvas-border-width: var(--border);
--offcanvas-border-color: var(--color-base-100);
--offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);

View File

@@ -148,7 +148,7 @@
/* Card Data Display Styles */
.card-data-section {
@apply space-y-1;
@apply space-y-2;
}
.card-data-row {
@@ -176,6 +176,20 @@
@layer components {
.card {
@apply bg-base-100;
}
.card .card-header {
@apply bg-base-200;
@apply p-2;
}
.card .card-footer {
@apply bg-base-200;
@apply p-2;
}
.fab {
@layer daisyui.component {
> :nth-child(n+7) {