home · contact · privacy
Improve structured-editing view.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 28 Jan 2025 14:29:36 +0000 (15:29 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 28 Jan 2025 14:29:36 +0000 (15:29 +0100)
templates/_base.tmpl
templates/edit_structured.tmpl

index af5070c8d8b468177d21d269203c3772bd679a8f..bc15e6bec8f650339e3f6a7430b92fb0f590c7db 100644 (file)
@@ -10,7 +10,8 @@
 body { background-color: white; font-family: sans-serif; }
 tr.alternating:nth-child(odd) { background-color: #dcdcdc; }
 tr.alternating:nth-child(even) { background-color: #ffffff; }
-td { text-align: left; vertical-align: top; }
+td { margin: 0; padding: 0; text-align: left; vertical-align: top; }
+input { background-color: transparent; }
 span.warning, table.warning tbody tr td, tr.warning td { background-color: #ff8888; }
 {% block css %}{% endblock %}
 </style>
index 0e510aeacd8ece3aa0bd0d3c3c24cd41d02f3247..f85a59db57b65370e3b18754fe5fa3f700d32169 100644 (file)
@@ -4,6 +4,9 @@
 {% block css %}
 {{ macros.css_td_money() }}
 {{ macros.css_errors() }}
+input.date_input, input.number_input { font-family: monospace; }
+input.number_input { text-align: right; }
+input.date_input { margin-right: 0.1em; }
 {% endblock %}
 
 
@@ -33,59 +36,78 @@ function update_form() {
     const dat_line = dat_lines[i];
     const tr = document.createElement("tr");
     table.appendChild(tr);
-    function add_input(name, value, colspan=1, placeholder='') {
+    function setup_input_td(tr, colspan) {
       const td = add_td(tr, colspan);
+      if (dat_line.error) { td.classList.add("invalid"); };
+      return td;
+    }
+    function add_input(td, name, value, size) {
       const input = document.createElement("input");
       td.appendChild(input);
       input.name = `line_${i}_${name}`
       input.value = value.trim();
-      input.placeholder = placeholder;
+      input.size = size;
       input.oninput = taint;
-      if (dat_line.error) {
-        td.classList.add("invalid");
-      }
+      return input;
+    }
+    function add_td_input(name, value, size=20, colspan=1) {
+      return add_input(setup_input_td(tr, colspan), name, value, size);
     }
     if (dat_line.is_intro) {
-      add_input('date', dat_line.booking_line.date)
-      add_input('target', dat_line.booking_line.target, 2)
-    } else if (!dat_line.error) {
-      add_input('account', dat_line.booking_line.account);
-      add_input('amount', dat_line.booking_line.amount == 'None' ? '' : dat_line.booking_line.amount);
-      add_input('currency', dat_line.booking_line.currency, 1, '€');
+      const td = setup_input_td(tr, 3);
+      const date_input = add_input(td, 'date', dat_line.booking_line.date, 10)
+      date_input.classList.add('date_input');
+      add_input(td, 'target', dat_line.booking_line.target, 35)
+    } else if (!dat_line.error) {  // i.e. valid TransferLine
+      add_td_input('account', dat_line.booking_line.account, 30);
+      // not using input[type=number] cuz no minimal step size, therefore regex test instead
+      const amt_input = add_td_input('amount', dat_line.booking_line.amount == 'None' ? '' : dat_line.booking_line.amount, 12);
+      amt_input.pattern = '^[0-9]+(\.[0-9]+)?$';
+      amt_input.classList.add("number_input");
+      // ensure integer amounts at least line up with double-digit decimals
+      if (amt_input.value.match(/^[0-9]+$/)) { amt_input.value += '.00'; }
+      // imply that POST handler will set '€' currency if unset, but amount set
+      const curr_input = add_td_input('currency', dat_line.booking_line.currency, 3);
+      curr_input.placeholder = '€';
     } else {
-      add_input('error', dat_line.code, 3)
+      add_td_input('error', dat_line.code, 20, 3)
     }
-    add_input('comment', dat_line.comment);
+    add_td_input('comment', dat_line.comment, 40);
+    // add action buttons, with "delete" after some safety distance
     const td_btns = add_td(tr);
-    add_button(td_btns, 'delete', false, function() {
-      dat_lines.splice(i, 1);
-    });
-    add_button(td_btns, 'move up', i > 1 ? false : true, function() {
+    add_button(td_btns, '^', i > 1 ? false : true, function() {
       const prev_line = dat_lines[i-1];
       dat_lines.splice(i-1, 1);
       dat_lines.splice(i, 0, prev_line);
     });
-    add_button(td_btns, 'move down', i+1 < dat_lines.length ? false : true, function() {
+    add_button(td_btns, 'v', i+1 < dat_lines.length ? false : true, function() {
       const next_line = dat_lines[i];
       dat_lines.splice(i, 1);
       dat_lines.splice(i+1, 0, next_line);
     });
+    td_btns.appendChild(document.createTextNode(' · · · '))
+    add_button(td_btns, 'delete', false, function() { dat_lines.splice(i, 1); });
+    // add error explanation row if necessary
     if (dat_line.error) {
       const tr = document.createElement("tr");
       table.appendChild(tr);
       const td = add_td(tr, 3);
       tr.appendChild(document.createElement("td"));
       td.textContent = dat_line.error;
-      td.classList.add("invalid");
       tr.classList.add("warning");
     }
   }
+  // add "add line" row
   const tr = document.createElement("tr");
   table.appendChild(tr);
   const td = add_td(tr, 5);
   add_button(td, 'add line', false, function() {
-     new_line = {error: '', comment: '', booking_line: {account: '', amount: '', currency: ''}};
-     dat_lines.push(new_line);
+   new_line = {error: '', comment: '', booking_line: {account: '', amount: '', currency: ''}};
+   dat_lines.push(new_line);
+  });
+  // make all rows alternate background color for better readability
+  Array.from(table.rows).forEach((tr) => {
+      tr.classList.add('alternating');
   });
 }