Skip to content

Commit

Permalink
Improve workflow for print/vet status tracking + public view page
Browse files Browse the repository at this point in the history
- Add usercontest status: sealed
- Modify translation workflow to include sealing for onsite-teams
- Add public view page for all team translation status (optimized for broadcasting on zoom/projector)
- Add auto-refresh for users.html and users_public.html

Co-authored-by: Ashar Fuadi <[email protected]>
  • Loading branch information
sijie123 and fushar committed Sep 4, 2022
1 parent 0420ae2 commit cd070b2
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 11 deletions.
2 changes: 2 additions & 0 deletions trans/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class Meta:
'user',
'contest',
'frozen',
'sealed',
'note',
'extra_country_1_code',
'extra_country_2_code',
Expand All @@ -96,6 +97,7 @@ class UserContestAdmin(ImportExportModelAdmin):
'user',
'contest',
'frozen',
'sealed',
'note',
'extra_country_1_code',
'extra_country_2_code',
Expand Down
20 changes: 20 additions & 0 deletions trans/migrations/0023_auto_20220730_1917.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.29 on 2022-07-30 12:17
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('trans', '0022_remove_user_online'),
]

operations = [
migrations.AddField(
model_name='usercontest',
name='sealed',
field=models.BooleanField(default=False),
),
]
1 change: 1 addition & 0 deletions trans/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ class UserContest(models.Model):
user = models.ForeignKey('User')
contest = models.ForeignKey('Contest', default=None)
frozen = models.BooleanField(default=False)
sealed = models.BooleanField(default=False)
note = models.TextField(default='')
extra_country_1_code = models.CharField(max_length=6, blank=True)
extra_country_2_code = models.CharField(max_length=6, blank=True)
Expand Down
5 changes: 5 additions & 0 deletions trans/templates/autorefresh.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
window.setTimeout( function() {
window.location.reload();
}, 30000);
</script>
3 changes: 3 additions & 0 deletions trans/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ user.username }} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#"></a></li>
{% if user.is_staff %}
<li><a href="{% url 'public_users_list' public='public' %}">Public View</a></li>
{% endif %}
{% if not user.is_staff %}
<li><a href="{% url 'settings'%}">Font Settings</a></li>
<li role="separator" class="divider"></li>
Expand Down
10 changes: 8 additions & 2 deletions trans/templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,14 @@ <h4> Your team is not translating.</h4>
{% endif %}

{% if has_contestants %}
<div class="alert alert-warning">
<p>We are preparing your contestant envelopes. <b>Please wait for a runner to approach your desk to verify the envelopes.</b></p>
{% if contest.user_contest.sealed %}
<div class="alert alert-success">
<p><b>All set!</b> You have verified and sealed your contestant envelopes.<br>
If this is an error, please look for a staff member immediately.</p>
{% else %}
<div class="alert alert-info">
<p><b>We are preparing your contestant envelopes.</b> Please wait for a runner to approach your desk to verify and seal the envelopes.</p>
{% endif %}

{% with extra_country_1_code=contest.user_contest.extra_country_1_code %}
{% with extra_country_1_count=contest.user_contest.extra_country_1_count %}
Expand Down
23 changes: 21 additions & 2 deletions trans/templates/user.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,32 @@ <h3>This contest has been frozen for this user</h3>
<b>Note:</b>
{{contest.user_contest.note}}
{% endif %}
<form class="form-inline" method="post" onsubmit="return confirm('Are you sure to unfreeze?');"
action="{% url 'unfreeze_user_contest' username=user_name contest_id=contest.id%}">
<form class="form-inline" method="post" onsubmit="return confirm('Are you sure to unfreeze? Once unfrozen, existing prints for the team should be considered old and discarded.');"
action="{% url 'unfreeze_user_contest' username=user_name contest_id=contest.id%}">
{% csrf_token %}
<button type="submit" class="btn btn-default btn-danger ">
Unfreeze
</button>
</form>

{% if has_contestants %}
<!-- only applicable if team has contestants. Otherwise, it's only a matter of freezing / unfreezing, no print/sign needed. -->
{% if not contest.user_contest.sealed %}
<!-- not yet contest.user_contest.sealed, so prompt staff to collect, prepare envelopes and bring to TL for checking -->
<h3>Please inform Team Leader to verify and seal the contestant envelopes</h3>
<form class="form-inline" method="post" onsubmit="return confirm('Are you sure to mark as sealed? This cannot be undone.');"
action="{% url 'seal_user_contest' username=user_name contest_id=contest.id%}">
{% csrf_token %}
<button type="submit" class="btn btn-default btn-info">
Mark as sealed
</button>
</form>
{% else %}
<!-- Print has been printed, verified and sealed -->
<h3>All set. Contestant envelopes have been verified and sealed.</h3>
{% endif %}
{% endif %}

{% else %}
<form class="form-inline" method="post" action="{% url 'freeze_user_contest' username=user_name contest_id=contest.id%}">
{% csrf_token %}
Expand Down
63 changes: 58 additions & 5 deletions trans/templates/users.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,64 @@ <h2>{{ contest.title }}</h2>
</td>
<td>
{% with user_contest=user_contests|get_dict:user.username|get_dict:contest.id %}
{% if not user.has_contestants and not user.is_translating %}
<span style="color: green"><b>Done</b></span>
{% elif user_contest is not None and user_contest.frozen %}
<span style="color: green"><b>Done</b></span>
{% if not user.has_contestants %}
<!-- Team is fully remote -->
{% if not user.is_translating or user_contest is not none and user_contest.frozen %}
<!-- If team is not translating, or has finished translation -->
<span style="color: green">
<b>
<i class="fa fa-file-pdf-o fa-lg"></i>
Done (PDF Only)
</b>
</span>
{% else %}
<span>
<i class="fa fa-pencil fa-lg"></i>
In Progress
</span>
{% endif %}

{% else %}
In progress
<!-- Team has some on-site contestants. Workflow:
1A. (If translating) Submit own country translations + request other countries translations = "freeze"
1B. (If not translating) Request other countries translations = "freeze"
2. HTC collects printed translations and brings to TL for checking and sealing into envelope
-->
{% if user_contest is none or not user_contest.frozen %}
<!-- Team is at step (1): haven't frozen -->
{% if user.is_translating %}
<!-- 1A: supposed to translate but not yet done -->
<span>
<i class="fa fa-pencil fa-lg"></i>
In Progress
</span>
{% else %}
<!-- 1B: awaiting request other countries translations -->
<span>
<i class="fa fa-list fa-lg"></i>
Choosing Copies
</span>
{% endif %}
{% elif not user_contest.sealed %}
<!-- Team is at step (2): awaiting TL seal -->
<span style="color: orange">
<b>
<i class="fa fa-user fa-lg"></i>
Pending TL Seal
</b>
</span>
{% else %}
<!-- Done: At this point, should be printed and sealed -->
<span style="color: green">
<b>
<i class="fa fa-envelope fa-lg"></i>
Done (Sealed)
</b>
</span>
{% endif %}

{% endif %}

{% endwith %}

{% with user_contest=user_contests|get_dict:user.username|get_dict:contest.id %}
Expand Down Expand Up @@ -123,4 +174,6 @@ <h2>{{ contest.title }}</h2>
</div>
</div>

{% include "autorefresh.html" %}

{% endblock %}
110 changes: 110 additions & 0 deletions trans/templates/users_public.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{% extends "base.html" %}

{% load dict_filter %}

{% block title %} Home {% endblock %}

{% block content %}

<div class="container-fluid">
<div class="col-md-12 col-lg-12 row">
{% for contest in contests %}
{% for userpart in users_public %}
<div class="col-md-3 col-lg-3">
<h2>{{ contest.title }}</h2>
<table class="table table-hover">
<thead>
<tr>
<th>User</th>
<th style="text-align: left;">Country (On-site Pax)</td>
<th>Status</th>
</tr>
</thead>

<tbody>
{% for user in userpart|dictsort:"username" %}
<tr>
<td><a href="{% url 'user_trans' username=user.username %}">{{ user.username }}</a></td>
<td style="text-align: left;">
{{ user.country_name }}
{% if user.has_contestants %}
({{ user.num_of_contestants }})
{% else %}
(-)
{% endif %}
</td>
<td>
{% with user_contest=user_contests|get_dict:user.username|get_dict:contest.id %}
{% if not user.has_contestants %}
<!-- Team is fully remote -->
{% if not user.is_translating or user_contest is not none and user_contest.frozen %}
<!-- If team is not translating, or has finished translation -->
<span style="color: green">
<b>
<i class="fa fa-file-pdf-o fa-lg"></i>
Done (PDF Only)
</b>
</span>
{% else %}
<span>
<i class="fa fa-pencil fa-lg"></i>
In Progress
</span>
{% endif %}

{% else %}
<!-- Team has some on-site contestants. Workflow:
1A. (If translating) Submit own country translations + request other countries translations = "freeze"
1B. (If not translating) Request other countries translations = "freeze"
2. HTC collects printed translations and brings to TL for checking and sealing into envelope
-->
{% if user_contest is none or not user_contest.frozen %}
<!-- Team is at step (1): haven't frozen -->
{% if user.is_translating %}
<!-- 1A: supposed to translate but not yet done -->
<span>
<i class="fa fa-pencil fa-lg"></i>
In Progress
</span>
{% else %}
<!-- 1B: awaiting request other countries translations -->
<span>
<i class="fa fa-list fa-lg"></i>
Choosing Copies
</span>
{% endif %}
{% elif not user_contest.sealed %}
<!-- Team is at step (2): awaiting TL seal -->
<span style="color: orange">
<b>
<i class="fa fa-user fa-lg"></i>
Pending TL Seal
</b>
</span>
{% else %}
<!-- Done: At this point, should be printed and sealed -->
<span style="color: green">
<b>
<i class="fa fa-envelope fa-lg"></i>
Done (Sealed)
</b>
</span>
{% endif %}

{% endif %}

{% endwith %}
</tr>
{% endfor %}
</tbody>

</table>
</div>
{% endfor %}
{% endfor %}
</div>
</div>

{% include "autorefresh.html" %}

{% endblock %}
3 changes: 3 additions & 0 deletions trans/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
url(r'^revert/$', Revert.as_view(), name='revert'),

url(r'^users/$', UsersList.as_view(), name='users_list'),
url(r'^users/(?P<public>[\w]*)/$', UsersList.as_view(), name='public_users_list'),
url(r'^user/(?P<username>[\w-]*)/$', UserTranslations.as_view(), name='user_trans'),
url(r'^upload_final_pdf/$', AddFinalPDF.as_view(), name='upload_final_pdf'),
url(r'^user_freeze_trans/(?P<task_name>[\w]*)/$', UserFreezeTranslation.as_view(), name='user_freeze_trans'),
Expand All @@ -46,6 +47,8 @@
name='freeze_user_contest'),
url(r'^unfreeze_user_contest/(?P<username>[\w-]*)/(?P<contest_id>[\w]*)/$',
UnfreezeUserContest.as_view(), name='unfreeze_user_contest'),
url(r'^seal_user_contest/(?P<username>[\w-]*)/(?P<contest_id>[\w]*)/$',
SealUserContest.as_view(), name='seal_user_contest'),
url(r'^unleash_edit_token/(?P<id>[\w]*)/$', UnleashEditTranslationToken.as_view(),
name='unleash_edit_token'),

Expand Down
25 changes: 23 additions & 2 deletions trans/views/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def get(self, request, username):
form = UploadFileForm()
return render(request, 'user.html', context={
'user_name': username,
'has_contestants': user.has_contestants,
'country': user.country.name,
'is_editor': user.is_editor,
'tasks_lists': tasks_lists,
Expand Down Expand Up @@ -194,6 +195,7 @@ def _fetch_translations(self, usernames):
user_contests[user.username][contest.id] = {
'frozen': user_contest.frozen,
'note': user_contest.note,
'sealed': user_contest.sealed,
'extra_country_1_code': user_contest.extra_country_1_code,
'extra_country_1_count': user_contest.extra_country_1_count,
'extra_country_2_code': user_contest.extra_country_2_code,
Expand All @@ -202,13 +204,19 @@ def _fetch_translations(self, usernames):

return (contests, contest_tasks, user_translations, user_contests)

def get(self, request):
def _chunks(self, xs, n):
return (xs[i:len(xs):n] for i in range(n))

def get(self, request, public=False):
users = self._fetch_users()
(contests, contest_tasks, user_translations, user_contests) = \
self._fetch_translations([user['username'] for user in users])

return render(request, 'users.html', context={
render_page = 'users_public.html' if public else 'users.html'
users_public = self._chunks(sorted(users, key=lambda u: u['username']), 4)
return render(request, render_page, context={
'users': users,
'users_public': users_public,
'contests': contests,
'contest_tasks': contest_tasks,
'user_translations': user_translations,
Expand Down Expand Up @@ -321,6 +329,7 @@ def post(self, request, username, contest_id):

user_contest, created = UserContest.objects.get_or_create(contest=contest, user=user)
user_contest.frozen = True
user_contest.sealed = False
user_contest.extra_country_1_code = extra_country_1_code
user_contest.extra_country_2_code = extra_country_2_code
user_contest.extra_country_1_count = extra_country_1_count
Expand Down Expand Up @@ -358,6 +367,18 @@ def post(self, request, username, contest_id):
# return redirect(to=reverse('user_trans', kwargs={'username': username}))
return redirect(request.META.get('HTTP_REFERER'))

class SealUserContest(LoginRequiredMixin, View):
def post(self, request, username, contest_id):
user = User.objects.get(username=username)
contest = Contest.objects.filter(id=contest_id).first()
if contest is None:
return HttpResponseNotFound("There is no contest")
user_contest = UserContest.objects.filter(contest=contest, user=user).first()
if user_contest is not None:
user_contest.sealed = True
user_contest.save()
return redirect(request.META.get('HTTP_REFERER'))

class UnleashEditTranslationToken(StaffCheckMixin, View):
def post(self, request, id):
trans = Translation.objects.get(id=id)
Expand Down

0 comments on commit cd070b2

Please sign in to comment.