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):
|
class IndexDefinitionForm(FlaskForm):
|
||||||
"""/lexicon/<name>/settings/index/"""
|
"""/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])
|
TYPE_CHOICES = ([("", "")] + [(str(t), str(t).lower()) for t in IndexType])
|
||||||
|
|
||||||
index_type = SelectField(choices=TYPE_CHOICES, coerce=parse_index_type)
|
index_type = SelectField(choices=TYPE_CHOICES, coerce=parse_index_type)
|
||||||
|
|
|
@ -105,6 +105,7 @@
|
||||||
<th>Cap</th>
|
<th>Cap</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for index_form in form.indices %}
|
{% for index_form in form.indices %}
|
||||||
|
{{ index_form.hidden_tag() }}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ index_form.index_type() }}</td>
|
<td>{{ index_form.index_type() }}</td>
|
||||||
<td>{{ index_form.pattern() }}</td>
|
<td>{{ index_form.pattern() }}</td>
|
||||||
|
|
|
@ -45,21 +45,47 @@
|
||||||
|
|
||||||
<h3>General</h3>
|
<h3>General</h3>
|
||||||
<p>
|
<p>
|
||||||
|
{{ form.title.label }}:<br>
|
||||||
|
{{ form.title(autocomplete="off", size=32, style="width:100%") }}<br>
|
||||||
{{ form.editor.label }}: {{ form.editor(autocomplete="off") }}<br>
|
{{ form.editor.label }}: {{ form.editor(autocomplete="off") }}<br>
|
||||||
{% for error in form.editor.errors %}
|
{% for error in form.editor.errors %}
|
||||||
<span style="color: #ff0000">{{ error }}</span><br>
|
<span style="color: #ff0000">{{ error }}</span><br>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{{ form.prompt.label }}: {{ form.prompt(class_="fullwidth") }}
|
||||||
|
{% for error in form.prompt.errors %}
|
||||||
|
<span style="color: #ff0000">{{ error }}</span><br>
|
||||||
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Game Progress</h3>
|
<h3>Game Progress</h3>
|
||||||
<p>
|
<p>
|
||||||
{{ number_setting(form.turnCurrent) }}
|
{{ 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.label }}:<br>
|
||||||
{{ form.turnAssignment(class_="fullwidth", rows=10) }}
|
{{ form.turnAssignment(class_="fullwidth", rows=10) }}
|
||||||
</p>
|
</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>
|
<h3>Turn Publishing</h3>
|
||||||
<p>
|
<p>
|
||||||
|
{{ flag_setting(form.publishNotifyEditorOnReady) }}
|
||||||
|
{{ flag_setting(form.publishNotifyPlayerOnReject) }}
|
||||||
|
{{ flag_setting(form.publishNotifyPlayerOnAccept) }}
|
||||||
{{ form.publishDeadlines(autocomplete="off") }}
|
{{ form.publishDeadlines(autocomplete="off") }}
|
||||||
{{ form.publishDeadlines.label }}<br>
|
{{ form.publishDeadlines.label }}<br>
|
||||||
{{ flag_setting(form.publishAsap) }}
|
{{ flag_setting(form.publishAsap) }}
|
||||||
|
|
|
@ -158,20 +158,65 @@ class Settings():
|
||||||
if name.startswith('s_'):
|
if name.startswith('s_'):
|
||||||
yield name, setting
|
yield name, setting
|
||||||
|
|
||||||
|
s_title = Setting('title',
|
||||||
|
StringField('Title override', validators=[Optional()]))
|
||||||
|
|
||||||
s_editor = Setting('editor',
|
s_editor = Setting('editor',
|
||||||
SelectField('Editor', validators=[DataRequired(), User(True)]),
|
SelectField('Editor', validators=[DataRequired(), User(True)]),
|
||||||
translator=UsernameTranslator())
|
translator=UsernameTranslator())
|
||||||
|
|
||||||
|
s_prompt = Setting('prompt',
|
||||||
|
TextAreaField('Prompt', validators=[DataRequired()]))
|
||||||
|
|
||||||
s_turnCurrent = Setting('turn.current',
|
s_turnCurrent = Setting('turn.current',
|
||||||
IntegerField(
|
IntegerField(
|
||||||
'Current turn',
|
'Current turn',
|
||||||
widget=NumberInput(),
|
widget=NumberInput(),
|
||||||
validators=[Optional()]))
|
validators=[Optional()]))
|
||||||
|
|
||||||
|
s_turnMax = Setting('turn.max',
|
||||||
|
IntegerField(
|
||||||
|
'Number of turns',
|
||||||
|
widget=NumberInput(),
|
||||||
|
validators=[DataRequired()]))
|
||||||
|
|
||||||
s_turnAssignment = Setting('turn.assignment',
|
s_turnAssignment = Setting('turn.assignment',
|
||||||
TextAreaField('index assignment raw'),
|
TextAreaField('index assignment raw'),
|
||||||
translator=TmpAsgnTranslator())
|
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',
|
s_publishDeadlines = Setting('publish.deadlines',
|
||||||
StringField(
|
StringField(
|
||||||
'Turn deadline, as a crontab specification',
|
'Turn deadline, as a crontab specification',
|
||||||
|
@ -191,6 +236,18 @@ class Settings():
|
||||||
BooleanField(
|
BooleanField(
|
||||||
'Block turn publish if any articles are awaiting editor review'))
|
'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',
|
s_articleCitationAllowSelf = Setting('article.citation.allow_self',
|
||||||
BooleanField('Allow players to cite themselves'))
|
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()}"
|
username: str = f"user_{os.urandom(8).hex()}"
|
||||||
charname: str = f"char_{os.urandom(8).hex()}"
|
charname: str = f"char_{os.urandom(8).hex()}"
|
||||||
char_sig: str = f"signature_{os.urandom(8).hex()}"
|
char_sig: str = f"signature_{os.urandom(8).hex()}"
|
||||||
|
# ub: bytes = username.encode("utf8")
|
||||||
|
|
||||||
with app.test_client() as client:
|
with app.test_client() as client:
|
||||||
# Create the user and log in
|
# Create the user and log in
|
||||||
|
@ -62,6 +63,7 @@ def test_character_view(db: DbContext, app: Flask, make: ObjectFactory):
|
||||||
created_redirect,
|
created_redirect,
|
||||||
data={"name": charname, "signature": char_sig, "csrf_token": csrf_token},
|
data={"name": charname, "signature": char_sig, "csrf_token": csrf_token},
|
||||||
)
|
)
|
||||||
|
print(response.data.decode("utf8"))
|
||||||
assert 300 <= response.status_code <= 399
|
assert 300 <= response.status_code <= 399
|
||||||
|
|
||||||
# The character is updated
|
# 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