From 78477efba6117f0fa78e0bde6c96e23276c6b03a Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Thu, 30 Apr 2020 01:24:31 -0700 Subject: [PATCH] Add index sorting and phantom styling on contents page --- amanuensis/lexicon/__init__.py | 2 + amanuensis/lexicon/gameloop.py | 47 +++++++++++++++++++ amanuensis/server/lexicon/__init__.py | 25 +++++----- .../server/lexicon/lexicon.contents.jinja | 11 +++-- 4 files changed, 69 insertions(+), 16 deletions(-) diff --git a/amanuensis/lexicon/__init__.py b/amanuensis/lexicon/__init__.py index 3cece3d..b795fc9 100644 --- a/amanuensis/lexicon/__init__.py +++ b/amanuensis/lexicon/__init__.py @@ -8,6 +8,7 @@ from .gameloop import ( get_draft, title_constraint_analysis, content_constraint_analysis, + sort_by_index_spec, attempt_publish) from .setup import ( player_can_join_lexicon, @@ -23,6 +24,7 @@ __all__ = [member.__name__ for member in [ get_draft, title_constraint_analysis, content_constraint_analysis, + sort_by_index_spec, attempt_publish, player_can_join_lexicon, add_player_to_lexicon, diff --git a/amanuensis/lexicon/gameloop.py b/amanuensis/lexicon/gameloop.py index 60923e4..b7cb48d 100644 --- a/amanuensis/lexicon/gameloop.py +++ b/amanuensis/lexicon/gameloop.py @@ -2,6 +2,7 @@ Submodule of functions for managing lexicon games during the core game loop of writing and publishing articles. """ +from collections import OrderedDict from typing import Iterable, Any, List, Optional, Tuple from amanuensis.config import ReadOnlyOrderedDict @@ -163,6 +164,52 @@ def content_constraint_analysis( return infos, warnings, errors +def index_match(index, title) -> bool: + if index.type == 'char': + return titlesort(title)[0].upper() in index.pattern.upper() + if index.type == 'prefix': + return title.startswith(index.pattern) + if index.type == 'etc': + return True + raise ValueError(f'Unknown index type: "{index.type}"') + + +def sort_by_index_spec(articles, index_specs, key=None): + """ + Sorts a list under the appropriate index in the given index + specification list. If the list is not a list of titles, the key + function should map the contents to the indexable strings. + """ + if key is None: + def key(k): + return k + # Determine the index evaluation order vs list order + index_by_pri = {} + index_list_order = [] + for index in index_specs: + if index.pri not in index_by_pri: + index_by_pri[index.pri] = [] + index_by_pri[index.pri].append(index) + index_list_order.append(index) + index_eval_order = [ + index + for pri in sorted(index_by_pri.keys(), reverse=True) + for index in index_by_pri[pri]] + print(str(articles)[:200]) + articles_titlesorted = sorted( + articles, + key=lambda a: titlesort(key(a))) + print(str(articles_titlesorted)[:200]) + indexed = OrderedDict() + for index in index_list_order: + indexed[index.pattern] = [] + for article in articles_titlesorted: + for index in index_eval_order: + if index_match(index, key(article)): + indexed[index.pattern].append(article) + return indexed + + def attempt_publish(lexicon: LexiconModel) -> bool: """ If the lexicon's publsh policy allows the current set of approved diff --git a/amanuensis/server/lexicon/__init__.py b/amanuensis/server/lexicon/__init__.py index 74bedfa..412949d 100644 --- a/amanuensis/server/lexicon/__init__.py +++ b/amanuensis/server/lexicon/__init__.py @@ -8,9 +8,11 @@ from flask import ( Markup) from flask_login import login_required, current_user -from amanuensis.lexicon import player_can_join_lexicon, add_player_to_lexicon +from amanuensis.lexicon import ( + player_can_join_lexicon, + add_player_to_lexicon, + sort_by_index_spec) from amanuensis.models import LexiconModel -from amanuensis.parser import filesafe_title from amanuensis.server.helpers import ( lexicon_param, player_required_if_not_public) @@ -61,17 +63,14 @@ def join(name): @lexicon_param @player_required_if_not_public def contents(name): - articles = [] - filenames = g.lexicon.ctx.article.ls() - for filename in filenames: - with g.lexicon.ctx.article.read(filename) as a: - articles.append({ - 'title': a.title, - 'link': url_for('lexicon.article', - name=name, - title=filesafe_title(a.title)), - }) - return render_template('lexicon.contents.jinja', articles=articles) + with g.lexicon.ctx.read('info') as info: + indexed = sort_by_index_spec(info, g.lexicon.cfg.article.index.list) + for articles in indexed.values(): + for i in range(len(articles)): + articles[i] = { + 'title': articles[i], + **info.get(articles[i])} + return render_template('lexicon.contents.jinja', indexed=indexed) @bp_lexicon.route('/article/') diff --git a/amanuensis/server/lexicon/lexicon.contents.jinja b/amanuensis/server/lexicon/lexicon.contents.jinja index dec7b33..811ddf6 100644 --- a/amanuensis/server/lexicon/lexicon.contents.jinja +++ b/amanuensis/server/lexicon/lexicon.contents.jinja @@ -8,13 +8,18 @@ <span style="color:#ff0000">{{ message }}</span><br> {% endfor %} -{% if articles %} +{% for index in indexed %} +<b>{{ index }}</b> +{% if indexed[index] %} <ul> -{% for article in articles %} -<li><a href="{{ article.link }}">{{ article.title }}</a></li> +{% for article in indexed[index] %} +<li><a href="{{ article.title|articlelink }}" class="{{ 'phantom' if not article.character else '' }}"> + {{ article.title }} +</a></li> {% endfor %} </ul> {% endif %} +{% endfor %} {% endblock %} {% set template_content_blocks = [self.main()] %} \ No newline at end of file