mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-04-22 08:38:35 +02:00
feat: guess what, more changes
This commit is contained in:
13
app/apps/common/templatetags/crispy_extra.py
Normal file
13
app/apps/common/templatetags/crispy_extra.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from django import forms, template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def is_input(field):
|
||||
return isinstance(field.field.widget, forms.TextInput)
|
||||
|
||||
|
||||
@register.filter
|
||||
def is_textarea(field):
|
||||
return isinstance(field.field.widget, forms.Textarea)
|
||||
@@ -10,8 +10,7 @@ from apps.common.widgets.decimal import ArbitraryDecimalDisplayNumberInput
|
||||
from apps.common.widgets.tom_select import TomSelect, TransactionSelect
|
||||
from apps.dca.models import DCAEntry, DCAStrategy
|
||||
from apps.transactions.models import Transaction, TransactionCategory, TransactionTag
|
||||
from crispy_bootstrap5.bootstrap5 import BS5Accordion
|
||||
from crispy_forms.bootstrap import AccordionGroup, FormActions
|
||||
from crispy_forms.bootstrap import AccordionGroup, FormActions, Accordion
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import HTML, Column, Layout, Row
|
||||
from django import forms
|
||||
@@ -154,7 +153,7 @@ class DCAEntryForm(forms.ModelForm):
|
||||
Column("amount_received"),
|
||||
),
|
||||
"notes",
|
||||
BS5Accordion(
|
||||
Accordion(
|
||||
AccordionGroup(
|
||||
_("Create transaction"),
|
||||
Switch("create_transaction"),
|
||||
|
||||
@@ -9,8 +9,7 @@ from apps.rules.models import (
|
||||
)
|
||||
from apps.transactions.forms import BulkEditTransactionForm
|
||||
from apps.transactions.models import Transaction
|
||||
from crispy_bootstrap5.bootstrap5 import BS5Accordion
|
||||
from crispy_forms.bootstrap import AccordionGroup, FormActions
|
||||
from crispy_forms.bootstrap import AccordionGroup, FormActions, Accordion
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import HTML, Column, Field, Layout, Row
|
||||
from django import forms
|
||||
@@ -208,7 +207,7 @@ class UpdateOrCreateTransactionRuleActionForm(forms.ModelForm):
|
||||
|
||||
self.helper.layout = Layout(
|
||||
"order",
|
||||
BS5Accordion(
|
||||
Accordion(
|
||||
AccordionGroup(
|
||||
_("Search Criteria"),
|
||||
Field("filter", rows=1),
|
||||
@@ -219,7 +218,7 @@ class UpdateOrCreateTransactionRuleActionForm(forms.ModelForm):
|
||||
),
|
||||
Column(
|
||||
Field("search_type", rows=1),
|
||||
css_class="form-group col-md-8",
|
||||
css_class="col-span-12 md:col-span-8",
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -229,7 +228,7 @@ class UpdateOrCreateTransactionRuleActionForm(forms.ModelForm):
|
||||
),
|
||||
Column(
|
||||
Field("search_is_paid", rows=1),
|
||||
css_class="form-group col-md-8",
|
||||
css_class="col-span-12 md:col-span-8",
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -239,7 +238,7 @@ class UpdateOrCreateTransactionRuleActionForm(forms.ModelForm):
|
||||
),
|
||||
Column(
|
||||
Field("search_mute", rows=1),
|
||||
css_class="form-group col-md-8",
|
||||
css_class="col-span-12 md:col-span-8",
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -249,7 +248,7 @@ class UpdateOrCreateTransactionRuleActionForm(forms.ModelForm):
|
||||
),
|
||||
Column(
|
||||
Field("search_account", rows=1),
|
||||
css_class="form-group col-md-8",
|
||||
css_class="col-span-12 md:col-span-8",
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -259,7 +258,7 @@ class UpdateOrCreateTransactionRuleActionForm(forms.ModelForm):
|
||||
),
|
||||
Column(
|
||||
Field("search_entities", rows=1),
|
||||
css_class="form-group col-md-8",
|
||||
css_class="col-span-12 md:col-span-8",
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -482,7 +481,7 @@ class DryRunUpdatedTransactionForm(BulkEditTransactionForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.helper.layout.insert(0, "transaction")
|
||||
self.helper.layout.insert(1, HTML("<hr/>"))
|
||||
self.helper.layout.insert(1, HTML('<hr class="hr my-3" />'))
|
||||
|
||||
# Change submit button
|
||||
self.helper.layout[-1] = FormActions(
|
||||
|
||||
@@ -564,7 +564,7 @@ def dry_run_rule_updated(request, pk):
|
||||
|
||||
response = render(
|
||||
request,
|
||||
"rules/fragments/transaction_rule/dry_run/created.html",
|
||||
"rules/fragments/transaction_rule/dry_run/updated.html",
|
||||
{"form": form, "rule": rule, "logs": logs, "results": results},
|
||||
)
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ from apps.transactions.models import (
|
||||
TransactionEntity,
|
||||
TransactionTag,
|
||||
)
|
||||
from crispy_bootstrap5.bootstrap5 import BS5Accordion
|
||||
from crispy_forms.bootstrap import AccordionGroup, AppendedText, FormActions
|
||||
from crispy_forms.bootstrap import AccordionGroup, AppendedText, FormActions, Accordion
|
||||
from crispy_forms.helper import FormHelper
|
||||
from crispy_forms.layout import (
|
||||
HTML,
|
||||
@@ -166,7 +165,7 @@ class TransactionForm(forms.ModelForm):
|
||||
),
|
||||
"description",
|
||||
Field("amount", inputmode="decimal"),
|
||||
BS5Accordion(
|
||||
Accordion(
|
||||
AccordionGroup(
|
||||
_("More"),
|
||||
"entities",
|
||||
|
||||
@@ -9,14 +9,13 @@
|
||||
<form hx-post="{% url 'account_reconciliation' %}">
|
||||
{% csrf_token %}
|
||||
{{ form.management_form }}
|
||||
<div class="space-y-2" id="balanceAccordionFlush">
|
||||
<div class="join join-vertical w-full" id="balanceAccordionFlush">
|
||||
{% for form in form.forms %}
|
||||
<div class="collapse collapse-arrow bg-base-100 border-base-300 border-2">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title font-medium text-sm">
|
||||
<c-ui.components.collapse>
|
||||
<c-slot name="title">
|
||||
{% if form.account_group %}<span class="badge badge-primary badge-outline me-2">{{ form.account_group.name }}</span>{% endif %}{{ form.account_name }}
|
||||
</div>
|
||||
<div class="collapse-content bg-base-200">
|
||||
</c-slot>
|
||||
<c-slot name="content">
|
||||
<div class="fieldset">
|
||||
<span class="fieldset-legend">{% translate 'Current balance' %}</span>
|
||||
<div data-amount="{{ form.current_balance|floatformat:"-40u" }}"
|
||||
@@ -54,11 +53,10 @@
|
||||
}
|
||||
).format(diff)
|
||||
then set formatted_string to `${prefix}${format_new_amount}${suffix}`
|
||||
then put formatted_string into me if diff else
|
||||
put '-' into me">-</div>
|
||||
then put formatted_string into me if diff else put '-' into me">-</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</c-slot>
|
||||
</c-ui.components.collapse>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load markdown %}
|
||||
{% load i18n %}
|
||||
<div
|
||||
class="transaction {% if transaction.type == "EX" %}expense{% else %}income{% endif %} group/transaction relative">
|
||||
class="transaction {% if transaction.type == "EX" %}expense{% else %}income{% endif %} group/transaction">
|
||||
<div class="flex my-1">
|
||||
{% if not disable_selection or not dummy %}
|
||||
<label class="px-3 flex! items-center justify-center">
|
||||
@@ -161,7 +161,7 @@
|
||||
<button class="btn btn-soft btn-sm transaction-action" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa-solid fa-ellipsis fa-fw"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-md-start menu w-max relative">
|
||||
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-md-start menu">
|
||||
<div class="absolute inset-[0rem_-3rem_-3rem_-3rem] pointer-events-auto -z-10"></div>
|
||||
{% if transaction.account.is_untracked_by %}
|
||||
<li class="menu-disabled" aria-disabled="true">
|
||||
|
||||
21
app/templates/cotton/ui/components/collapse.html
Normal file
21
app/templates/cotton/ui/components/collapse.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<div class="bg-base-100 border-base-300 border-2 join-item {{ base_classes }}"
|
||||
x-data="{ expanded: {% if active %}true{% else %}false{% endif %} }">
|
||||
|
||||
<div class="font-medium text-sm cursor-pointer p-4 flex w-full items-center justify-between gap-4 text-left {{ title_classes }}"
|
||||
@click="expanded = ! expanded">
|
||||
|
||||
<div>
|
||||
{{ title }}
|
||||
</div>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke="currentColor" class="size-5 shrink-0 transition" aria-hidden="true" x-bind:class="expanded ? 'rotate-180' : ''">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5"></path>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="bg-base-200 p-4 {{ content_classes }}"
|
||||
x-show="expanded"
|
||||
x-collapse>
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,9 +1,10 @@
|
||||
<div class="collapse collapse-arrow bg-base-100 border border-base-300{% if div.css_class %} {{div.css_class}}{% endif %}">
|
||||
<input type="radio" name="{{ div.data_parent }}" {% if div.active %}checked="checked"{% endif %} />
|
||||
<div class="collapse-title font-semibold">
|
||||
{{ div.name }}
|
||||
</div>
|
||||
<div class="collapse-content">
|
||||
{{ fields|safe }}
|
||||
</div>
|
||||
</div>
|
||||
<c-ui.components.collapse
|
||||
title_class="join-item"
|
||||
:active="div.active">
|
||||
<c-slot name="title">
|
||||
{{ div.name }}
|
||||
</c-slot>
|
||||
<c-slot name="content">
|
||||
{{ fields|safe }}
|
||||
</c-slot>
|
||||
</c-ui.components.collapse>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{% load crispy_forms_field %}
|
||||
{% load crispy_extra %}
|
||||
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
@@ -39,7 +40,7 @@
|
||||
{% include 'crispy-daisyui/layout/field_file.html' %}
|
||||
{% elif field|is_select %}
|
||||
{% if field.errors %}
|
||||
{% crispy_field field 'class' 'select-error input-error w-full' %}
|
||||
{% crispy_field field 'class' 'select-error w-full' %}
|
||||
{% else %}
|
||||
{% crispy_field field 'class' '' %}
|
||||
{% endif %}
|
||||
@@ -49,6 +50,18 @@
|
||||
{% else %}
|
||||
{% crispy_field field 'class' 'checkbox w-full' %}
|
||||
{% endif %}
|
||||
{% elif field|is_input %}
|
||||
{% if field.errors %}
|
||||
{% crispy_field field 'class' 'input input-error w-full' %}
|
||||
{% else %}
|
||||
{% crispy_field field 'class' 'input w-full' %}
|
||||
{% endif %}
|
||||
{% elif field|is_textarea %}
|
||||
{% if field.errors %}
|
||||
{% crispy_field field 'class' 'textarea textarea-error w-full' %}
|
||||
{% else %}
|
||||
{% crispy_field field 'class' 'textarea w-full' %}
|
||||
{% endif %}
|
||||
{% elif field.errors %}
|
||||
{% crispy_field field 'class' 'input input-error w-full' %}
|
||||
{% else %}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</legend>
|
||||
{% endif %}
|
||||
|
||||
<label class="input w-full {% if input_size %} {{ input_size }}{% endif %}{% if field.errors %} input-error{% endif %}">
|
||||
<label class="{% if input_size %} {{ input_size }}{% endif %}{% if field.errors %} input-error{% endif %}">
|
||||
{# prepend #}
|
||||
{% if crispy_prepended_text %}
|
||||
{{ crispy_prepended_text }}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
{% load currency_display %}
|
||||
{% load i18n %}
|
||||
<div class="container px-md-3 py-3 column-gap-5">
|
||||
<c-ui.fab-single-action
|
||||
url="{% url 'automatic_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 'Automatic Exchange Rates' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'automatic_exchange_rate_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
</span></div>
|
||||
<div>{% translate 'Automatic Exchange Rates' %}</div>
|
||||
{% endspaceless %}
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-header bg-base-200 p-4 text-base-content/70">
|
||||
<div class="card-header rounded-box">
|
||||
<button type="button" hx-get="{% url 'automatic_exchange_rate_force_fetch' %}"
|
||||
class="btn btn-outline btn-primary btn-sm">{% trans 'Fetch all' %}</button>
|
||||
class="btn btn-primary btn-sm">{% trans 'Fetch all' %}</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if services %}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% load i18n %}
|
||||
<div class="card-body show-loading" hx-get="{% url 'exchange_rates_list_pair' %}" hx-trigger="updated from:window" hx-swap="outerHTML" hx-vals='{"page": "{{ page_obj.number }}", "from": "{{ from_currency|default_if_none:"" }}", "to": "{{ to_currency|default_if_none:"" }}"}'>
|
||||
{% if page_obj %}
|
||||
<c-config.search></c-config.search>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-hover whitespace-nowrap">
|
||||
<thead>
|
||||
|
||||
@@ -4,26 +4,20 @@
|
||||
{% block title %}{% translate 'Export and Restore' %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row d-flex flex-row align-items-center justify-content-center my-5">
|
||||
<div class="text-center w-auto mb-3">
|
||||
<button class="btn btn-outline-success d-flex flex-column align-items-center justify-content-center p-3"
|
||||
style="width: 100px; height: 100px;"
|
||||
hx-get="{% url 'export_form' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-download mb-1"></i>
|
||||
<span>{% trans 'Export' %}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="text-center w-auto mb-3">
|
||||
<button class="btn btn-outline-primary d-flex flex-column align-items-center justify-content-center p-3"
|
||||
style="width: 100px; height: 100px;"
|
||||
hx-get="{% url 'restore_form' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-upload mb-1"></i>
|
||||
<span>{% trans 'Restore' %}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex items-center justify-center min-h-[90dvh]">
|
||||
<div class="flex gap-4">
|
||||
<button class="btn btn-error btn-square w-24 h-24 flex flex-col items-center justify-center"
|
||||
hx-get="{% url 'export_form' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-download mb-1"></i>
|
||||
<span class="text-sm">{% trans 'Export' %}</span>
|
||||
</button>
|
||||
<button class="btn btn-success btn-square w-24 h-24 flex flex-col items-center justify-center"
|
||||
hx-get="{% url 'restore_form' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-upload mb-1"></i>
|
||||
<span class="text-sm">{% trans 'Restore' %}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
{% load i18n %}
|
||||
<div class="container px-md-3 py-3 column-gap-5">
|
||||
<c-components.fab>
|
||||
<c-components.fab_menu_button
|
||||
color="primary"
|
||||
hx_target="#generic-offcanvas"
|
||||
url="{% url 'import_profiles_add' %}"
|
||||
icon="fa-solid fa-plus"
|
||||
title="{% trans 'New' %}"></c-components.fab_menu_button>
|
||||
|
||||
<c-components.fab_menu_button
|
||||
color="primary"
|
||||
hx_target="#persistent-generic-offcanvas-left"
|
||||
url="{% url 'import_presets_list' %}"
|
||||
icon="fa-solid fa-file-code"
|
||||
title="{% trans 'From preset' %}"></c-components.fab_menu_button>
|
||||
</c-components.fab>
|
||||
|
||||
<div class="container">
|
||||
<div class="text-3xl font-bold font-mono w-full mb-3">
|
||||
{% spaceless %}
|
||||
<div>{% translate 'Import Profiles' %}<span>
|
||||
<span class="dropdown" data-tippy-content="{% translate "Add" %}">
|
||||
<a class="no-underline text-2xl p-1" role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
data-bs-title="{% translate "Add" %}" aria-expanded="false">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i>
|
||||
</a>
|
||||
<ul class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
|
||||
<li><a role="button"
|
||||
hx-get="{% url 'import_profiles_add' %}"
|
||||
hx-target="#generic-offcanvas">{% trans 'New' %}</a></li>
|
||||
<li><a role="button"
|
||||
hx-get="{% url 'import_presets_list' %}"
|
||||
hx-target="#persistent-generic-offcanvas-left">{% trans 'From preset' %}</a></li>
|
||||
</ul>
|
||||
</span>
|
||||
</span></div>
|
||||
<div>{% translate 'Import Profiles' %}</div>
|
||||
{% endspaceless %}
|
||||
</div>
|
||||
|
||||
@@ -26,58 +26,60 @@
|
||||
<div class="card-body overflow-x-auto">
|
||||
{% if profiles %}
|
||||
<c-config.search></c-config.search>
|
||||
<table class="table table-hover whitespace-nowrap">
|
||||
<thead>
|
||||
<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 'Version' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for profile in profiles %}
|
||||
<tr class="profile">
|
||||
<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 'import_profile_edit' profile_id=profile.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-success"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Runs" %}"
|
||||
hx-get="{% url 'import_profile_runs_list' profile_id=profile.id %}"
|
||||
hx-target="#persistent-generic-offcanvas-left">
|
||||
<tr class="profile">
|
||||
<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 'import_profile_edit' profile_id=profile.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Runs" %}"
|
||||
hx-get="{% url 'import_profile_runs_list' profile_id=profile.id %}"
|
||||
hx-target="#persistent-generic-offcanvas-left">
|
||||
<i class="fa-solid fa-person-running fa-fw"></i></a>
|
||||
<a class="btn btn-secondary btn-sm join-item text-primary"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Import" %}"
|
||||
hx-get="{% url 'import_run_add' profile_id=profile.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<a class="btn btn-secondary btn-sm join-item"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Import" %}"
|
||||
hx-get="{% url 'import_run_add' profile_id=profile.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-file-import fa-fw"></i></a>
|
||||
<a class="btn btn-error btn-sm join-item"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'import_profile_delete' profile_id=profile.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>{{ profile.name }}</td>
|
||||
<td>{{ profile.get_version_display }}</td>
|
||||
</tr>
|
||||
<a class="btn btn-error btn-sm join-item"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Delete" %}"
|
||||
hx-delete="{% url 'import_profile_delete' profile_id=profile.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>{{ profile.name }}</td>
|
||||
<td>{{ profile.get_version_display }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<c-msg.empty title="{% translate "No import profiles" %}" remove-padding></c-msg.empty>
|
||||
<c-msg.empty title="{% translate "No import profiles" %}" remove-padding></c-msg.empty>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
hx-target="#generic-offcanvas">
|
||||
|
||||
<div class="col">
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card bg-base-100 shadow">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ preset.name }}</h5>
|
||||
<hr>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
{% for run in runs %}
|
||||
<div class="col">
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card bg-base-100 shadow">
|
||||
<div class="card-header bg-base-200 p-4 text-sm {% if run.status == run.Status.QUEUED %}text-base-content{% elif run.status == run.Status.PROCESSING %}text-warning{% elif run.status == run.Status.FINISHED %}text-success{% else %}text-error{% endif %}">
|
||||
<span><i class="fa-solid {% if run.status == run.Status.QUEUED %}fa-hourglass-half{% elif run.status == run.Status.PROCESSING %}fa-spinner{% elif run.status == run.Status.FINISHED %}fa-check{% else %}fa-xmark{% endif %} fa-fw me-2"></i>{{ run.get_status_display }}</span>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% block title %}{% translate 'Logs for' %} #{{ run.id }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="card bg-base-100 shadow-xl max-h-full overflow-auto">
|
||||
<div class="card bg-base-100 shadow max-h-full overflow-auto">
|
||||
<div class="card-body">
|
||||
{{ run.logs|linebreaks }}
|
||||
</div>
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
</label>
|
||||
|
||||
<div class="dropdown dropdown-top dropdown-end">
|
||||
<div tabindex="0" role="button" class="btn btn-secondary btn-sm">
|
||||
<div role="button" class="btn btn-secondary btn-sm" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa-solid fa-cog"></i>
|
||||
</div>
|
||||
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-1 w-52 p-2 shadow">
|
||||
<ul class="dropdown-menu menu">
|
||||
<li><a
|
||||
hx-get="{% url 'user_settings' %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
{% vite_hmr_client %}
|
||||
|
||||
{% vite_asset 'main.js' defer=True %}
|
||||
{% comment %} {% vite_asset 'sweetalert2.js' defer=True %}
|
||||
{% vite_asset 'select.js' defer=True %}
|
||||
{% vite_asset 'datepicker.js' %}
|
||||
{% vite_asset 'autosize.js' defer=True %} {% endcomment %}
|
||||
|
||||
{% include 'includes/scripts/hyperscript/init_tom_select.html' %}
|
||||
{% include 'includes/scripts/hyperscript/init_date_picker.html' %}
|
||||
@@ -15,11 +11,7 @@
|
||||
{% include 'includes/scripts/hyperscript/htmx_error_handler.html' %}
|
||||
{% include 'includes/scripts/hyperscript/sounds.html' %}
|
||||
{% include 'includes/scripts/hyperscript/swal.html' %}
|
||||
|
||||
{% comment %} {% vite_asset 'htmx.js' defer=True %}
|
||||
{% vite_asset 'charts.js' %}
|
||||
|
||||
{% vite_asset 'style.js' %} {% endcomment %}
|
||||
{% include 'includes/scripts/hyperscript/autosize.html' %}
|
||||
|
||||
<script>
|
||||
let tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
|
||||
12
app/templates/includes/scripts/hyperscript/autosize.html
Normal file
12
app/templates/includes/scripts/hyperscript/autosize.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<script type="text/hyperscript">
|
||||
init
|
||||
for elem in <.textarea/>
|
||||
autosize(elem)
|
||||
end
|
||||
end
|
||||
on htmx:afterSettle
|
||||
for elem in <.textarea/>
|
||||
autosize(elem)
|
||||
end
|
||||
end
|
||||
</script>
|
||||
@@ -6,9 +6,8 @@
|
||||
<div class="join join-vertical w-full" id="emergency-fund-accordion">
|
||||
{% for id, data in data.items %}
|
||||
{% if data.average %}
|
||||
<div class="collapse collapse-arrow join-item bg-base-100 border-base-200 border">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-base font-medium">
|
||||
<c-ui.components.collapse>
|
||||
<c-slot name="title">
|
||||
<span>
|
||||
<span class="text-subtle">{% trans "You've spent an average of" %}</span>
|
||||
<c-amount.display
|
||||
@@ -22,8 +21,8 @@
|
||||
<span class="text-3xl">{{ data.months }}</span>
|
||||
<span class="text-subtle">{% trans 'months without any income.' %}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="collapse-content bg-base-200">
|
||||
</c-slot>
|
||||
<c-slot name="content">
|
||||
<div class="flex justify-between items-baseline mt-2">
|
||||
<div class="text-end font-mono">
|
||||
<div class="text-subtle">{% translate 'average expenses' %}</div>
|
||||
@@ -61,8 +60,8 @@
|
||||
<span>{{ data.months }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</c-slot>
|
||||
</c-ui.components.collapse>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
title="{% translate 'Order by' %}">
|
||||
<i class="fa-solid fa-sort fa-fw"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end menu w-max relative">
|
||||
<ul class="dropdown-menu dropdown-menu-end menu">
|
||||
<li>
|
||||
<button class="{% if order == 'default' %}menu-active{% endif %}" type="button"
|
||||
_="on click remove .menu-active from <li > button/> in the closest <ul/>
|
||||
@@ -166,7 +166,7 @@
|
||||
</div>
|
||||
|
||||
{# Filter transactions form #}
|
||||
<div class="bs collapse overflow-visible" id="collapse-filter" hx-preserve>
|
||||
<div class="bs collapse z-1" id="collapse-filter" hx-preserve>
|
||||
<div class="card card-body bg-base-200 mt-2">
|
||||
<div class="text-right">
|
||||
<button class="btn btn-outline btn-error btn-sm w-fit"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
hx-indicator="#dry-run-created-result, closest form" class="show-loading" novalidate>
|
||||
{% crispy form %}
|
||||
</form>
|
||||
<hr>
|
||||
<hr class="hr my-3">
|
||||
<div id="dry-run-created-result" class="show-loading">
|
||||
{% include 'rules/fragments/transaction_rule/dry_run/visual.html' with logs=logs results=results %}
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
hx-indicator="#dry-run-deleted-result, closest form" class="show-loading" novalidate>
|
||||
{% crispy form %}
|
||||
</form>
|
||||
<hr>
|
||||
<hr class="hr my-3">
|
||||
<div id="dry-run-deleted-result" class="show-loading">
|
||||
{% include 'rules/fragments/transaction_rule/dry_run/visual.html' with logs=logs results=results %}
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
hx-indicator="#dry-run-updated-result, closest form" class="show-loading" novalidate>
|
||||
{% crispy form %}
|
||||
</form>
|
||||
<hr>
|
||||
<hr class="hr my-3">
|
||||
<div id="dry-run-updated-result" class="show-loading">
|
||||
{% include 'rules/fragments/transaction_rule/dry_run/visual.html' with logs=logs results=results %}
|
||||
</div>
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
{% load i18n %}
|
||||
<div class="card bg-base-100 shadow-xl max-h-full overflow-auto overflow-x-auto">
|
||||
<div class="card-header bg-base-200 p-4">
|
||||
<div role="tablist" class="tabs tabs-lifted">
|
||||
<button class="tab tab-active" id="visual-tab" data-bs-toggle="tab" data-bs-target="#visual-tab-pane"
|
||||
type="button" role="tab" aria-controls="visual-tab-pane"
|
||||
aria-selected="true">{% translate 'Visual' %}</button>
|
||||
<button class="tab" id="logs-tab" data-bs-toggle="tab" data-bs-target="#logs-tab-pane" type="button"
|
||||
role="tab" aria-controls="logs-tab-pane" aria-selected="false">{% translate 'Logs' %}</button>
|
||||
</div>
|
||||
<div class="card" x-data="{ selectedTab: 'visual' }">
|
||||
<div role="tablist" class="card-header tabs tabs-border">
|
||||
<input type="radio" name="test-tab" class="tab" aria-label="{% translate 'Visual' %}"
|
||||
x-on:click="selectedTab = 'visual'"
|
||||
x-bind:checked="selectedTab === 'visual'"/>
|
||||
<input type="radio" name="test-tab" class="tab" aria-label="{% translate 'Logs' %}"
|
||||
x-on:click="selectedTab = 'logs'"
|
||||
x-bind:checked="selectedTab === 'logs'"/>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="visual-tab-pane" role="tabpanel" aria-labelledby="home-tab"
|
||||
tabindex="0">
|
||||
{% if not results %}
|
||||
{% translate 'Run a test to see...' %}
|
||||
{% else %}
|
||||
{% for result in results %}
|
||||
<div role="tabpanel" aria-labelledby="home-tab"
|
||||
tabindex="0" x-cloak x-show="selectedTab === 'visual'">
|
||||
{% if not results %}
|
||||
{% translate 'Run a test to see...' %}
|
||||
{% else %}
|
||||
{% for result in results %}
|
||||
|
||||
{% if result.type == 'header' %}
|
||||
<div class="my-3">
|
||||
<h6 class="text-center mb-3">
|
||||
<span class="badge badge-secondary">
|
||||
{% if result.type == 'header' %}
|
||||
<div class="my-3">
|
||||
<h6 class="text-center mb-3">
|
||||
<span class="badge badge-primary">
|
||||
{% if result.header_type == "edit_transaction" %}
|
||||
{% translate 'Edit transaction' %}
|
||||
{% elif result.header_type == "update_or_create_transaction" %}
|
||||
{% translate 'Update or create transaction' %}
|
||||
{% endif %}
|
||||
</span>
|
||||
</h6>
|
||||
</div>
|
||||
{% endif %}
|
||||
</h6>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if result.type == 'triggering_transaction' %}
|
||||
<div class="mt-4">
|
||||
<h6 class="text-center mb-3"><span class="badge badge-secondary">{% translate 'Start' %}</span></h6>
|
||||
<c-transaction.item :transaction="result.transaction" :dummy="True"
|
||||
:disable-selection="True"></c-transaction.item>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if result.type == 'triggering_transaction' %}
|
||||
<div class="mt-4">
|
||||
<h6 class="text-center mb-3"><span class="badge badge-primary">{% translate 'Start' %}</span></h6>
|
||||
<c-transaction.item :transaction="result.transaction" :dummy="True"
|
||||
:disable-selection="True"></c-transaction.item>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if result.type == 'edit_transaction' %}
|
||||
{% if result.type == 'edit_transaction' %}
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
{% translate 'Set' %} <span
|
||||
class="badge badge-secondary">{{ result.field }}</span> {% translate 'to' %}
|
||||
<span class="badge badge-secondary">{{ result.new_value }}</span>
|
||||
</div>
|
||||
<c-transaction.item :transaction="result.transaction" :dummy="True"
|
||||
{% translate 'Set' %} <span
|
||||
class="badge badge-secondary">{{ result.field }}</span> {% translate 'to' %}
|
||||
<span class="badge badge-secondary">{{ result.new_value }}</span>
|
||||
</div>
|
||||
<c-transaction.item :transaction="result.transaction" :dummy="True"
|
||||
:disable-selection="True"></c-transaction.item>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if result.type == 'update_or_create_transaction' %}
|
||||
<div>
|
||||
<div class="alert alert-info" role="alert">
|
||||
{% translate 'Search' %}: {{ result.query }}
|
||||
</div>
|
||||
{% if result.start_transaction %}
|
||||
<c-transaction.item :transaction="result.start_transaction" :dummy="True"
|
||||
:disable-selection="True"></c-transaction.item>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if result.type == 'update_or_create_transaction' %}
|
||||
<div>
|
||||
<div class="alert alert-info" role="alert">
|
||||
{% translate 'Search' %}: {{ result.query }}
|
||||
{% else %}
|
||||
<div class="alert alert-error" role="alert">
|
||||
{% translate 'No transaction found, a new one will be created' %}
|
||||
</div>
|
||||
{% if result.start_transaction %}
|
||||
<c-transaction.item :transaction="result.start_transaction" :dummy="True"
|
||||
:disable-selection="True"></c-transaction.item>
|
||||
{% else %}
|
||||
<div class="alert alert-error" role="alert">
|
||||
{% translate 'No transaction found, a new one will be created' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="text-center text-3xl my-2"><i class="fa-solid fa-arrow-down"></i></div>
|
||||
<c-transaction.item :transaction="result.end_transaction" :dummy="True"
|
||||
:disable-selection="True"></c-transaction.item>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div class="text-center text-3xl my-2"><i class="fa-solid fa-arrow-down"></i></div>
|
||||
<c-transaction.item :transaction="result.end_transaction" :dummy="True"
|
||||
:disable-selection="True"></c-transaction.item>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if result.type == 'error' %}
|
||||
<div>
|
||||
<div class="alert alert-{% if result.level == 'error' %}error{% elif result.level == 'warning' %}warning{% else %}info{% endif %}" role="alert">
|
||||
{{ result.error }}
|
||||
</div>
|
||||
{% if result.type == 'error' %}
|
||||
<div>
|
||||
<div
|
||||
class="alert alert-{% if result.level == 'error' %}error{% elif result.level == 'warning' %}warning{% else %}info{% endif %}"
|
||||
role="alert">
|
||||
{{ result.error }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="tab-pane fade" id="logs-tab-pane" role="tabpanel" aria-labelledby="logs-tab" tabindex="0">
|
||||
{% if not logs %}
|
||||
{% translate 'Run a test to see...' %}
|
||||
{% else %}
|
||||
<pre>
|
||||
{{ logs|linebreaks }}
|
||||
</pre>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div role="tabpanel" aria-labelledby="logs-tab" tabindex="0"
|
||||
x-cloak x-show="selectedTab === 'logs'">
|
||||
{% if not logs %}
|
||||
{% translate 'Run a test to see...' %}
|
||||
{% else %}
|
||||
<pre class="overflow-x-auto">
|
||||
{{ logs|linebreaks }}
|
||||
</pre>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<div class="my-3">
|
||||
<div class="text-xl mb-2">{% translate 'Then...' %}</div>
|
||||
<div class="row g-3">
|
||||
<div class="flex flex-col gap-3">
|
||||
{% for action in all_actions %}
|
||||
{% if action.action_type == "edit_transaction" %}
|
||||
<div class="card bg-base-100 card-border shadow">
|
||||
@@ -69,7 +69,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{% elif action.action_type == "update_or_create_transaction" %}
|
||||
<div class="card shadow">
|
||||
<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 %}
|
||||
@@ -103,7 +103,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
<div class="card shadow">
|
||||
<div class="bg-base-100 card-border shadow">
|
||||
<div class="card-body">
|
||||
{% translate 'This rule has no actions' %}
|
||||
</div>
|
||||
@@ -117,7 +117,7 @@
|
||||
aria-expanded="false">
|
||||
<i class="fa-solid fa-flask-vial me-2"></i>{% translate 'Test' %}
|
||||
</button>
|
||||
<ul class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
|
||||
<ul class="dropdown-menu menu">
|
||||
{% if transaction_rule.on_create %}
|
||||
<li><a role="link" href="#"
|
||||
hx-get="{% url 'transaction_rule_dry_run_created' pk=transaction_rule.id %}"
|
||||
@@ -140,7 +140,7 @@
|
||||
aria-expanded="false">
|
||||
<i class="fa-solid fa-circle-plus me-2"></i>{% translate 'Add new' %}
|
||||
</button>
|
||||
<ul class="dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow">
|
||||
<ul class="dropdown-menu menu">
|
||||
<li><a role="link" href="#"
|
||||
hx-get="{% url 'transaction_rule_action_add' transaction_rule_id=transaction_rule.id %}"
|
||||
hx-target="#generic-offcanvas">{% trans 'Edit Transaction' %}</a></li>
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
{% block title %}{% translate 'Bulk Editing' %}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<p>{% trans 'Editing' %} {{ transactions|length }} {% trans 'transactions' %}</p>
|
||||
<p>{% trans 'Editing' %} {{ transactions|length }} {% trans 'transactions' %}
|
||||
<hr class="hr my-3" />
|
||||
<div class="editing-transactions">
|
||||
{% for transaction in transactions %}
|
||||
<input type="hidden" name="transactions" value="{{ transaction.id }}"/>
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
title="{% translate 'Order by' %}">
|
||||
<i class="fa-solid fa-sort fa-fw"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end menu w-max relative">
|
||||
<ul class="dropdown-menu dropdown-menu-end menu">
|
||||
<li>
|
||||
<button class="{% if order == 'default' %}menu-active{% endif %}" type="button"
|
||||
_="on click remove .menu-active from <li > button/> in the closest <ul/>
|
||||
@@ -118,7 +118,7 @@
|
||||
</div>
|
||||
|
||||
{# Filter transactions form #}
|
||||
<div class="bs collapse overflow-visible" id="collapse-filter" hx-preserve>
|
||||
<div class="bs collapse z-1" id="collapse-filter" hx-preserve>
|
||||
<div class="card card-body bg-base-200 mt-2">
|
||||
<div class="text-right">
|
||||
<button class="btn btn-outline btn-error btn-sm w-fit"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<div class="mb-3">
|
||||
<div class="join w-full " role="group" aria-label="{{ field.label }}">
|
||||
<input type="radio" class="join-item btn btn-warning btn-outline w-1/2" name="{{ field.name }}" id="{{ field.id_for_label }}_false"
|
||||
value="false" aria-label="{% trans 'Projected' %}" {% if not field.value %}checked{% endif %}>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<div class="mb-3">
|
||||
<div class="join w-full" role="group" aria-label="{{ field.label }}">
|
||||
<input type="radio"
|
||||
class="join-item btn btn-neutral {% if field.errors %}input-error{% endif %}"
|
||||
class="join-item btn btn-neutral btn-outline w-1/3 {% if field.errors %}input-error{% endif %}"
|
||||
name="{{ field.html_name }}"
|
||||
id="{{ field.html_name }}_none_tr"
|
||||
value=""
|
||||
aria-label="{% trans 'Unchanged' %}"
|
||||
{% if field.value is None %}checked{% endif %}>
|
||||
{% if not field.value %}checked{% endif %}>
|
||||
|
||||
{% for choice in field.field.choices %}
|
||||
<input type="radio"
|
||||
class="join-item btn {% if forloop.first %}btn-success{% elif forloop.last %}btn-error{% else %}btn-primary{% endif %} {% if field.errors %}input-error{% endif %}"
|
||||
class="join-item btn btn-outline w-1/3 {% if forloop.first %}btn-success{% elif forloop.last %}btn-error{% else %}btn-primary{% endif %} {% if field.errors %}input-error{% endif %}"
|
||||
name="{{ field.html_name }}"
|
||||
id="{{ field.html_name }}_{{ forloop.counter }}_tr"
|
||||
value="{{ choice.0 }}"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_field %}
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<div class="mb-3">
|
||||
<div class="join w-full" role="group" aria-label="{{ field.label }}">
|
||||
<input type="radio" class="join-item btn btn-neutral" name="{{ field.name }}" id="{{ field.id_for_label }}_null"
|
||||
value="" aria-label="{% trans 'Unchanged' %}" {% if field.value is None %}checked{% endif %}>
|
||||
<input type="radio" class="join-item btn btn-neutral btn-outline w-1/3" name="{{ field.name }}" id="{{ field.id_for_label }}_null"
|
||||
value="" aria-label="{% trans 'Unchanged' %}" {% if not field.value %}checked{% endif %}>
|
||||
|
||||
<input type="radio" class="join-item btn btn-primary" name="{{ field.name }}" id="{{ field.id_for_label }}_false"
|
||||
<input type="radio" class="join-item btn btn-primary btn-outline w-1/3" name="{{ field.name }}" id="{{ field.id_for_label }}_false"
|
||||
value="false" aria-label="{% trans 'Projected' %}" {% if field.value is False %}checked{% endif %}">
|
||||
|
||||
<input type="radio" class="join-item btn btn-success" name="{{ field.name }}" id="{{ field.id_for_label }}_true"
|
||||
<input type="radio" class="join-item btn btn-success btn-outline w-1/3" name="{{ field.name }}" id="{{ field.id_for_label }}_true"
|
||||
value="true" aria-label="{% trans 'Paid' %}" {% if field.value is True %}checked{% endif %}>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
{% load hijack %}
|
||||
{% load i18n %}
|
||||
<c-ui.fab-single-action
|
||||
url="{% url 'user_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 'Users' %}<span>
|
||||
<a class="no-underline text-2xl p-1 category-action"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Add" %}"
|
||||
hx-get="{% url 'user_add' %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-circle-plus fa-fw"></i></a>
|
||||
</span></div>
|
||||
<div>{% translate 'Users' %}</div>
|
||||
{% endspaceless %}
|
||||
</div>
|
||||
|
||||
@@ -20,58 +17,60 @@
|
||||
{% if users %}
|
||||
<div class="overflow-x-auto">
|
||||
<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 'Active' %}</th>
|
||||
<th scope="col">{% translate 'Name' %}</th>
|
||||
<th scope="col">{% translate 'Email' %}</th>
|
||||
<th scope="col">{% translate 'Superuser' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<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 'user_edit' pk=user.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
{% if request.user|can_hijack:user and request.user != user %}
|
||||
<a class="btn btn-info btn-sm join-item"
|
||||
<div class="overflow-x-auto">
|
||||
<table class="table table-zebra">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="table-col-auto"></th>
|
||||
<th scope="col">{% translate 'Active' %}</th>
|
||||
<th scope="col">{% translate 'Name' %}</th>
|
||||
<th scope="col">{% translate 'Email' %}</th>
|
||||
<th scope="col">{% translate 'Superuser' %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<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"
|
||||
data-tippy-content="{% translate "Impersonate" %}"
|
||||
hx-post="{% url 'hijack:acquire' %}"
|
||||
hx-vals='{"user_pk":"{{user.id}}"}'
|
||||
hx-swap="none"
|
||||
_="on htmx:afterRequest(event) from me
|
||||
hx-swap="innerHTML"
|
||||
data-tippy-content="{% translate "Edit" %}"
|
||||
hx-get="{% url 'user_edit' pk=user.id %}"
|
||||
hx-target="#generic-offcanvas">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
{% if request.user|can_hijack:user and request.user != user %}
|
||||
<a class="btn btn-info btn-sm join-item"
|
||||
role="button"
|
||||
data-tippy-content="{% translate "Impersonate" %}"
|
||||
hx-post="{% url 'hijack:acquire' %}"
|
||||
hx-vals='{"user_pk":"{{ user.id }}"}'
|
||||
hx-swap="none"
|
||||
_="on htmx:afterRequest(event) from me
|
||||
if event.detail.successful
|
||||
go to url '/'">
|
||||
<i class="fa-solid fa-mask fa-fw"></i></a>
|
||||
<i class="fa-solid fa-mask fa-fw"></i></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% if user.is_active %}
|
||||
<i class="fa-solid fa-solid fa-check text-success"></i>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% if user.is_active %}
|
||||
<i class="fa-solid fa-solid fa-check text-success"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ user.first_name }} {{ user.last_name }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
{% if user.is_superuser %}
|
||||
<i class="fa-solid fa-solid fa-check text-success"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<td>{{ user.first_name }} {{ user.last_name }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>
|
||||
{% if user.is_superuser %}
|
||||
<i class="fa-solid fa-solid fa-check text-success"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<c-msg.empty title="{% translate "No users" %}" remove-padding></c-msg.empty>
|
||||
|
||||
@@ -9,41 +9,46 @@
|
||||
{% block content %}
|
||||
<div class="min-h-screen flex items-center justify-center p-4">
|
||||
<div class="w-full max-w-md">
|
||||
{% settings "DEMO" as demo_mode %}
|
||||
{% if demo_mode %}
|
||||
<div class="card bg-base-100 shadow-xl mb-3">
|
||||
<div class="card-body">
|
||||
<h1 class="text-lg card-title text-center mb-4">{% trans "Welcome to WYGIWYH's demo!" %}</h1>
|
||||
<p>{% trans 'Use the credentials below to login' %}:</p>
|
||||
<p>{% trans 'E-mail' %}: <span class="badge badge-secondary select-all">demo@demo.com</span></p>
|
||||
<p>{% trans 'Password' %}: <span class="badge badge-secondary select-all">wygiwyhdemo</span></p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card bg-base-100 shadow-2xl">
|
||||
<div class="card-body">
|
||||
<h1 class="text-2xl card-title text-center mb-4">Login</h1>
|
||||
{% crispy form %}
|
||||
|
||||
{% get_providers as socialaccount_providers %}
|
||||
{% if socialaccount_providers %}
|
||||
<div class="mt-3">
|
||||
<hr class="hr">
|
||||
<ul class="socialaccount_providers list-none">
|
||||
{% for provider in socialaccount_providers %}
|
||||
<li class="mt-2">
|
||||
<a title="{{ provider.name }}"
|
||||
class="btn btn-outline btn-primary w-full socialaccount_provider {{ provider.id }}"
|
||||
href="{% provider_login_url provider %}">
|
||||
{% translate 'Login with' %} {{ provider.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% settings "DEMO" as demo_mode %}
|
||||
{% if demo_mode %}
|
||||
<div class="card bg-base-100 shadow-xl mb-3">
|
||||
<div class="card-body">
|
||||
<h1 class="text-lg card-title text-center mb-4">{% trans "Welcome to WYGIWYH's demo!" %}</h1>
|
||||
<p>{% trans 'Use the credentials below to login' %}:</p>
|
||||
<p>{% trans 'E-mail' %}: <span class="badge badge-secondary select-all">demo@demo.com</span></p>
|
||||
<p>{% trans 'Password' %}: <span class="badge badge-secondary select-all">wygiwyhdemo</span></p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card bg-base-100 shadow-2xl">
|
||||
<div class="card-body">
|
||||
<h1 class="text-2xl card-title text-center mb-4">Login</h1>
|
||||
{% crispy form %}
|
||||
|
||||
{% get_providers as socialaccount_providers %}
|
||||
{% if socialaccount_providers %}
|
||||
<hr class="hr my-3">
|
||||
<ul class="socialaccount_providers list-none flex flex-col gap-3">
|
||||
{% for provider in socialaccount_providers %}
|
||||
<li>
|
||||
<a title="{{ provider.name }}"
|
||||
class="btn btn-outline btn-primary w-full socialaccount_provider {{ provider.id }}"
|
||||
href="{% provider_login_url provider %}">
|
||||
{% translate 'Login with' %} {{ provider.name }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="{{ provider.name }}"
|
||||
class="btn btn-outline btn-primary w-full socialaccount_provider {{ provider.id }}"
|
||||
href="{% provider_login_url provider %}">
|
||||
{% translate 'Login with' %} {{ provider.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user