core: contest team (#1183)

This commit is contained in:
Baoshuo authored and GitHub committed 2026-09-16 01:05:44 +08:00
1 parent 238b1263bf
commit 78e898fdfc
22 files changed
+934 -96

No files matched your search

@@ -44,12 +44,61 @@
{% if not (tsdoc.attend) and not model.contest.isDone(tdoc) %}
<li class="menu__item">
{% if handler.user.hasPerm(perm.PERM_ATTEND_CONTEST) and handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
<form action="{{ url('contest_detail', tid=tdoc.docId) }}" method="POST">
{% set team_vdocs = team_vdocs|default([]) %}
<form action="{{ url('contest_detail', tid=tdoc.docId) }}" method="POST" data-contest-attend-form{% if tdoc.allowTeam or tdoc._code %} data-contest-needs-dialog{% endif %}>
<input type="hidden" name="operation" value="attend">
<button class="menu__link" {% if tdoc._code %}data-contest-code{% endif %} type="submit">
<button class="menu__link" data-contest-attend type="submit">
<span class="icon icon-add"></span> {{ _('Attend Contest') }}
</button>
</form>
<div style="display:none" class="dialog__body--contest-attend">
<div>
<div class="row"><div class="columns">
<h1>{{ _('Attend Contest') }}</h1>
<p class="supplementary contest-attend-dialog__desc">{{ _('Choose how you want to participate in this contest.') }}</p>
</div></div>
<input type="hidden" name="contest_attend_mode" value="personal">
<div class="contest-attend-dialog__modes">
<button type="button" class="primary rounded button" data-contest-attend-mode="personal" aria-pressed="true">
<span class="icon icon-user"></span> {{ _('Personal Participation') }}
</button>
<button type="button" class="rounded button{% if not tdoc.allowTeam %} disabled{% endif %}" data-contest-attend-mode="team" aria-pressed="false"{% if teamDisabled %} disabled{% endif %}>
<span class="icon icon-user--multiple"></span> {{ _('Team Participation') }}
</button>
</div>
{% if not tdoc.allowTeam %}
<p class="supplementary contest-attend-dialog__hint">{{ _('Team participation is not allowed for this contest.') }}</p>
{% elif not team_vdocs.length %}
<p class="supplementary contest-attend-dialog__hint">
{{ _('You are not in any team.') }}
<a class="typo-a" href="{{ url('contest_team') }}">{{ _('Manage Teams') }}</a>
</p>
{% endif %}
{% if team_vdocs.length %}
<div class="row contest-attend-dialog__team-select"><div class="columns">
<label>
{{ _('Team') }}
<select class="select" name="contest_attend_vuid" disabled>
{% for v in team_vdocs %}
<option value="{{ v._id }}">{{ v.displayName }} (ID {{ v._id }})</option>
{% endfor %}
</select>
</label>
</div></div>
<p class="supplementary contest-attend-dialog__hint">
<a class="typo-a" href="{{ url('contest_team') }}">{{ _('Manage Teams') }}</a>
</p>
{% endif %}
{% if tdoc._code %}
<div class="row"><div class="columns">
<label class="material textbox">
{{ _('Invitation code') }}
<input name="contest_attend_code" type="text" data-autofocus>
</label>
</div></div>
{% endif %}
</div>
</div>
{% elif not handler.user.hasPriv(PRIV.PRIV_USER_PROFILE) %}
<a class="menu__link" href="javascript:showSignInDialog()">
<span class="icon icon-add"></span> {{ _('Login to Attend Contest') }}
@@ -4,7 +4,22 @@
{%- for tsdoc in tsdocs -%}
<tr data-uid="{{ tsdoc.uid }}">
<td class="col--uid">{{ tsdoc.uid }}</td>
<td class="col--user">{{ user.render_inline(udict[tsdoc.uid], badge=false) }}</td>
<td class="col--user">
{{ user.render_inline(udict[tsdoc.uid], badge=false) }}
{% if tsdoc.displayName or (tsdoc.members and tsdoc.members.length) %}
<br><small class="supplementary">
{% if tsdoc.members and tsdoc.members.length %}
{{ _('Team') }}: {{ tsdoc.displayName }} —
{% for uid in tsdoc.members %}
{%- if not loop.first -%}, {% endif -%}
{{ user.render_inline(udict[uid], avatar=false, badge=false) }}
{%- endfor -%}
{% else %}
{{ tsdoc.displayName }}
{% endif %}
</small>
{% endif %}
</td>
<td class="col--start-time">{{ contest.render_time(tsdoc.startAt or tdoc.beginAt) }}</td>
<td class="col--end-time">{{ contest.render_time(tsdoc.endAt or tdoc.endAt) }}</td>
<td class="col--rank">{{ _('UnRank') if tsdoc.unrank else _('Rank') }}</td>
@@ -49,12 +49,25 @@
{%- if column.type == 'rank' -%}
<span class="{{ 'rank--unrank' if column.value == '0' else 'rank--normal' }}">{{ '*' if column.value == '0' else column.value|string|nl2br|safe }}</span>
{%- elif column.type == 'user' -%}
{%- set canView = canViewAll or handler.user._id == column.raw -%}
{%- set canView = canViewAll or handler.user._id == column.raw or (handler.team and handler.team == column.raw) -%}
<button class="star user--{{ column.raw }}" data-uid="{{ column.raw }}">
<span class="starred--hide"><span class="icon icon-star--outline" data-tooltip="{{ _('Star') }}"></span></span>
<span class="starred--show"><span class="icon icon-star" data-tooltip="{{ _('Unstar') }}"></span></span>
</button>
{{ user.render_inline(udict[column.raw], badge=false) }}
{%- if udict[column.raw].teamMembers -%}
<span class="user-profile-link">
<span class="icon icon-user--multiple"></span>
<span class="user-profile-name">{{ udict[column.raw].displayName }}</span>
</span>
<br><small class="supplementary">
{%- for memberUid in udict[column.raw].teamMembers -%}
{%- if loop.index0 -%}, {% endif -%}
{{ user.render_inline(udict[memberUid], avatar=false, badge=false) }}
{%- endfor -%}
</small>
{%- else -%}
{{ user.render_inline(udict[column.raw], badge=false) }}
{%- endif -%}
{%- elif column.type == 'record' and column.raw -%}
{{ renderRecord(column, canView) }}
{%- elif column.type == 'records' -%}
@@ -76,4 +89,4 @@
</tbody>
</table>
</div>
</div>
</div>