diff --git a/js/tail_log.js b/js/tail_log.js index e4d4274d5e..52363aa5b3 100644 --- a/js/tail_log.js +++ b/js/tail_log.js @@ -4,6 +4,7 @@ Liberapay.stream_lines = function(url, data_cb, error_cb) { function fetch_lines(first_pos) { jQuery.ajax({ url: url, + dataType: 'text', headers: {Range: 'x-lines='+first_pos+'-'}, }).done(function(data, textStatus, xhr) { var file_is_partial = false; diff --git a/liberapay/utils/__init__.py b/liberapay/utils/__init__.py index bb54da4bc5..96c5c5470d 100644 --- a/liberapay/utils/__init__.py +++ b/liberapay/utils/__init__.py @@ -640,19 +640,26 @@ def check_address_v2(addr): return True -def render_postal_address(addr, single_line=False): +def render_postal_address(addr, single_line=False, format='local'): if not check_address_v2(addr): return - # FIXME The rendering below is simplistic, we should implement - # https://github.com/liberapay/liberapay.com/issues/1056 - elements = [addr['local_address'], addr['city'], addr['postal_code']] - if addr.get('region'): - elements.append(addr['region']) - elements.append(LOCALE_EN.countries[addr['country']]) - if single_line: - return ', '.join(elements) + if format == 'local': + # FIXME The rendering below is simplistic, we should implement + # https://github.com/liberapay/liberapay.com/issues/1056 + elements = [addr['local_address'], addr['city'], addr['postal_code']] + if addr.get('region'): + elements.append(addr['region']) + elements.append(LOCALE_EN.countries[addr['country']]) + sep = ', ' if single_line else '\n' + elif format == 'downward': + elements = [LOCALE_EN.countries[addr['country']]] + if addr.get('region'): + elements.append(addr['region']) + elements += [addr['city'], addr['postal_code'], addr['local_address']] + sep = ' / ' if single_line else '\n' else: - return '\n'.join(elements) + raise ValueError(f"unknown `format` value {format!r}") + return sep.join(elements) def mkdir_p(path): diff --git a/liberapay/wireup.py b/liberapay/wireup.py index d283e30cf1..8938aa6d69 100644 --- a/liberapay/wireup.py +++ b/liberapay/wireup.py @@ -48,7 +48,7 @@ from liberapay.utils import find_files, markdown, resolve from liberapay.utils.emails import compile_email_spt from liberapay.utils.http_caching import asset_etag -from liberapay.utils.types import Object +from liberapay.utils.types import LocalizedString, Object from liberapay.version import get_version from liberapay.website import Website @@ -172,6 +172,20 @@ def cast_currency_basket(v, cursor): except (psycopg2.ProgrammingError, NeedDatabase): pass + def cast_localized_string(v, cursor): + if v in (None, '(,)'): + return None + else: + text, lang = v[1:-1].split(',') + if text.startswith('"') and text.endswith('"'): + text = text[1:-1].replace('""', '"') + return LocalizedString(text, lang) + try: + oid = db.one("SELECT 'localized_string'::regtype::oid") + register_type(new_type((oid,), 'localized_string', cast_localized_string)) + except (psycopg2.ProgrammingError, NeedDatabase): + pass + if db and env.override_query_cache: db.cache.max_size = 0 diff --git a/sql/branch.sql b/sql/branch.sql new file mode 100644 index 0000000000..cd4060a71b --- /dev/null +++ b/sql/branch.sql @@ -0,0 +1 @@ +CREATE TYPE localized_string AS (string text, lang text); diff --git a/style/base/utils.scss b/style/base/utils.scss index 5ef82676ee..32325ca144 100644 --- a/style/base/utils.scss +++ b/style/base/utils.scss @@ -31,6 +31,10 @@ margin-top: 0 !important; } +.m-0 { + margin: 0; +} + .mb-3 { margin-bottom: ($line-height-computed / 2); } @@ -47,6 +51,14 @@ margin-bottom: $line-height-computed; } +.row-gap-3 { + row-gap: 0.5em; +} + +.column-gap-2 { + column-gap: 0.3em; +} + .pre-wrap { white-space: pre-wrap; } diff --git a/templates/macros/pagination.html b/templates/macros/pagination.html index fa21522801..3b74cd1535 100644 --- a/templates/macros/pagination.html +++ b/templates/macros/pagination.html @@ -27,12 +27,13 @@ % if current_page > 1 or has_more