Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • mj/mo-submit
1 result
Select Git revision
Show changes
Commits on Source (8)
......@@ -303,6 +303,9 @@ class User(Base):
def name_sort_key(self) -> Tuple[str, str]:
return (locale.strxfrm(self.last_name), locale.strxfrm(self.first_name))
def is_inactive(self) -> bool:
return self.password_hash is None
class Contest(Base):
__tablename__ = 'contests'
......
......@@ -13,6 +13,7 @@ import mo.util_format as util_format
from mo.web import app
from mo.web.org_contest import contest_breadcrumbs
from mo.web.org_place import place_breadcrumbs
from mo.web.util import user_html_flags
# Konfigurace Jinjy
......@@ -100,3 +101,7 @@ def json_pretty(js: Any) -> str:
@app.template_global()
def log_url(typ: str, id: int) -> str:
return url_for('org_log', typ=typ, id=id)
@app.template_filter()
def user_flags(u: db.User) -> Markup:
return user_html_flags(u)
......@@ -25,7 +25,7 @@ from mo.util_format import inflect_number, inflect_by_number
from mo.web import app
import mo.web.util
from mo.web.util import MODecimalField, PagerForm
from mo.web.table import CellCheckbox, Table, Row, Column, cell_pion_link, cell_place_link, cell_email_link
from mo.web.table import CellCheckbox, Table, Row, Column, cell_pion_link, cell_place_link, cell_email_link, cell_email_link_flags
import wtforms.validators as validators
from wtforms.widgets.html5 import NumberInput
......@@ -551,16 +551,13 @@ def make_contestant_table(query: Query, round: db.Round, add_checkbox: bool = Fa
html_attr = {
'class': 'state-' + pion.state.name
}
if u.is_test:
html_attr['class'] += ' testuser'
html_attr['title'] = 'Testovací uživatel'
rows.append(Row(
keys={
'sort_key': u.sort_key(),
'user_id': u.user_id,
'first_name': cell_pion_link(u, pion.contest_id, u.first_name),
'last_name': cell_pion_link(u, pion.contest_id, u.last_name),
'email': cell_email_link(u),
'email': cell_email_link_flags(u),
'school': pant.school_place.name,
'school_code': cell_place_link(pant.school_place, pant.school_place.get_code()),
'grade': pant.grade,
......
......@@ -11,6 +11,7 @@ import werkzeug.exceptions
from mo.csv import FileFormat
import mo.db as db
from mo.web import app
from mo.web.util import user_html_flags
@dataclass
......@@ -55,17 +56,19 @@ class Row:
class CellLink(Cell):
url: str
hint: Optional[str]
html_suffix: Markup
def __init__(self, text: str, url: str, hint: Optional[str] = None):
def __init__(self, text: str, url: str, hint: Optional[str] = None, html_suffix: Markup = Markup("")):
Cell.__init__(self, text)
self.url = url
self.hint = hint
self.html_suffix = html_suffix
def to_html(self) -> str:
a = '<td><a href="' + escape(self.url) + '"'
if self.hint:
a += ' title="' + escape(self.hint) + '"'
return a + '>' + escape(self.text) + '</a>'
return a + '>' + escape(self.text) + '</a>' + str(self.html_suffix)
class CellCheckbox(Cell):
......@@ -85,6 +88,20 @@ class CellCheckbox(Cell):
ch += ' checked'
return ch + '>'
class CellMarkup(Cell):
text: str
html: str
def __init__(self, text: str, html: Union[str, Markup]):
self.text = text
self.html = str(html)
def __str__(self) -> str:
return self.text
def to_html(self) -> str:
return self.html
class Table:
columns: Sequence[Column]
......@@ -184,6 +201,9 @@ class Table:
def cell_email_link(user: db.User) -> CellLink:
return CellLink(user.email, 'mailto:' + urllib.parse.quote(user.email, safe='@'))
def cell_email_link_flags(user: db.User) -> CellLink:
return CellLink(user.email, 'mailto:' + urllib.parse.quote(user.email, safe='@'), html_suffix=user_html_flags(user))
def cell_user_link(user: db.User, text: str) -> CellLink:
return CellLink(text, url_for('org_user', id=user.user_id))
......
......@@ -61,7 +61,7 @@ konkrétní úlohu. Symbol <span class="icon">🗐</span> značí, že existuje
</thead>
{% for pion in pions %}
{% set u = pion.user %}
<tr class="state-{{ pion.state.name }}{% if u.is_test %} testuser{% endif %}" {% if u.is_test %}title="Testovací uživatel"{% endif %}>
<tr class="state-{{ pion.state.name }}>
<th>{{ u|pion_link(contest.contest_id) }}
<td>{{ pion.state.friendly_name() }}
{% set sum_points = [] %}
......
......@@ -32,7 +32,7 @@
</thead>
<tr><td>Jméno:<td>{{ user.first_name }}
<tr><td>Příjmení:<td>{{ user.last_name }}
<tr><td>E-mail:<td>{{ user.email|mailto }}
<tr><td>E-mail:<td>{{ user.email|mailto }}{{ user|user_flags }}
<tr><td>Škola:<td><a href='{{ url_for('org_place', id=pant.school) }}'>{{ pant.school_place.name }}</a>
<tr><td>Třída:<td>{{ pant.grade }}
<tr><td>Rok narození:<td>{{ pant.birth_year }}
......
......@@ -51,7 +51,7 @@
{% for user in users %}
<tr>
<td>{{ user.first_name }}</td><td>{{ user.last_name }}</td>
<td>{{ user.email|mailto }}{% if user.password_hash == None %}<span class="user-inactive" title='Účet dosud nebyl aktivován'> *</span>{% endif %}</td>
<td>{{ user.email|mailto }}{{ user|user_flags }}</td>
<td>{% if user.is_admin %}správce{% elif user.roles|count == 0 %}<i>žádná role</i>{% else %}
<ul>
{% for role in user.roles %}
......
......@@ -9,7 +9,7 @@
{% set site_id = sc.site.place_id if sc.site else None %}
<table class="data">
<tr><th>Účastník<td>{{ sc.user|pion_link(sc.contest.contest_id) }}
<tr><th>Účastník<td>{{ sc.user|pion_link(sc.contest.contest_id) }}{{ sc.user|user_flags }}
<tr><th>Úloha<td><a href='{{ url_for('org_contest_task', contest_id=sc.contest.contest_id, site_id=site_id, task_id=sc.task.task_id) }}'>{{ sc.task.code }} {{ sc.task.name }}</a>
{% if solution %}
<tr><th>Body<td>
......
......@@ -73,9 +73,9 @@
</tr>
</thead>
{% for user in users %}
<tr{% if user.is_test %} class="testuser" title="Testovací uživatel"{% endif %}>
<tr>
<td>{{ user.first_name }}</td><td>{{ user.last_name }}</td>
<td>{{ user.email|mailto }}{% if user.password_hash == None %}<span class="user-inactive" title='Účet dosud nebyl aktivován'> *</span>{% endif %}</td>
<td>{{ user.email|mailto }}{{ user|user_flags }}</td>
<td>{% if user.participants|count == 0 %}<i>v žádném ročníku</i>{% else %}
<ul>
{% for participant in user.participants %}
......
......@@ -35,14 +35,14 @@ finální (ve výchozím stavu poslední nahrané).{% elif sc.allow_upload_solut
{% set u = for_user or obj.user %}
{% set task = for_task or obj %}
{% if for_task %}
<tr class="state-{{ obj.state.name }}{% if u.is_test %} testuser{% endif %}" {% if u.is_test %}title="Testovací uživatel"{% endif %}>
<tr class="state-{{ obj.state.name }}">
{% else %}
<tr>
{% endif %}
<td>{% if for_user %}
<a href='{{ url_for('org_contest_task', contest_id=ct_id, task_id=task.task_id) }}'>{{ task.code }} {{ task.name }}</a>
{% else %}
{{ u|pion_link(contest.contest_id) }}</a>
{{ u|pion_link(contest.contest_id) }}{{ u|user_flags }}</a>
{% endif %}
{% if for_task %}<td>{{ obj.state.friendly_name() }}{% endif %}
{% if sol %}
......
......@@ -9,6 +9,7 @@ import werkzeug.exceptions
import werkzeug.utils
import wtforms
from wtforms.fields.html5 import DecimalField
from markupsafe import Markup
import mo.db as db
import mo.jobs
......@@ -145,3 +146,13 @@ class MODecimalField(DecimalField):
d /= 10
return super(MODecimalField, self)._value()
def user_html_flags(u: db.User) -> Markup:
r = []
if u.is_test:
r.append("<span class='user-test' title='Testovací uživatel'>*</span>")
if u.is_inactive():
r.append("<span class='user-inactive' title='Účet dosud nebyl aktivován'>*</span>")
if len(r) == 0:
return Markup("")
return Markup(" " + "".join(r))
......@@ -114,16 +114,6 @@ table.data td.sol-warn {
background-color: #ffaaaa;
}
table tr.testuser {
opacity: 0.7;
background: repeating-linear-gradient(
45deg,
white,
white 10px,
#ddd 10px,
#ddd 20px
);
}
table tr.state-disqualified, table tr.state-disqualified a:not(.btn) {
color: red;
}
......@@ -256,6 +246,9 @@ table.data tbody tr.job-failed:hover {
/* Users */
.user-test {
color: green;
}
.user-inactive {
color: red;
}
......