From: Christian Heller Date: Sun, 26 Jan 2025 11:20:45 +0000 (+0100) Subject: Add per-line structured editing of Bookings. X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/%7B%7B%20web_path%20%7D%7D/decks/static/conditions?a=commitdiff_plain;h=3a7c0b8b73dbd4f543fbad5d2df86e258f5e3163;p=plomledger Add per-line structured editing of Bookings. --- diff --git a/ledger.py b/ledger.py index 016e087..87f58f5 100755 --- a/ledger.py +++ b/ledger.py @@ -221,30 +221,52 @@ class Handler(PlomHttpHandler): def do_POST(self) -> None: # pylint: disable=invalid-name,missing-function-docstring + redir_path = Path('/') + if self.pagename.startswith('edit_'): + id_ = int(self.path_toks[2]) + redir_path = Path('/').joinpath('booking').joinpath(str(id_)) if self.pagename == 'file': if 'reload' in self.postvars.as_dict: self.server.load() elif 'save' in self.postvars.as_dict: self.server.save() - elif self.pagename == 'edit': - id_ = int(self.path_toks[2]) - old_booking = self.server.bookings[id_] - start_idx = self.server.dat_lines.index(old_booking.dat_lines[0]) - end_idx = self.server.dat_lines.index(old_booking.dat_lines[-1]) + elif self.pagename == 'edit_structured': + line_keys = self.postvars.keys_prefixed('line_') + lineno_to_inputs: dict[int, list[str]] = {} + for key in line_keys: + toks = key.split('_', maxsplit=2) + lineno = int(toks[1]) + if lineno not in lineno_to_inputs: + lineno_to_inputs[lineno] = [] + lineno_to_inputs[lineno] += [toks[2]] + new_dat_lines = [] + indent = ' ' + for lineno, input_names in lineno_to_inputs.items(): + data = '' + comment = self.postvars.first(f'line_{lineno}_comment') + for name in input_names: + input_ = self.postvars.first(f'line_{lineno}_{name}') + if name == 'intro': + data = input_ + elif name == 'error': + data = f'{indent}{input_}' + elif name == 'account': + data = f'{indent}{input_}' + elif name in {'amount', 'currency'}: + data += f' {input_}' + new_dat_lines += [ + DatLine(f'{data} ; {comment}' if comment else data)] + self.server.rewrite_booking(id_, new_dat_lines) + elif self.pagename == 'edit_raw': new_dat_lines = [DatLine(line) for line in self.postvars.first('booking').splitlines()] - self.server.dat_lines = (self.server.dat_lines[:start_idx] - + new_dat_lines - + self.server.dat_lines[end_idx+1:]) - self.server.load_bookings() - self.redirect(Path('/').joinpath('booking').joinpath(str(id_))) - return - self.redirect(Path('/')) + self.server.rewrite_booking(id_, new_dat_lines) + self.redirect(redir_path) def do_GET(self) -> None: # pylint: disable=invalid-name,missing-function-docstring ctx = {'tainted': self.server.tainted} - if self.pagename in {'booking', 'edit'}: + if self.pagename == 'booking' or self.pagename.startswith('edit_'): ctx['id'] = int(self.path_toks[2]) ctx['dat_lines'] = self.server.bookings[ctx['id']].dat_lines if self.pagename == 'balance': @@ -252,22 +274,23 @@ class Handler(PlomHttpHandler): int(self.params.first('cutoff') or '0')) self.send_rendered(Path('balance.tmpl'), ctx | {'roots': balance_roots, 'valid': valid}) - elif self.pagename == 'booking': - self.send_rendered(Path('booking.tmpl'), ctx) - elif self.pagename == 'edit': - self.send_rendered(Path('edit.tmpl'), ctx) - elif self.pagename == 'raw': - self.send_rendered(Path('raw.tmpl'), + elif self.pagename in {'booking', 'edit_structured'}: + self.send_rendered(Path('edit_structured.tmpl'), ctx) + elif self.pagename == 'edit_raw': + self.send_rendered(Path('edit_raw.tmpl'), ctx) + elif self.pagename == 'ledger_raw': + self.send_rendered(Path('ledger_raw.tmpl'), ctx | {'dat_lines': self.server.dat_lines}) else: self.send_rendered( - Path('index.tmpl'), + Path('ledger_structured.tmpl'), ctx | {'dat_lines': self.server.dat_lines_sans_empty}) class Server(PlomHttpServer): """Extends parent by loading .dat file into database for Handler.""" bookings: list[Booking] + dat_lines: list[DatLine] def __init__(self, path_dat: Path, *args, **kwargs) -> None: super().__init__(PATH_TEMPLATES, (SERVER_HOST, SERVER_PORT), Handler) @@ -313,6 +336,15 @@ class Server(PlomHttpServer): '\n'.join([line.raw for line in self.dat_lines]), encoding='utf8') self.load() + def rewrite_booking(self, id_: int, new_dat_lines: list[DatLine]) -> None: + """Rewrite .dat_lines for Booking of .id_ with new_dat_lines.""" + old_booking = self.bookings[id_] + start_idx = self.dat_lines.index(old_booking.dat_lines[0]) + end_idx = self.dat_lines.index(old_booking.dat_lines[-1]) + self.dat_lines = (self.dat_lines[:start_idx] + + new_dat_lines + self.dat_lines[end_idx+1:]) + self.load_bookings() + @property def dat_lines_sans_empty(self) -> list[DatLine]: """Return only those .data_lines with .code or .comment.""" diff --git a/templates/_base.tmpl b/templates/_base.tmpl index a613a1b..d6881d2 100644 --- a/templates/_base.tmpl +++ b/templates/_base.tmpl @@ -13,7 +13,7 @@ span.warning, table.warning tbody tr td, tr.warning td { background-color: #ff88
-home · raw · balance · {% if tainted %} · unsaved changes: {% endif %} +ledger structured / raw · balance · {% if tainted %} · unsaved changes: {% endif %}

{% block content %}{% endblock %} diff --git a/templates/_macros.tmpl b/templates/_macros.tmpl index 850f4c5..1412c84 100644 --- a/templates/_macros.tmpl +++ b/templates/_macros.tmpl @@ -7,19 +7,17 @@ td.amt, td.curr { font-family: monospace; font-size: 1.3em; } td.invalid, tr.warning td.invalid { background-color: #ff0000; } {% endmacro %} -{% macro table_dat_lines(dat_lines, single, raw) %} +{% macro table_dat_lines(dat_lines, raw) %} {% for dat_line in dat_lines %} - {% if (not (raw or single)) and dat_line.is_intro and loop.index > 1 %} + {% if (not raw) and dat_line.is_intro and loop.index > 1 %} {% endif %} - {% if not single %} - {% if dat_line.is_intro %} - - {% else %} - - {% endif %} + {% if dat_line.is_intro %} + + {% else %} + {% endif %} {% if raw %} @@ -44,9 +42,7 @@ td.invalid, tr.warning td.invalid { background-color: #ff0000; } {% if dat_line.error and not raw %} - {% if not single %} - - {% endif %} + diff --git a/templates/booking.tmpl b/templates/booking.tmpl deleted file mode 100644 index 9470c27..0000000 --- a/templates/booking.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block css %} -{{ macros.css_td_money() }} -{{ macros.css_errors() }} -{% endblock %} - -{% block content %} -edit -
-{{ macros.table_dat_lines(dat_lines, single=true, raw=false) }} -{% endblock %} diff --git a/templates/edit_raw.tmpl b/templates/edit_raw.tmpl new file mode 100644 index 0000000..ad344a8 --- /dev/null +++ b/templates/edit_raw.tmpl @@ -0,0 +1,18 @@ +{% extends '_base.tmpl' %} + + +{% block css %} +{{ macros.css_td_money() }} +{{ macros.css_errors() }} +{% endblock %} + +{% block content %} +edit structured +
+ + + + +{% endblock %} diff --git a/templates/edit_structured.tmpl b/templates/edit_structured.tmpl new file mode 100644 index 0000000..6e13a9a --- /dev/null +++ b/templates/edit_structured.tmpl @@ -0,0 +1,37 @@ +{% extends '_base.tmpl' %} + + +{% block css %} +{{ macros.css_td_money() }} +{{ macros.css_errors() }} +{% endblock %} + +{% block content %} +edit raw +
+ +
 
#/b#/b
{{dat_line.error}}
+{% for dat_line in dat_lines %} + + {% if dat_line.is_intro %} + + {% elif not dat_line.error %} + + + + {% else %} + + {% endif %} + + + {% if dat_line.error %} + + + + + {% endif %} +{% endfor %} +
{{dat_line.error}}
+ + +{% endblock %} diff --git a/templates/index.tmpl b/templates/index.tmpl deleted file mode 100644 index 886a01c..0000000 --- a/templates/index.tmpl +++ /dev/null @@ -1,11 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block css %} -{{ macros.css_td_money() }} -{{ macros.css_errors() }} -{% endblock %} - -{% block content %} -{{ macros.table_dat_lines(dat_lines, single=false, raw=false) }} -{% endblock %} diff --git a/templates/ledger_raw.tmpl b/templates/ledger_raw.tmpl new file mode 100644 index 0000000..d09e722 --- /dev/null +++ b/templates/ledger_raw.tmpl @@ -0,0 +1,12 @@ +{% extends '_base.tmpl' %} + + +{% block css %} +table { font-family: monospace; } +{{ macros.css_errors() }} +{% endblock %} + +{% block content %} +{{ macros.table_dat_lines(dat_lines, raw=true) }} +{% endblock %} + diff --git a/templates/ledger_structured.tmpl b/templates/ledger_structured.tmpl new file mode 100644 index 0000000..1669ce9 --- /dev/null +++ b/templates/ledger_structured.tmpl @@ -0,0 +1,11 @@ +{% extends '_base.tmpl' %} + + +{% block css %} +{{ macros.css_td_money() }} +{{ macros.css_errors() }} +{% endblock %} + +{% block content %} +{{ macros.table_dat_lines(dat_lines, raw=false) }} +{% endblock %} diff --git a/templates/raw.tmpl b/templates/raw.tmpl deleted file mode 100644 index 8b2d621..0000000 --- a/templates/raw.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -{% extends '_base.tmpl' %} - - -{% block css %} -table { font-family: monospace; } -{{ macros.css_errors() }} -{% endblock %} - -{% block content %} -{{ macros.table_dat_lines(dat_lines, single=false, raw=true) }} -{% endblock %} -