From 8446adcc835a41d5f0403f2c7359161107b8c741 Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Wed, 29 Apr 2020 23:23:46 -0700 Subject: [PATCH] Implement index list setting field --- .../server/session/session.settings.jinja | 3 ++ amanuensis/server/session/settings.py | 49 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/amanuensis/server/session/session.settings.jinja b/amanuensis/server/session/session.settings.jinja index b7bf747..031b08f 100644 --- a/amanuensis/server/session/session.settings.jinja +++ b/amanuensis/server/session/session.settings.jinja @@ -63,6 +63,9 @@ {{ number_setting(form.turnMax) }} {{ form.articleIndexList.label }}:
{{ form.articleIndexList(class_="fullwidth", rows=10) }} + {% for error in form.articleIndexList.errors %} + {{ error }}
+ {% endfor %} {{ number_setting(form.articleIndexCapacity) }}

diff --git a/amanuensis/server/session/settings.py b/amanuensis/server/session/settings.py index 7d3c960..51d9853 100644 --- a/amanuensis/server/session/settings.py +++ b/amanuensis/server/session/settings.py @@ -1,3 +1,4 @@ +import re from typing import cast from flask import current_app @@ -8,7 +9,8 @@ from wtforms import ( BooleanField, TextAreaField, IntegerField, - SelectField) + SelectField, + ValidationError) from wtforms.validators import DataRequired, Optional from wtforms.widgets.html5 import NumberInput @@ -17,6 +19,12 @@ from amanuensis.models import ModelFactory, UserModel from amanuensis.server.forms import User +index_regex = re.compile( + r'(char|prefix|etc)' # index type + r'(\[(-?\d+)\])?' # index pri + r':(.+)') # index pattern + + class SettingTranslator(): """ Base class for the translation layer between internal config data @@ -46,6 +54,32 @@ class UsernameTranslator(SettingTranslator): return user.uid +class IndexListTranslator(SettingTranslator): + """ + Converts internal index representations into the index + specification format used in the editable list. + """ + def load(self, cfg_value): + index_list = [] + for index in cfg_value: + if index.pri == 0: + index_list.append('{type}:{pattern}'.format(**index)) + else: + index_list.append('{type}[{pri}]:{pattern}'.format(**index)) + return '\n'.join(index_list) + + def save(self, field_data): + index_list = [] + for index in field_data.split('\n'): + match = index_regex.fullmatch(index) + itype, _, pri, pattern = match.groups() + index_list.append(dict( + type=itype, + pri=pri or 0, + pattern=pattern.strip())) + return index_list + + class Setting(): """ Represents a relation between a node in a lexicon config and a @@ -84,6 +118,14 @@ class Setting(): cfg[self.cfg_path[-1]] = self.translator.save(data) +def IndexList(form, field): + if not field.data: + raise ValidationError('You must specify an index list.') + for index in field.data.split('\n'): + if not index_regex.fullmatch(index): + raise ValidationError(f'Bad index: "{index}"') + + class Settings(): @staticmethod def settings(): @@ -166,7 +208,10 @@ class Settings(): 'Block turn publish if any articles are awaiting editor review')) s_articleIndexList = Setting('article.index.list', - TextAreaField('Index specifications')) + TextAreaField( + 'Index specifications', + validators=[IndexList]), + translator=IndexListTranslator()) s_articleIndexCapacity = Setting('article.index.capacity', IntegerField(