home · contact · privacy
Add account autocompletion to account input fields.
authorChristian Heller <c.heller@plomlompom.de>
Tue, 4 Feb 2025 13:07:43 +0000 (14:07 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Tue, 4 Feb 2025 13:07:43 +0000 (14:07 +0100)
ledger.py
templates/edit_structured.tmpl

index 2907ba3f2906e36a5cf013ab0688e50a7c8db8b7..30f93dd3221c3cba1be1caed4e0e155c8421c408 100755 (executable)
--- a/ledger.py
+++ b/ledger.py
@@ -88,6 +88,15 @@ class Account:
             total += child.wealth
         return total
 
+    @staticmethod
+    def names_over_bookings(bookings: list['Booking']) -> list[str]:
+        """Sorted list of all account names refered to in bookings."""
+        names = set()
+        for booking in bookings:
+            for account_name in booking.account_changes:
+                names.add(account_name)
+        return sorted(list(names))
+
 
 class Line(ABC):
     """Line abstraction featuring .as_dict property."""
@@ -320,14 +329,15 @@ class Booking:
 
 
 class Handler(PlomHttpHandler):
-    # pylint: disable=missing-class-docstring
+    """"Handles HTTP requests."""
     mapper = PlomQueryMap
 
     def _send_rendered(self, tmpl_name: str, ctx: dict[str, Any]) -> None:
         self.send_rendered(Path(f'{tmpl_name}.tmpl'), ctx)
 
     def do_POST(self) -> None:
-        # pylint: disable=invalid-name,missing-function-docstring
+        """"Route POST requests to respective handlers."""
+        # pylint: disable=invalid-name
         redir_target = Path(self.path)
         if (file_prefixed := self.postvars.keys_prefixed(PREFIX_FILE)):
             self.post_file_action(file_prefixed[0])
@@ -395,7 +405,8 @@ class Handler(PlomHttpHandler):
         return Path(self.path).joinpath(f'#{id}')
 
     def do_GET(self) -> None:
-        # pylint: disable=invalid-name,missing-function-docstring
+        """"Route GET requests to respective handlers."""
+        # pylint: disable=invalid-name
         if self.pagename == 'bookings':
             self.redirect(
                 Path('/').joinpath(EDIT_STRUCT).joinpath(self.path_toks[2]))
@@ -413,15 +424,11 @@ class Handler(PlomHttpHandler):
     def get_balance(self, ctx) -> None:
         """Display tree of calculated Accounts over .bookings[:up_incl+1]."""
         id_ = int(self.params.first('up_incl') or '-1')
-        valid, account_names = True, set()
         to_balance = (self.server.bookings[:id_ + 1] if id_ >= 0
                       else self.server.bookings)
-        for booking in to_balance:
-            valid = valid if not booking.is_questionable else False
-            for account_name in booking.account_changes:
-                account_names.add(account_name)
+        valid = 0 == len([b for b in to_balance if b.is_questionable])
         full_names_to_accounts: dict[str, Account] = {}
-        for full_name in sorted(list(account_names)):
+        for full_name in Account.names_over_bookings(to_balance):
             step_names = full_name.split(':')
             path = ''
             for step_name in step_names:
@@ -448,6 +455,8 @@ class Handler(PlomHttpHandler):
         ctx['id'] = id_
         ctx['dat_lines'] = [dl if raw else dl.as_dict for dl
                             in self.server.bookings[id_].booked_lines]
+        if not raw:
+            ctx['accounts'] = Account.names_over_bookings(self.server.bookings)
         self._send_rendered(EDIT_RAW if raw else EDIT_STRUCT, ctx)
 
     def get_ledger(self, ctx: dict[str, Any], raw: bool) -> None:
index efa474ee5f3e72e40e17693a489008b48c61f180..8f2bcfa89d6596740d4865cb62af27e41a384b3d 100644 (file)
@@ -59,7 +59,9 @@ function update_form() {
       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);
+      const acc_input = add_td_input('account', dat_line.booking_line.account, 30);
+      acc_input.setAttribute ('list', 'accounts');
+      acc_input.autocomplete = 'off';
       // 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]+)?$';
@@ -121,4 +123,9 @@ window.onload = update_form;
 <table id="dat_lines">
 </table>
 </form>
+<datalist id="accounts">
+{% for acc in accounts %}
+<option value="{{acc}}">{{acc}}</a>
+{% endfor %}
+</datalist>
 {% endblock %}