Add icon field, closes #24

This commit is contained in:
Edgar P. Burkhart 2025-01-02 17:30:59 +01:00
parent b4654ec445
commit 224f55a8b1
Signed by: edpibu
GPG key ID: 9833D3C5A25BD227
10 changed files with 81 additions and 24 deletions

View file

@ -1,4 +1,4 @@
from main.forms import NummiForm from main.forms import IconInput, NummiForm
from .models import Account from .models import Account
@ -12,3 +12,6 @@ class AccountForm(NummiForm):
"default", "default",
"archived", "archived",
] ]
widgets = {
"icon": IconInput(),
}

View file

@ -1,5 +1,5 @@
from django.forms.widgets import Select from django.forms.widgets import Select
from main.forms import NummiForm from main.forms import IconInput, NummiForm
from .models import Category from .models import Category
@ -12,6 +12,9 @@ class CategoryForm(NummiForm):
"icon", "icon",
"budget", "budget",
] ]
widgets = {
"icon": IconInput,
}
class CategorySelect(Select): class CategorySelect(Select):

View file

@ -1,5 +1,5 @@
{% load main_extras %} {% load main_extras %}
<span class="category-select"> <span class="ico-input category-select">
{{ "folder"|remix }} {{ "folder"|remix }}
{% include "django/forms/widgets/select.html" %} {% include "django/forms/widgets/select.html" %}
</span> </span>

View file

@ -1,4 +1,7 @@
from django import forms from django import forms
from django.forms.widgets import TextInput
from .utils import get_icons
class NummiFileInput(forms.ClearableFileInput): class NummiFileInput(forms.ClearableFileInput):
@ -19,3 +22,29 @@ class NummiForm(forms.ModelForm):
yield ((self[f] for f in fieldset) for fieldset in group) yield ((self[f] for f in fieldset) for fieldset in group)
else: else:
yield ([f] for f in self) yield ([f] for f in self)
class DatalistInput(TextInput):
template_name = "main/forms/widgets/datalist.html"
def __init__(self, *args, options=[]):
self.options = options
super().__init__(*args)
def get_context(self, *args):
context = super().get_context(*args)
name = context["widget"]["name"]
context["widget"]["attrs"]["list"] = f"{name}-list"
context["widget"]["attrs"]["autocomplete"] = "off"
context["widget"]["options"] = self.options
return context
class IconInput(DatalistInput):
template_name = "main/forms/widgets/icon.html"
icon_list = get_icons()
def get_context(self, *args):
context = super().get_context(*args)
context["widget"]["options"] = self.icon_list
return context

View file

@ -103,7 +103,7 @@ form {
} }
} }
} }
> .category-select { > .ico-input {
display: grid; display: grid;
grid-template-columns: min-content 1fr; grid-template-columns: min-content 1fr;
column-gap: 0.5rem; column-gap: 0.5rem;

View file

@ -25,9 +25,34 @@ for (let form of forms) {
let icon = categorySelect.querySelector("span"); let icon = categorySelect.querySelector("span");
let icons = JSON.parse(input.dataset.icons); let icons = JSON.parse(input.dataset.icons);
icon.className = `ri-${icons[input.value] || "folder"}-line`; function setIcon(event) {
input.addEventListener("input", (event) => {
icon.className = `ri-${icons[input.value] || "folder"}-line`; icon.className = `ri-${icons[input.value] || "folder"}-line`;
}
setIcon();
input.addEventListener("input", setIcon);
form.addEventListener("reset", (event) => {
setTimeout(setIcon, 0);
});
}
let iconSelect = form.querySelector(".icon-select");
if (iconSelect) {
let input = iconSelect.querySelector("input");
let icon = iconSelect.querySelector("span");
let icons = Array.from(iconSelect.querySelector("datalist").options).map(
(opt) => opt.value,
);
function setIcon(event) {
console.log(input.value);
icon.className = `ri-${
icons.includes(input.value) ? input.value : "square"
}-line`;
}
setIcon();
input.addEventListener("input", setIcon);
form.addEventListener("reset", (event) => {
setTimeout(setIcon, 0);
}); });
} }
} }

View file

@ -0,0 +1,5 @@
{% load main_extras %}
<span class="ico-input icon-select">
{{ "square"|remix }}
{% include "main/forms/widgets/datalist.html" %}
</span>

9
nummi/main/utils.py Normal file
View file

@ -0,0 +1,9 @@
import json
from urllib import request
def get_icons():
url = "https://cdn.jsdelivr.net/npm/remixicon@4.5.0/fonts/remixicon.glyph.json"
data = json.loads(request.urlopen(url).read())
return [i.removesuffix("-line") for i in data.keys() if i.endswith("-line")]

View file

@ -1,8 +1,7 @@
import json import json
from category.forms import CategorySelect from category.forms import CategorySelect
from django.forms.widgets import TextInput from main.forms import DatalistInput, NummiFileInput, NummiForm
from main.forms import NummiFileInput, NummiForm
from .models import Invoice, Transaction from .models import Invoice, Transaction
from .utils import get_datalist from .utils import get_datalist
@ -82,19 +81,3 @@ class InvoiceForm(NummiForm):
widgets = { widgets = {
"file": NummiFileInput, "file": NummiFileInput,
} }
class DatalistInput(TextInput):
template_name = "transaction/forms/widgets/datalist.html"
def __init__(self, *args, options=[]):
self.options = options
super().__init__(*args)
def get_context(self, *args):
context = super().get_context(*args)
name = context["widget"]["name"]
context["widget"]["attrs"]["list"] = f"{name}-list"
context["widget"]["attrs"]["autocomplete"] = "off"
context["widget"]["options"] = self.options
return context