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
@ -12,3 +12,6 @@ class AccountForm(NummiForm):
"default",
"archived",
]
widgets = {
"icon": IconInput(),
}

View file

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

View file

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

View file

@ -1,4 +1,7 @@
from django import forms
from django.forms.widgets import TextInput
from .utils import get_icons
class NummiFileInput(forms.ClearableFileInput):
@ -19,3 +22,29 @@ class NummiForm(forms.ModelForm):
yield ((self[f] for f in fieldset) for fieldset in group)
else:
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;
grid-template-columns: min-content 1fr;
column-gap: 0.5rem;

View file

@ -25,9 +25,34 @@ for (let form of forms) {
let icon = categorySelect.querySelector("span");
let icons = JSON.parse(input.dataset.icons);
icon.className = `ri-${icons[input.value] || "folder"}-line`;
input.addEventListener("input", (event) => {
function setIcon(event) {
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
from category.forms import CategorySelect
from django.forms.widgets import TextInput
from main.forms import NummiFileInput, NummiForm
from main.forms import DatalistInput, NummiFileInput, NummiForm
from .models import Invoice, Transaction
from .utils import get_datalist
@ -82,19 +81,3 @@ class InvoiceForm(NummiForm):
widgets = {
"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