From f9f46523af63e43d9f0d3f55e80c1b3a65e8ccda Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 10:42:14 +0100 Subject: [PATCH 01/10] Add plomlib submodule. --- .gitmodules | 3 +++ plomlib | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 plomlib diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..42cf7f3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "plomlib"] + path = plomlib + url = https://plomlompom.com/repos/clone/plomlib diff --git a/plomlib b/plomlib new file mode 160000 index 0000000..e7202fc --- /dev/null +++ b/plomlib @@ -0,0 +1 @@ +Subproject commit e7202fcfd78c6a60bd90da789a68c8ec4baf7b1a -- 2.30.2 From 1a8df0730e4eda4184cde0e848d607ded3f8eee7 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 10:42:30 +0100 Subject: [PATCH 02/10] Define jinja dependency. --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7cb100d --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Jinja2==3.1.5 -- 2.30.2 From 1e47710da184388afa04a77047b14c08c279efb4 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 10:42:46 +0100 Subject: [PATCH 03/10] Initial server code and template commit. --- ledger.py | 122 +++++++++++++++++++++++++++++++++++++++++++ templates/_base.tmpl | 17 ++++++ templates/index.tmpl | 33 ++++++++++++ templates/raw.tmpl | 22 ++++++++ 4 files changed, 194 insertions(+) create mode 100755 ledger.py create mode 100644 templates/_base.tmpl create mode 100644 templates/index.tmpl create mode 100644 templates/raw.tmpl diff --git a/ledger.py b/ledger.py new file mode 100755 index 0000000..746d8a3 --- /dev/null +++ b/ledger.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +"""Viewer for ledger .dat files.""" +from decimal import Decimal +from os import environ +from pathlib import Path +from sys import exit as sys_exit +from typing import Optional +from plomlib.web import PlomHttpHandler, PlomHttpServer, PlomQueryMap + + +LEDGER_DAT = environ.get('LEDGER_DAT') +SERVER_PORT = 8084 +SERVER_HOST = '127.0.0.1' +PATH_TEMPLATES = Path('templates') + + +class DatLine: + """Line of .dat file parsed into comments and machine-readable data.""" + + def __init__(self, line: str) -> None: + self.raw = line[:] + halves = [t.rstrip() for t in line.split(';', maxsplit=1)] + self.comment = halves[1] if len(halves) > 1 else '' + self.code = halves[0] + self.type = 'no_data' + self.booking: Optional[Booking] = None + if self.code: + self.type = 'invalid' + if self.code[0].isspace(): + toks = self.code.lstrip().split() + self.acc = toks[0] + if 1 == len(toks): + self.amt, self.curr = '', '' + self.type = 'value' + elif 3 == len(toks): + amt_dec = Decimal(toks[1]) + exp = amt_dec.as_tuple().exponent + assert isinstance(exp, int) + self.amt = (f'{amt_dec:.1f}…' if exp < -2 + else f'{amt_dec:.2f}') + self.curr = toks[2] + self.type = 'value' + else: + self.type = 'intro' + + @property + def is_empty(self) -> bool: + """Return if both .code and .comment are empty.""" + return not bool(self.code or self.comment) + + @property + def raw_nbsp(self) -> str: + """Return .raw but ensure whitespace as  , and at least one.""" + if not self.raw: + return ' ' + return self.raw.replace(' ', ' ') + + +class Booking: + """Represents lines of individual booking.""" + # pylint: disable=too-few-public-methods + + def __init__(self, id_: int, idx_start_end: tuple[int, int]) -> None: + self.id_ = id_ + self.idx_start, self.idx_end = idx_start_end + + +class Handler(PlomHttpHandler): + # pylint: disable=missing-class-docstring + mapper = PlomQueryMap + + def do_POST(self) -> None: + # pylint: disable=invalid-name,missing-function-docstring + self.redirect(Path('')) + + def do_GET(self) -> None: + # pylint: disable=invalid-name,missing-function-docstring + if self.pagename == 'booking': + b = self.server.bookings[int(self.params.first('idx'))] + dat_lines = self.server.dat_lines[b.idx_start:b.idx_end] + self.send_rendered(Path('index.tmpl'), {'dat_lines': dat_lines}) + elif self.pagename == 'raw': + self.send_rendered(Path('raw.tmpl'), + {'dat_lines': self.server.dat_lines}) + else: + self.send_rendered(Path('index.tmpl'), + {'dat_lines': self.server.dat_lines_sans_empty}) + + +class Server(PlomHttpServer): + """Extends parent by loading .dat file into database for Handler.""" + + def __init__(self, path_dat: Path, *args, **kwargs) -> None: + super().__init__(PATH_TEMPLATES, (SERVER_HOST, SERVER_PORT), Handler) + self.dat_lines = [ + DatLine(line) + for line in path_dat.read_text(encoding='utf8').splitlines()] + self.bookings: list[Booking] = [] + code_lines = [dl.code for dl in self.dat_lines] + in_booking = False + last_booking_start = -1 + for idx, code in enumerate(code_lines + ['']): + if in_booking and not code: + in_booking = False + self.bookings += [Booking(len(self.bookings), + (last_booking_start, idx))] + self.dat_lines[last_booking_start].booking = self.bookings[-1] + elif code and not in_booking: + in_booking = True + last_booking_start = idx + + @property + def dat_lines_sans_empty(self) -> list[DatLine]: + """Return only those .data_lines with .code or .comment.""" + return [dl for dl in self.dat_lines if not dl.is_empty] + + +if __name__ == "__main__": + if not LEDGER_DAT: + print("LEDGER_DAT environment variable not set.") + sys_exit(1) + Server(Path(LEDGER_DAT)).serve() diff --git a/templates/_base.tmpl b/templates/_base.tmpl new file mode 100644 index 0000000..8e6de41 --- /dev/null +++ b/templates/_base.tmpl @@ -0,0 +1,17 @@ + + + + + + + +home · raw +
+{% block content %}{% endblock %} + + diff --git a/templates/index.tmpl b/templates/index.tmpl new file mode 100644 index 0000000..ca1e096 --- /dev/null +++ b/templates/index.tmpl @@ -0,0 +1,33 @@ +{% extends '_base.tmpl' %} + +{% block css %} +td.amt { text-align: right } +td.amt, td.curr { font-family: monospace; font-size: 1.3em; } +td.curr { text-align: center; } +{% endblock %} + +{% block content %} +
+
+
+ +{% for l in dat_lines %} + {% if "intro" == l.type and loop.index > 1 %}{% endif %} + + {% if l.type == "intro" %} + + {% else %} + + {% endif %} + {% if l.type == "value" %} + + {% elif l.type == "intro" %} + + {% else %} + + {% endif %} + + +{% endfor %} +
 
#{{l.amt}}{{l.curr|truncate(4,true,"…")}}{{l.acc}}{{l.code}}{{l.code}}{{l.comment}}
+{% endblock %} diff --git a/templates/raw.tmpl b/templates/raw.tmpl new file mode 100644 index 0000000..34f69d1 --- /dev/null +++ b/templates/raw.tmpl @@ -0,0 +1,22 @@ +{% extends '_base.tmpl' %} + +{% block css %} +table { font-family: monospace; } +{% endblock %} + +{% block content %} + +{% for l in dat_lines %} + + {% if l.type == "intro" %} + + + {% else %} + + + {% endif %} + +{% endfor %} +
#{{l.raw_nbsp}}{{l.raw_nbsp}}
+{% endblock %} + -- 2.30.2 From 586b58498d1c4d2998dddea34492c110f99455ae Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 11:54:09 +0100 Subject: [PATCH 04/10] For Booking view, use '/{Booking.id_}' rather than '?idx={Booking.id_}'. --- ledger.py | 2 +- templates/index.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ledger.py b/ledger.py index 746d8a3..eee9c5d 100755 --- a/ledger.py +++ b/ledger.py @@ -76,7 +76,7 @@ class Handler(PlomHttpHandler): def do_GET(self) -> None: # pylint: disable=invalid-name,missing-function-docstring if self.pagename == 'booking': - b = self.server.bookings[int(self.params.first('idx'))] + b = self.server.bookings[int(self.path_toks[2])] dat_lines = self.server.dat_lines[b.idx_start:b.idx_end] self.send_rendered(Path('index.tmpl'), {'dat_lines': dat_lines}) elif self.pagename == 'raw': diff --git a/templates/index.tmpl b/templates/index.tmpl index ca1e096..bf83499 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -22,7 +22,7 @@ td.curr { text-align: center; } {% if l.type == "value" %} {{l.amt}}{{l.curr|truncate(4,true,"…")}}{{l.acc}} {% elif l.type == "intro" %} - {{l.code}} + {{l.code}} {% else %} {{l.code}} {% endif %} -- 2.30.2 From 4ce3720993e0533723cf967cb0941eec441dc40f Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 12:05:17 +0100 Subject: [PATCH 05/10] Store relevant lines in Booking, calc ending index from their number. --- ledger.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/ledger.py b/ledger.py index eee9c5d..2a1fdd6 100755 --- a/ledger.py +++ b/ledger.py @@ -60,9 +60,11 @@ class Booking: """Represents lines of individual booking.""" # pylint: disable=too-few-public-methods - def __init__(self, id_: int, idx_start_end: tuple[int, int]) -> None: + def __init__(self, id_: int, idx_start: int, b_lines: list[str]) -> None: self.id_ = id_ - self.idx_start, self.idx_end = idx_start_end + self.idx_start = idx_start + self.b_lines = b_lines + self.idx_end = self.idx_start + len(self.b_lines) class Handler(PlomHttpHandler): @@ -97,17 +99,18 @@ class Server(PlomHttpServer): for line in path_dat.read_text(encoding='utf8').splitlines()] self.bookings: list[Booking] = [] code_lines = [dl.code for dl in self.dat_lines] - in_booking = False last_booking_start = -1 + b_lines: list[str] = [] for idx, code in enumerate(code_lines + ['']): - if in_booking and not code: - in_booking = False + if code: + if not b_lines: + last_booking_start = idx + b_lines += [code] + elif b_lines: self.bookings += [Booking(len(self.bookings), - (last_booking_start, idx))] + last_booking_start, b_lines)] + b_lines.clear() self.dat_lines[last_booking_start].booking = self.bookings[-1] - elif code and not in_booking: - in_booking = True - last_booking_start = idx @property def dat_lines_sans_empty(self) -> list[DatLine]: -- 2.30.2 From 165edaae3a1749dd9e5473578a9b740e275c77ce Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 12:35:39 +0100 Subject: [PATCH 06/10] Move interpretation of .code lines into new BookingLine construct. --- ledger.py | 81 ++++++++++++++++++++++++++------------------ templates/index.tmpl | 6 ++-- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/ledger.py b/ledger.py index 2a1fdd6..8a50435 100755 --- a/ledger.py +++ b/ledger.py @@ -22,26 +22,17 @@ class DatLine: halves = [t.rstrip() for t in line.split(';', maxsplit=1)] self.comment = halves[1] if len(halves) > 1 else '' self.code = halves[0] - self.type = 'no_data' - self.booking: Optional[Booking] = None - if self.code: - self.type = 'invalid' - if self.code[0].isspace(): - toks = self.code.lstrip().split() - self.acc = toks[0] - if 1 == len(toks): - self.amt, self.curr = '', '' - self.type = 'value' - elif 3 == len(toks): - amt_dec = Decimal(toks[1]) - exp = amt_dec.as_tuple().exponent - assert isinstance(exp, int) - self.amt = (f'{amt_dec:.1f}…' if exp < -2 - else f'{amt_dec:.2f}') - self.curr = toks[2] - self.type = 'value' - else: - self.type = 'intro' + self.booking_line: Optional[BookingLine] = None + + @property + def type(self) -> str: + """Provide categorization of .code part.""" + return self.booking_line.type if self.booking_line else 'no_data' + + @property + def booking_id(self) -> int: + """If .booking_line, its .booking_id, else -1.""" + return self.booking_line.booking_id if self.booking_line else -1 @property def is_empty(self) -> bool: @@ -56,15 +47,41 @@ class DatLine: return self.raw.replace(' ', ' ') +class BookingLine: + """Parsed code part of a DatLine belonging to a Booking.""" + + def __init__(self, booking_id: int, code: str) -> None: + self.booking_id = booking_id + self.type = 'invalid' + self.acc, self.amt, self.curr = '', '', '' + if code[0].isspace(): + toks = code.lstrip().split() + self.acc = toks[0] + if 1 == len(toks): + self.type = 'value' + elif 3 == len(toks): + amt_dec = Decimal(toks[1]) + exp = amt_dec.as_tuple().exponent + assert isinstance(exp, int) + self.amt = (f'{amt_dec:.1f}…' if exp < -2 + else f'{amt_dec:.2f}') + self.curr = toks[2] + self.type = 'value' + else: + self.type = 'intro' + + class Booking: """Represents lines of individual booking.""" # pylint: disable=too-few-public-methods - def __init__(self, id_: int, idx_start: int, b_lines: list[str]) -> None: + def __init__(self, id_: int, idx_start: int, dat_lines: list[DatLine] + ) -> None: self.id_ = id_ self.idx_start = idx_start - self.b_lines = b_lines - self.idx_end = self.idx_start + len(self.b_lines) + self.idx_end = self.idx_start + len(dat_lines) + for dat_line in dat_lines: + dat_line.booking_line = BookingLine(self.id_, dat_line.code) class Handler(PlomHttpHandler): @@ -98,19 +115,17 @@ class Server(PlomHttpServer): DatLine(line) for line in path_dat.read_text(encoding='utf8').splitlines()] self.bookings: list[Booking] = [] - code_lines = [dl.code for dl in self.dat_lines] last_booking_start = -1 - b_lines: list[str] = [] - for idx, code in enumerate(code_lines + ['']): - if code: - if not b_lines: + booking_lines: list[DatLine] = [] + for idx, dat_line in enumerate(self.dat_lines + [DatLine('')]): + if dat_line.code: + if not booking_lines: last_booking_start = idx - b_lines += [code] - elif b_lines: + booking_lines += [dat_line] + elif booking_lines: self.bookings += [Booking(len(self.bookings), - last_booking_start, b_lines)] - b_lines.clear() - self.dat_lines[last_booking_start].booking = self.bookings[-1] + last_booking_start, booking_lines)] + booking_lines.clear() @property def dat_lines_sans_empty(self) -> list[DatLine]: diff --git a/templates/index.tmpl b/templates/index.tmpl index bf83499..301b2d4 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -15,14 +15,14 @@ td.curr { text-align: center; } {% if "intro" == l.type and loop.index > 1 %} {% endif %} {% if l.type == "intro" %} - # + # {% else %} {% endif %} {% if l.type == "value" %} - {{l.amt}}{{l.curr|truncate(4,true,"…")}}{{l.acc}} + {{l.booking_line.amt}}{{l.booking_line.curr|truncate(4,true,"…")}}{{l.booking_line.acc}} {% elif l.type == "intro" %} - {{l.code}} + {{l.code}} {% else %} {{l.code}} {% endif %} -- 2.30.2 From 05b77bc289db675fad9c70961ae06a1afa3e7a0a Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 12:36:00 +0100 Subject: [PATCH 07/10] Fix buggy links in raw view. --- templates/raw.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/raw.tmpl b/templates/raw.tmpl index 34f69d1..20980ae 100644 --- a/templates/raw.tmpl +++ b/templates/raw.tmpl @@ -9,8 +9,8 @@ table { font-family: monospace; } {% for l in dat_lines %} {% if l.type == "intro" %} - # - {{l.raw_nbsp}} + # + {{l.raw_nbsp}} {% else %} {{l.raw_nbsp}} -- 2.30.2 From 05d0535ef9f976f788bb5fe7abb3a9b98b04b67d Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 12:51:51 +0100 Subject: [PATCH 08/10] Improve Booking-specific view. --- ledger.py | 25 ++++++++++--------------- templates/booking.tmpl | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 templates/booking.tmpl diff --git a/ledger.py b/ledger.py index 8a50435..24e8311 100755 --- a/ledger.py +++ b/ledger.py @@ -75,12 +75,10 @@ class Booking: """Represents lines of individual booking.""" # pylint: disable=too-few-public-methods - def __init__(self, id_: int, idx_start: int, dat_lines: list[DatLine] - ) -> None: + def __init__(self, id_: int, dat_lines: list[DatLine]) -> None: self.id_ = id_ - self.idx_start = idx_start - self.idx_end = self.idx_start + len(dat_lines) - for dat_line in dat_lines: + self.dat_lines = dat_lines + for dat_line in self.dat_lines: dat_line.booking_line = BookingLine(self.id_, dat_line.code) @@ -95,9 +93,10 @@ class Handler(PlomHttpHandler): def do_GET(self) -> None: # pylint: disable=invalid-name,missing-function-docstring if self.pagename == 'booking': - b = self.server.bookings[int(self.path_toks[2])] - dat_lines = self.server.dat_lines[b.idx_start:b.idx_end] - self.send_rendered(Path('index.tmpl'), {'dat_lines': dat_lines}) + self.send_rendered( + Path('booking.tmpl'), + {'dat_lines': + self.server.bookings[int(self.path_toks[2])].dat_lines}) elif self.pagename == 'raw': self.send_rendered(Path('raw.tmpl'), {'dat_lines': self.server.dat_lines}) @@ -115,17 +114,13 @@ class Server(PlomHttpServer): DatLine(line) for line in path_dat.read_text(encoding='utf8').splitlines()] self.bookings: list[Booking] = [] - last_booking_start = -1 booking_lines: list[DatLine] = [] - for idx, dat_line in enumerate(self.dat_lines + [DatLine('')]): + for dat_line in self.dat_lines + [DatLine('')]: if dat_line.code: - if not booking_lines: - last_booking_start = idx booking_lines += [dat_line] elif booking_lines: - self.bookings += [Booking(len(self.bookings), - last_booking_start, booking_lines)] - booking_lines.clear() + self.bookings += [Booking(len(self.bookings), booking_lines)] + booking_lines = [] @property def dat_lines_sans_empty(self) -> list[DatLine]: diff --git a/templates/booking.tmpl b/templates/booking.tmpl new file mode 100644 index 0000000..1bfea62 --- /dev/null +++ b/templates/booking.tmpl @@ -0,0 +1,25 @@ +{% extends '_base.tmpl' %} + +{% block css %} +td.amt { text-align: right } +td.amt, td.curr { font-family: monospace; font-size: 1.3em; } +td.curr { text-align: center; } +{% endblock %} + +{% block content %} + +{% for l in dat_lines %} + + {% if l.type == "value" %} + + {% elif l.type == "intro" %} + + {% else %} + + {% endif %} + + +{% endfor %} +
{{l.booking_line.amt}}{{l.booking_line.curr|truncate(4,true,"…")}}{{l.booking_line.acc}}{{l.code}}{{l.code}}{{l.comment}}
+{% endblock %} + -- 2.30.2 From 257f3da062b47827bfe906c7628b32c5bfea47f4 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 12:57:42 +0100 Subject: [PATCH 09/10] Minor linking fix to raw view template. --- templates/raw.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/raw.tmpl b/templates/raw.tmpl index 20980ae..59e951f 100644 --- a/templates/raw.tmpl +++ b/templates/raw.tmpl @@ -10,7 +10,7 @@ table { font-family: monospace; } {% if l.type == "intro" %} # - {{l.raw_nbsp}} + {{l.raw_nbsp}} {% else %} {{l.raw_nbsp}} -- 2.30.2 From 834df9102bb71a8bcbda291d6504a6a45b357e78 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Mon, 20 Jan 2025 13:33:22 +0100 Subject: [PATCH 10/10] Refactor templates. --- templates/_base.tmpl | 1 + templates/_macros.tmpl | 42 ++++++++++++++++++++++++++++++++++++++++++ templates/booking.tmpl | 19 ++----------------- templates/index.tmpl | 25 ++----------------------- templates/raw.tmpl | 14 +------------- 5 files changed, 48 insertions(+), 53 deletions(-) create mode 100644 templates/_macros.tmpl diff --git a/templates/_base.tmpl b/templates/_base.tmpl index 8e6de41..2953be2 100644 --- a/templates/_base.tmpl +++ b/templates/_base.tmpl @@ -1,3 +1,4 @@ +{% import '_macros.tmpl' as macros %} diff --git a/templates/_macros.tmpl b/templates/_macros.tmpl new file mode 100644 index 0000000..4df4fc6 --- /dev/null +++ b/templates/_macros.tmpl @@ -0,0 +1,42 @@ +{% macro css_value_line() %} +td.amt { text-align: right } +td.amt, td.curr { font-family: monospace; font-size: 1.3em; } +td.curr { text-align: center; } +{% endmacro %} + +{% macro table_dat_lines(dat_lines, single, raw) %} + +{% for dat_line in dat_lines %} + {% if (not (raw or single)) and dat_line.type == "intro" and loop.index > 1 %} + + {% endif %} + + {% if not single %} + {% if dat_line.type == "intro" %} + + {% else %} + + {% endif %} + {% endif %} + {% if raw %} + {% if dat_line.type == "intro" %} + + {% else %} + + {% endif %} + {% else %} + {% if dat_line.type == "intro" %} + + {% elif dat_line.type == "value" %} + + + + {% else %} + + {% endif %} + + {% endif %} + +{% endfor %} +
 
#{{dat_line.raw_nbsp}}{{dat_line.raw_nbsp}}{{dat_line.code}}{{dat_line.booking_line.amt}}{{dat_line.booking_line.curr|truncate(4,true,"…")}}{{dat_line.booking_line.acc}}{{dat_line.code}}{{dat_line.comment}}
+{% endmacro %} diff --git a/templates/booking.tmpl b/templates/booking.tmpl index 1bfea62..86273b9 100644 --- a/templates/booking.tmpl +++ b/templates/booking.tmpl @@ -1,25 +1,10 @@ {% extends '_base.tmpl' %} {% block css %} -td.amt { text-align: right } -td.amt, td.curr { font-family: monospace; font-size: 1.3em; } -td.curr { text-align: center; } +{{ macros.css_value_line() }} {% endblock %} {% block content %} - -{% for l in dat_lines %} - - {% if l.type == "value" %} - - {% elif l.type == "intro" %} - - {% else %} - - {% endif %} - - -{% endfor %} -
{{l.booking_line.amt}}{{l.booking_line.curr|truncate(4,true,"…")}}{{l.booking_line.acc}}{{l.code}}{{l.code}}{{l.comment}}
+{{ macros.table_dat_lines(dat_lines, single=true, raw=false) }} {% endblock %} diff --git a/templates/index.tmpl b/templates/index.tmpl index 301b2d4..fc24e6e 100644 --- a/templates/index.tmpl +++ b/templates/index.tmpl @@ -1,33 +1,12 @@ {% extends '_base.tmpl' %} {% block css %} -td.amt { text-align: right } -td.amt, td.curr { font-family: monospace; font-size: 1.3em; } -td.curr { text-align: center; } +{{ macros.css_value_line() }} {% endblock %} {% block content %}

- -{% for l in dat_lines %} - {% if "intro" == l.type and loop.index > 1 %}{% endif %} - - {% if l.type == "intro" %} - - {% else %} - - {% endif %} - {% if l.type == "value" %} - - {% elif l.type == "intro" %} - - {% else %} - - {% endif %} - - -{% endfor %} -
 
#{{l.booking_line.amt}}{{l.booking_line.curr|truncate(4,true,"…")}}{{l.booking_line.acc}}{{l.code}}{{l.code}}{{l.comment}}
+{{ macros.table_dat_lines(dat_lines, single=false, raw=false) }} {% endblock %} diff --git a/templates/raw.tmpl b/templates/raw.tmpl index 59e951f..6851d93 100644 --- a/templates/raw.tmpl +++ b/templates/raw.tmpl @@ -5,18 +5,6 @@ table { font-family: monospace; } {% endblock %} {% block content %} - -{% for l in dat_lines %} - - {% if l.type == "intro" %} - - - {% else %} - - - {% endif %} - -{% endfor %} -
#{{l.raw_nbsp}}{{l.raw_nbsp}}
+{{ macros.table_dat_lines(dat_lines, single=false, raw=true) }} {% endblock %} -- 2.30.2