Apply custom accounts combobox to transaction editor
This commit is contained in:
parent
af2818b6ae
commit
64b49b00ff
@ -38,7 +38,7 @@ def journal():
|
|||||||
@app.route('/journal/new-transaction', methods=['GET', 'POST'])
|
@app.route('/journal/new-transaction', methods=['GET', 'POST'])
|
||||||
def journal_new_transaction():
|
def journal_new_transaction():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return render_template('journal/journal_edit_transaction.html', transaction=None)
|
return render_template('journal/journal_edit_transaction.html', transaction=None, all_accounts=all_accounts())
|
||||||
|
|
||||||
# New transaction
|
# New transaction
|
||||||
transaction = Transaction(
|
transaction = Transaction(
|
||||||
@ -73,7 +73,7 @@ def journal_edit_transaction():
|
|||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return render_template('journal/journal_edit_transaction.html', transaction=transaction)
|
return render_template('journal/journal_edit_transaction.html', transaction=transaction, all_accounts=all_accounts())
|
||||||
|
|
||||||
if request.form.get('action', None) == 'delete':
|
if request.form.get('action', None) == 'delete':
|
||||||
# Delete transaction
|
# Delete transaction
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
<path fill-rule="evenodd" d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z" clip-rule="evenodd" />
|
<path fill-rule="evenodd" d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z" clip-rule="evenodd" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<ul class="hidden peer-focus:block absolute z-10 mt-1 max-h-60 w-full overflow-auto bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
|
<ul class="hidden peer-focus:block absolute z-20 mt-1 max-h-60 w-full overflow-auto bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
|
||||||
{% for account in all_accounts %}
|
{% for account in all_accounts %}
|
||||||
<li class="group relative cursor-default select-none py-1 pl-3 pr-9 text-gray-900 hover:text-white hover:bg-indigo-600">
|
<li class="group relative cursor-default select-none py-1 pl-3 pr-9 text-gray-900 hover:text-white hover:bg-indigo-600">
|
||||||
<span class="combobox-text block truncate group-data-[selected=selected]:font-semibold">{{ account }}</span>
|
<span class="combobox-text block truncate group-data-[selected=selected]:font-semibold">{{ account }}</span>
|
||||||
|
@ -18,6 +18,80 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% block title %}{{ 'Edit' if transaction and transaction.id else 'New' }} transaction{% endblock %}
|
{% block title %}{{ 'Edit' if transaction and transaction.id else 'New' }} transaction{% endblock %}
|
||||||
|
|
||||||
|
{# Macros for template posting rows as these are reused #}
|
||||||
|
{% macro template_dr() %}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
{#<td></td>#}
|
||||||
|
<td class="py-1 px-1" colspan="2">
|
||||||
|
<div class="relative flex">
|
||||||
|
<div class="relative flex flex-grow items-stretch shadow-sm">
|
||||||
|
<div class="absolute inset-y-0 left-0 flex items-center z-10">
|
||||||
|
<select class="h-full border-0 bg-transparent py-0 pl-2 pr-8 text-gray-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600" name="sign" onchange="changeDrCr(this)">
|
||||||
|
<option value="dr" selected>Dr</option>
|
||||||
|
<option value="cr">Cr</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="relative combobox w-full">
|
||||||
|
<input type="text" class="bordered-field pl-16 peer" name="account" autocomplete="off">
|
||||||
|
{% include 'components/accounts_combobox_inner.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a class="relative -ml-px px-2 py-2 text-gray-500 hover:text-gray-700" href="#" onclick="addPosting(this);return false;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="amount-dr has-amount py-1 px-1">
|
||||||
|
<div class="relative shadow-sm">
|
||||||
|
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||||
|
<span class="text-gray-500">$</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="bordered-field pl-7" name="amount" step="0.01" oninput="changeAmount(this)">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="amount-cr py-1 pl-1"></td>
|
||||||
|
</tr>
|
||||||
|
{% endmacro %}
|
||||||
|
{% macro template_cr() %}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
{#<td></td>#}
|
||||||
|
<td class="py-1 px-1" colspan="2">
|
||||||
|
<div class="relative flex">
|
||||||
|
<div class="relative flex flex-grow items-stretch shadow-sm">
|
||||||
|
<div class="absolute inset-y-0 left-0 flex items-center z-10">
|
||||||
|
<select class="h-full border-0 bg-transparent py-0 pl-2 pr-8 text-gray-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600" name="sign" onchange="changeDrCr(this)">
|
||||||
|
<option value="dr">Dr</option>
|
||||||
|
<option value="cr" selected>Cr</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="relative combobox w-full">
|
||||||
|
<input type="text" class="bordered-field pl-16 peer" name="account" autocomplete="off">
|
||||||
|
{% include 'components/accounts_combobox_inner.html' %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a class="relative -ml-px px-2 py-2 text-gray-500 hover:text-gray-700" href="#" onclick="addPosting(this);return false;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="amount-dr py-1 px-1"></td>
|
||||||
|
<td class="amount-cr has-amount py-1 pl-1">
|
||||||
|
<div class="relative shadow-sm">
|
||||||
|
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
||||||
|
<span class="text-gray-500">$</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="bordered-field pl-7" name="amount" step="0.01" oninput="changeAmount(this)">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1 class="page-heading mb-4">
|
<h1 class="page-heading mb-4">
|
||||||
{{ 'Edit' if transaction and transaction.id else 'New' }} transaction
|
{{ 'Edit' if transaction and transaction.id else 'New' }} transaction
|
||||||
@ -52,13 +126,16 @@
|
|||||||
<td class="py-1 px-1" colspan="2">
|
<td class="py-1 px-1" colspan="2">
|
||||||
<div class="relative flex">
|
<div class="relative flex">
|
||||||
<div class="relative flex flex-grow items-stretch shadow-sm">
|
<div class="relative flex flex-grow items-stretch shadow-sm">
|
||||||
<div class="absolute inset-y-0 left-0 flex items-center">
|
<div class="absolute inset-y-0 left-0 flex items-center z-10">
|
||||||
<select class="h-full border-0 bg-transparent py-0 pl-2 pr-8 text-gray-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600" name="sign" onchange="changeDrCr(this)">
|
<select class="h-full border-0 bg-transparent py-0 pl-2 pr-8 text-gray-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600" name="sign" onchange="changeDrCr(this)">
|
||||||
<option value="dr"{% if posting.quantity >= 0 %} selected{% endif %}>Dr</option>
|
<option value="dr"{% if posting.quantity >= 0 %} selected{% endif %}>Dr</option>
|
||||||
<option value="cr"{% if posting.quantity < 0 %} selected{% endif %}>Cr</option>
|
<option value="cr"{% if posting.quantity < 0 %} selected{% endif %}>Cr</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="bordered-field pl-16" name="account" value="{{ posting.account }}">
|
<div class="relative combobox w-full">
|
||||||
|
<input type="text" class="bordered-field pl-16 peer" name="account" value="{{ posting.account }}" autocomplete="off">
|
||||||
|
{% include 'components/accounts_combobox_inner.html' %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="relative -ml-px px-2 py-2 text-gray-500 hover:text-gray-700" href="#" onclick="addPosting(this);return false;">
|
<a class="relative -ml-px px-2 py-2 text-gray-500 hover:text-gray-700" href="#" onclick="addPosting(this);return false;">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
||||||
@ -91,68 +168,8 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr>
|
{{ template_dr() }}
|
||||||
<td></td>
|
{{ template_cr() }}
|
||||||
{#<td></td>#}
|
|
||||||
<td class="py-1 px-1" colspan="2">
|
|
||||||
<div class="relative flex">
|
|
||||||
<div class="relative flex flex-grow items-stretch shadow-sm">
|
|
||||||
<div class="absolute inset-y-0 left-0 flex items-center">
|
|
||||||
<select class="h-full border-0 bg-transparent py-0 pl-2 pr-8 text-gray-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600" name="sign" onchange="changeDrCr(this)">
|
|
||||||
<option value="dr" selected>Dr</option>
|
|
||||||
<option value="cr">Cr</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<input type="text" class="bordered-field pl-16" name="account">
|
|
||||||
</div>
|
|
||||||
<a class="relative -ml-px px-2 py-2 text-gray-500 hover:text-gray-700" href="#" onclick="addPosting(this);return false;">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="amount-dr has-amount py-1 px-1">
|
|
||||||
<div class="relative shadow-sm">
|
|
||||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
|
||||||
<span class="text-gray-500">$</span>
|
|
||||||
</div>
|
|
||||||
<input type="number" class="bordered-field pl-7" name="amount" step="0.01" oninput="changeAmount(this)">
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="amount-cr py-1 pl-1"></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
{#<td></td>#}
|
|
||||||
<td class="py-1 px-1" colspan="2">
|
|
||||||
<div class="relative flex">
|
|
||||||
<div class="relative flex flex-grow items-stretch shadow-sm">
|
|
||||||
<div class="absolute inset-y-0 left-0 flex items-center">
|
|
||||||
<select class="h-full border-0 bg-transparent py-0 pl-2 pr-8 text-gray-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600" name="sign" onchange="changeDrCr(this)">
|
|
||||||
<option value="dr">Dr</option>
|
|
||||||
<option value="cr" selected>Cr</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<input type="text" class="bordered-field pl-16" name="account">
|
|
||||||
</div>
|
|
||||||
<a class="relative -ml-px px-2 py-2 text-gray-500 hover:text-gray-700" href="#" onclick="addPosting(this);return false;">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="amount-dr py-1 px-1"></td>
|
|
||||||
<td class="amount-cr has-amount py-1 pl-1">
|
|
||||||
<div class="relative shadow-sm">
|
|
||||||
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
|
||||||
<span class="text-gray-500">$</span>
|
|
||||||
</div>
|
|
||||||
<input type="number" class="bordered-field pl-7" name="amount" step="0.01" oninput="changeAmount(this)">
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -166,10 +183,13 @@
|
|||||||
|
|
||||||
<input type="hidden" name="referrer" value="{{ request.referrer or '' }}">
|
<input type="hidden" name="referrer" value="{{ request.referrer or '' }}">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
{# Save HTML for template posting rows so we can access this from JS when required #}
|
||||||
|
<table style="display:none" id="template-dr">{{ template_dr() }}</table>
|
||||||
|
<table style="display:none" id="template-cr">{{ template_cr() }}</table>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{# TODO: This would be much easier with React or similar... #}
|
|
||||||
<script>
|
<script>
|
||||||
function changeDrCr(el) {
|
function changeDrCr(el) {
|
||||||
let trPosting = el.parentNode.parentNode.parentNode.parentNode.parentNode;
|
let trPosting = el.parentNode.parentNode.parentNode.parentNode.parentNode;
|
||||||
@ -193,40 +213,9 @@
|
|||||||
let trPosting = el.parentNode.parentNode.parentNode;
|
let trPosting = el.parentNode.parentNode.parentNode;
|
||||||
let sign = trPosting.querySelector('select').value; // Use same sign as row clicked
|
let sign = trPosting.querySelector('select').value; // Use same sign as row clicked
|
||||||
|
|
||||||
let inputAmount =
|
|
||||||
'<div class="relative shadow-sm">' +
|
|
||||||
'<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">' +
|
|
||||||
'<span class="text-gray-500">$</span>' +
|
|
||||||
'</div>' +
|
|
||||||
'<input type="number" class="bordered-field pl-7" name="amount" step="0.01" oninput="changeAmount(this)">' +
|
|
||||||
'</div>';
|
|
||||||
|
|
||||||
// Add new posting row
|
// Add new posting row
|
||||||
let trNew = document.createElement('tr');
|
let trNew = document.createElement('tr');
|
||||||
trNew.innerHTML =
|
trNew.innerHTML = document.getElementById(sign === 'dr' ? 'template-dr' : 'template-cr').querySelector('tr').innerHTML;
|
||||||
'<tr>' +
|
|
||||||
'<td></td>' +
|
|
||||||
'<td class="py-1 px-1" colspan="2">' +
|
|
||||||
'<div class="relative flex">' +
|
|
||||||
'<div class="relative flex flex-grow items-stretch shadow-sm">' +
|
|
||||||
'<div class="absolute inset-y-0 left-0 flex items-center">' +
|
|
||||||
'<select class="h-full border-0 bg-transparent py-0 pl-2 pr-8 text-gray-900 focus:ring-2 focus:ring-inset focus:ring-indigo-600" name="sign" onchange="changeDrCr(this)">' +
|
|
||||||
(sign === 'dr' ? '<option value="dr" selected>Dr</option><option value="cr">Cr</option>' : '<option value="dr">Dr</option><option value="cr" selected>Cr</option>') +
|
|
||||||
'</select>' +
|
|
||||||
'</div>' +
|
|
||||||
'<input type="text" class="bordered-field pl-16" name="account">' +
|
|
||||||
'</div>' +
|
|
||||||
'<a class="relative -ml-px px-2 py-2 text-gray-500 hover:text-gray-700" href="#" onclick="addPosting(this);return false;">' +
|
|
||||||
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">' +
|
|
||||||
'<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />' +
|
|
||||||
'</svg>' +
|
|
||||||
'</a>' +
|
|
||||||
'</div>' +
|
|
||||||
'</td>' +
|
|
||||||
(sign === 'dr' ? ('<td class="amount-dr has-amount py-1 px-1">' + inputAmount + '</td>') : '<td class="amount-dr py-1 px-1"></td>') +
|
|
||||||
(sign === 'cr' ? ('<td class="amount-cr has-amount py-1 pl-1">' + inputAmount + '</td>') : '<td class="amount-cr py-1 pl-1"></td>') +
|
|
||||||
'</tr>';
|
|
||||||
|
|
||||||
trPosting.after(trNew);
|
trPosting.after(trNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,4 +236,5 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script src="{{ url_for('static', filename='js/combobox.js') }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
Reference in New Issue
Block a user