Compare commits
No commits in common. "5e202a83cee75785d74a55d1ddde1461e1b712af" and "87531dc8e611c6f985e76b06b600e2c5dfd23d61" have entirely different histories.
5e202a83ce
...
87531dc8e6
|
@ -59,11 +59,6 @@ def parse_index_type(type_str):
|
|||
class IndexDefinitionForm(FlaskForm):
|
||||
"""/lexicon/<name>/settings/index/"""
|
||||
|
||||
class Meta:
|
||||
# Disable CSRF on the individual index definitions, since the schema
|
||||
# form will have one
|
||||
csrf = False
|
||||
|
||||
TYPE_CHOICES = ([("", "")] + [(str(t), str(t).lower()) for t in IndexType])
|
||||
|
||||
index_type = SelectField(choices=TYPE_CHOICES, coerce=parse_index_type)
|
||||
|
|
|
@ -105,6 +105,7 @@
|
|||
<th>Cap</th>
|
||||
</tr>
|
||||
{% for index_form in form.indices %}
|
||||
{{ index_form.hidden_tag() }}
|
||||
<tr>
|
||||
<td>{{ index_form.index_type() }}</td>
|
||||
<td>{{ index_form.pattern() }}</td>
|
||||
|
|
|
@ -45,21 +45,47 @@
|
|||
|
||||
<h3>General</h3>
|
||||
<p>
|
||||
{{ form.title.label }}:<br>
|
||||
{{ form.title(autocomplete="off", size=32, style="width:100%") }}<br>
|
||||
{{ form.editor.label }}: {{ form.editor(autocomplete="off") }}<br>
|
||||
{% for error in form.editor.errors %}
|
||||
<span style="color: #ff0000">{{ error }}</span><br>
|
||||
{% endfor %}
|
||||
{{ form.prompt.label }}: {{ form.prompt(class_="fullwidth") }}
|
||||
{% for error in form.prompt.errors %}
|
||||
<span style="color: #ff0000">{{ error }}</span><br>
|
||||
{% endfor %}
|
||||
</p>
|
||||
|
||||
<h3>Game Progress</h3>
|
||||
<p>
|
||||
{{ number_setting(form.turnCurrent) }}
|
||||
{{ number_setting(form.turnMax) }}
|
||||
{{ form.articleIndexList.label }}:<br>
|
||||
{{ form.articleIndexList(class_="fullwidth", rows=10) }}
|
||||
{% for error in form.articleIndexList.errors %}
|
||||
<span style="color: #ff0000">{{ error }}</span><br>
|
||||
{% endfor %}
|
||||
{{ number_setting(form.articleIndexCapacity) }}
|
||||
{{ form.turnAssignment.label }}:<br>
|
||||
{{ form.turnAssignment(class_="fullwidth", rows=10) }}
|
||||
</p>
|
||||
|
||||
<h3>Visibility and Joining</h3>
|
||||
<p>
|
||||
{{ flag_setting(form.joinPublic) }}
|
||||
{{ flag_setting(form.joinOpen) }}
|
||||
{{ form.joinPassword(autocomplete="off") }}
|
||||
{{ form.joinPassword.label }}<br>
|
||||
{{ number_setting(form.joinMaxPlayers) }}
|
||||
{{ number_setting(form.joinCharsPerPlayer) }}
|
||||
</p>
|
||||
|
||||
<h3>Turn Publishing</h3>
|
||||
<p>
|
||||
{{ flag_setting(form.publishNotifyEditorOnReady) }}
|
||||
{{ flag_setting(form.publishNotifyPlayerOnReject) }}
|
||||
{{ flag_setting(form.publishNotifyPlayerOnAccept) }}
|
||||
{{ form.publishDeadlines(autocomplete="off") }}
|
||||
{{ form.publishDeadlines.label }}<br>
|
||||
{{ flag_setting(form.publishAsap) }}
|
||||
|
|
|
@ -158,20 +158,65 @@ class Settings():
|
|||
if name.startswith('s_'):
|
||||
yield name, setting
|
||||
|
||||
s_title = Setting('title',
|
||||
StringField('Title override', validators=[Optional()]))
|
||||
|
||||
s_editor = Setting('editor',
|
||||
SelectField('Editor', validators=[DataRequired(), User(True)]),
|
||||
translator=UsernameTranslator())
|
||||
|
||||
s_prompt = Setting('prompt',
|
||||
TextAreaField('Prompt', validators=[DataRequired()]))
|
||||
|
||||
s_turnCurrent = Setting('turn.current',
|
||||
IntegerField(
|
||||
'Current turn',
|
||||
widget=NumberInput(),
|
||||
validators=[Optional()]))
|
||||
|
||||
s_turnMax = Setting('turn.max',
|
||||
IntegerField(
|
||||
'Number of turns',
|
||||
widget=NumberInput(),
|
||||
validators=[DataRequired()]))
|
||||
|
||||
s_turnAssignment = Setting('turn.assignment',
|
||||
TextAreaField('index assignment raw'),
|
||||
translator=TmpAsgnTranslator())
|
||||
|
||||
s_joinPublic = Setting('join.public',
|
||||
BooleanField('Show game on public pages'))
|
||||
|
||||
s_joinOpen = Setting('join.open',
|
||||
BooleanField('Allow players to join game'))
|
||||
|
||||
s_joinPassword = Setting('join.password',
|
||||
StringField('Password to join game', validators=[Optional()]))
|
||||
|
||||
s_joinMaxPlayers = Setting('join.max_players',
|
||||
IntegerField(
|
||||
'Maximum number of players',
|
||||
widget=NumberInput(),
|
||||
validators=[DataRequired()]))
|
||||
|
||||
s_joinCharsPerPlayer = Setting('join.chars_per_player',
|
||||
IntegerField(
|
||||
'Characters per player',
|
||||
widget=NumberInput(),
|
||||
validators=[DataRequired()]))
|
||||
|
||||
s_publishNotifyEditorOnReady = Setting('publish.notify_editor_on_ready',
|
||||
BooleanField(
|
||||
'Notify the editor when a player marks an article as ready'))
|
||||
|
||||
s_publishNotifyPlayerOnReject = Setting('publish.notify_player_on_reject',
|
||||
BooleanField(
|
||||
'Notify a player when their article is rejected by the editor'))
|
||||
|
||||
s_publishNotifyPlayerOnAccept = Setting('publish.notify_player_on_accept',
|
||||
BooleanField(
|
||||
'Notify a player when their article is accepted by the editor'))
|
||||
|
||||
s_publishDeadlines = Setting('publish.deadlines',
|
||||
StringField(
|
||||
'Turn deadline, as a crontab specification',
|
||||
|
@ -191,6 +236,18 @@ class Settings():
|
|||
BooleanField(
|
||||
'Block turn publish if any articles are awaiting editor review'))
|
||||
|
||||
s_articleIndexList = Setting('article.index.list',
|
||||
TextAreaField(
|
||||
'Index specifications',
|
||||
validators=[IndexList]),
|
||||
translator=IndexListTranslator())
|
||||
|
||||
s_articleIndexCapacity = Setting('article.index.capacity',
|
||||
IntegerField(
|
||||
'Index capacity override',
|
||||
widget=NumberInput(),
|
||||
validators=[Optional()]))
|
||||
|
||||
s_articleCitationAllowSelf = Setting('article.citation.allow_self',
|
||||
BooleanField('Allow players to cite themselves'))
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ def test_character_view(db: DbContext, app: Flask, make: ObjectFactory):
|
|||
username: str = f"user_{os.urandom(8).hex()}"
|
||||
charname: str = f"char_{os.urandom(8).hex()}"
|
||||
char_sig: str = f"signature_{os.urandom(8).hex()}"
|
||||
# ub: bytes = username.encode("utf8")
|
||||
|
||||
with app.test_client() as client:
|
||||
# Create the user and log in
|
||||
|
@ -62,6 +63,7 @@ def test_character_view(db: DbContext, app: Flask, make: ObjectFactory):
|
|||
created_redirect,
|
||||
data={"name": charname, "signature": char_sig, "csrf_token": csrf_token},
|
||||
)
|
||||
print(response.data.decode("utf8"))
|
||||
assert 300 <= response.status_code <= 399
|
||||
|
||||
# The character is updated
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
from amanuensis.db.models import IndexType
|
||||
import os
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
from flask import Flask, url_for
|
||||
|
||||
from amanuensis.backend import memq, charq, indq
|
||||
from amanuensis.db import DbContext
|
||||
|
||||
from tests.conftest import ObjectFactory
|
||||
|
||||
|
||||
def test_index_view(db: DbContext, app: Flask, make: ObjectFactory):
|
||||
"""Test the lexicon index page"""
|
||||
|
||||
with app.test_client() as client:
|
||||
# Create the user and log in
|
||||
user = make.user()
|
||||
assert user
|
||||
user_client = make.client(user.id)
|
||||
assert client
|
||||
user_client.login(client)
|
||||
|
||||
# Create a lexicon and join as the editor
|
||||
lexicon = make.lexicon()
|
||||
assert lexicon
|
||||
mem = memq.create(db, user.id, lexicon.id, is_editor=True)
|
||||
assert mem
|
||||
|
||||
# The index settings page exists
|
||||
index_settings = url_for("lexicon.settings.index", lexicon_name=lexicon.name)
|
||||
response = client.get(index_settings)
|
||||
assert response.status_code == 200
|
||||
|
||||
# Add some indices
|
||||
i1 = indq.create(db, lexicon.id, IndexType.CHAR, "ABCDE", 0, 0, 0)
|
||||
assert i1
|
||||
p1 = i1.pattern
|
||||
assert p1
|
||||
i2 = indq.create(db, lexicon.id, IndexType.RANGE, "F-M", 0, 0, 0)
|
||||
assert i2
|
||||
p2 = i2.pattern
|
||||
assert p2
|
||||
i3 = indq.create(db, lexicon.id, IndexType.CHAR, "NOPQ", 0, 0, 0)
|
||||
assert i3
|
||||
p3 = i3.pattern
|
||||
assert p3
|
||||
db.session.commit()
|
||||
|
||||
# The index settings page shows the indices
|
||||
response = client.get(index_settings)
|
||||
assert response.status_code == 200
|
||||
# for i in indq.get_for_lexicon(db, lexicon.id):
|
||||
assert p1.encode("utf8") in response.data
|
||||
assert p2.encode("utf8") in response.data
|
||||
assert p3.encode("utf8") in response.data
|
||||
|
||||
# Indices can be modified
|
||||
soup = BeautifulSoup(response.data, features="html.parser")
|
||||
csrf_token = soup.find(id="csrf_token")["value"]
|
||||
assert csrf_token
|
||||
response = client.post(
|
||||
index_settings,
|
||||
data={
|
||||
"csrf_token": csrf_token,
|
||||
"indices-0-index_type": "CHAR",
|
||||
"indices-0-pattern": "ABCDEF",
|
||||
"indices-0-logical_order": 0,
|
||||
"indices-0-display_order": 0,
|
||||
"indices-0-capacity": "",
|
||||
"indices-1-index_type": "PREFIX",
|
||||
"indices-1-pattern": "F-M",
|
||||
"indices-1-logical_order": 1,
|
||||
"indices-1-display_order": -1,
|
||||
"indices-1-capacity": "",
|
||||
"indices-2-index_type": "",
|
||||
"indices-2-pattern": "NOPQ",
|
||||
"indices-2-logical_order": 0,
|
||||
"indices-2-display_order": 0,
|
||||
"indices-2-capacity": "",
|
||||
},
|
||||
)
|
||||
assert 300 <= response.status_code <= 399
|
||||
|
||||
updated_indices = list(indq.get_for_lexicon(db, lexicon.id))
|
||||
assert len(updated_indices) == 2
|
||||
assert updated_indices[0].index_type == IndexType.CHAR
|
||||
assert updated_indices[0].pattern == "ABCDEF"
|
||||
assert updated_indices[1].index_type == IndexType.PREFIX
|
||||
assert updated_indices[1].pattern == "F-M"
|
Loading…
Reference in New Issue