feat: Konten umbenennbar, Betrag-Spalte mit Euro im Kopf
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,36 @@
|
||||
document.body.addEventListener('htmx:responseError', function (e) {
|
||||
alert('Fehler: ' + (e.detail.xhr.responseText || e.detail.xhr.status));
|
||||
});
|
||||
|
||||
// Minimale JSON-Kodierung für htmx-Formulare/Selects, die gegen die JSON-APIs
|
||||
// (POST/PATCH /api/...) senden. Felder mit data-type="int" werden als Zahl
|
||||
// kodiert, leere Werte als null, alles andere bleibt String.
|
||||
htmx.defineExtension('json-form', {
|
||||
onEvent: function (name, evt) {
|
||||
if (name === 'htmx:configRequest') {
|
||||
evt.detail.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
},
|
||||
encodeParameters: function (xhr, parameters, elt) {
|
||||
var out = {};
|
||||
for (var k in parameters) {
|
||||
var v = parameters[k];
|
||||
var field = elt.matches && elt.matches('[name="' + k + '"]')
|
||||
? elt
|
||||
: elt.querySelector('[name="' + k + '"]');
|
||||
var kind = field && field.dataset ? field.dataset.type : null;
|
||||
if (v === '') {
|
||||
out[k] = null;
|
||||
} else if (kind === 'int') {
|
||||
out[k] = parseInt(v, 10);
|
||||
} else {
|
||||
out[k] = v;
|
||||
}
|
||||
}
|
||||
xhr.overrideMimeType('text/json');
|
||||
return JSON.stringify(out);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -16,17 +16,24 @@
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>Konto</th><th>Bank</th><th>Saldo</th></tr>
|
||||
<tr><th>Konto</th><th>Bank</th><th>Saldo</th><th>Umbenennen</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for account, balance in balances %}
|
||||
<tr>
|
||||
<td>{{ account.name }}</td>
|
||||
<td class="account">{{ account.name }}</td>
|
||||
<td>{{ account.bank }}</td>
|
||||
<td class="{{ 'neg' if balance < 0 else '' }}">{{ '%.2f'|format(balance) }} €</td>
|
||||
<td>
|
||||
<form class="inline-form" hx-ext="json-form" hx-patch="/api/accounts/{{ account.id }}"
|
||||
hx-swap="none" hx-on::after-request="if(event.detail.successful){window.location.reload()}">
|
||||
<input type="text" name="name" value="{{ account.name }}" required maxlength="100">
|
||||
<button type="submit">Umbenennen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="3">Keine Konten angelegt.</td></tr>
|
||||
<tr><td colspan="4">Keine Konten angelegt.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -43,17 +43,17 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Datum</th><th>Konto</th><th>Verwendungszweck</th><th>Empfänger/Zahler</th>
|
||||
<th>Betrag</th><th>Kategorie</th><th></th>
|
||||
<th>Betrag (€)</th><th>Kategorie</th><th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for tx in transactions %}
|
||||
<tr>
|
||||
<td>{{ tx.booking_date.strftime('%d.%m.%Y') }}</td>
|
||||
<td>{{ account_names.get(tx.account_id, tx.account_id) }}</td>
|
||||
<td class="account">{{ account_names.get(tx.account_id, tx.account_id) }}</td>
|
||||
<td>{{ tx.purpose }}</td>
|
||||
<td>{{ tx.counterparty }}</td>
|
||||
<td class="{{ 'neg' if tx.amount < 0 else '' }}">{{ '%.2f'|format(tx.amount) }} €</td>
|
||||
<td class="amount {{ 'neg' if tx.amount < 0 else '' }}">{{ '%.2f'|format(tx.amount) }}</td>
|
||||
<td>
|
||||
<select name="category_id" data-type="int" hx-ext="json-form"
|
||||
hx-patch="/api/transactions/{{ tx.id }}" hx-trigger="change" hx-swap="none">
|
||||
@@ -113,36 +113,4 @@
|
||||
<button type="submit">Buchung speichern</button>
|
||||
</form>
|
||||
</fieldset>
|
||||
|
||||
<script>
|
||||
// Minimale JSON-Kodierung für htmx-Formulare/Selects, die gegen die JSON-APIs
|
||||
// (POST/PATCH /api/...) senden. Felder mit data-type="int" werden als Zahl
|
||||
// kodiert, leere Werte als null, alles andere bleibt String.
|
||||
htmx.defineExtension('json-form', {
|
||||
onEvent: function (name, evt) {
|
||||
if (name === 'htmx:configRequest') {
|
||||
evt.detail.headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
},
|
||||
encodeParameters: function (xhr, parameters, elt) {
|
||||
var out = {};
|
||||
for (var k in parameters) {
|
||||
var v = parameters[k];
|
||||
var field = elt.matches && elt.matches('[name="' + k + '"]')
|
||||
? elt
|
||||
: elt.querySelector('[name="' + k + '"]');
|
||||
var kind = field && field.dataset ? field.dataset.type : null;
|
||||
if (v === '') {
|
||||
out[k] = null;
|
||||
} else if (kind === 'int') {
|
||||
out[k] = parseInt(v, 10);
|
||||
} else {
|
||||
out[k] = v;
|
||||
}
|
||||
}
|
||||
xhr.overrideMimeType('text/json');
|
||||
return JSON.stringify(out);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user