Move download submissions to manage submissions page
This commit is contained in:
parent
aeed1814b3
commit
3ef47518ee
5 changed files with 77 additions and 59 deletions
|
@ -119,7 +119,6 @@ urlpatterns = [
|
|||
url(r'^/pdf$', problem.ProblemPdfView.as_view(), name='problem_pdf'),
|
||||
url(r'^/pdf/(?P<language>[a-z-]+)$', problem.ProblemPdfView.as_view(), name='problem_pdf'),
|
||||
url(r'^/clone', problem.ProblemClone.as_view(), name='problem_clone'),
|
||||
url(r'^/downloadAC$', problem.download_submissions, name='download_submissions'),
|
||||
url(r'^/submit$', problem.problem_submit, name='problem_submit'),
|
||||
url(r'^/resubmit/(?P<submission>\d+)$', problem.problem_submit, name='problem_submit'),
|
||||
|
||||
|
@ -139,8 +138,8 @@ urlpatterns = [
|
|||
|
||||
url(r'^/manage/submission', include([
|
||||
url('^$', problem_manage.ManageProblemSubmissionView.as_view(), name='problem_manage_submissions'),
|
||||
url('^/rejudge$', problem_manage.RejudgeSubmissionsView.as_view(), name='problem_submissions_rejudge'),
|
||||
url('^/rejudge/preview$', problem_manage.PreviewRejudgeSubmissionsView.as_view(),
|
||||
url('^/action$', problem_manage.ActionSubmissionsView.as_view(), name='problem_submissions_action'),
|
||||
url('^/action/preview$', problem_manage.PreviewActionSubmissionsView.as_view(),
|
||||
name='problem_submissions_rejudge_preview'),
|
||||
url('^/rejudge/success/(?P<task_id>[A-Za-z0-9-]*)$', problem_manage.rejudge_success,
|
||||
name='problem_submissions_rejudge_success'),
|
||||
|
|
|
@ -4,7 +4,6 @@ import shutil
|
|||
from datetime import timedelta
|
||||
from operator import itemgetter
|
||||
from random import randrange
|
||||
import zipfile, tempfile
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
@ -678,24 +677,3 @@ class ProblemClone(ProblemMixin, PermissionRequiredMixin, TitleMixin, SingleObje
|
|||
problem.types.set(types)
|
||||
|
||||
return HttpResponseRedirect(reverse('admin:judge_problem_change', args=(problem.id,)))
|
||||
|
||||
|
||||
def download_submissions(request, problem):
|
||||
if not request.user.is_superuser:
|
||||
raise Http404
|
||||
|
||||
submissions = Submission.objects.filter(problem__code=problem, result='AC')
|
||||
|
||||
with tempfile.SpooledTemporaryFile() as tmp:
|
||||
with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as archive:
|
||||
for submission in submissions:
|
||||
file_name = str(submission.id) + '.' + str(submission.language.key)
|
||||
archive.writestr(file_name, submission.source.source)
|
||||
|
||||
# Reset file pointer
|
||||
tmp.seek(0)
|
||||
|
||||
# Write file data to response
|
||||
response = HttpResponse(tmp.read(), content_type='application/x-zip-compressed')
|
||||
response['Content-Disposition'] = 'attachment; filename="%s"' % (str(problem) + '_submissions.zip')
|
||||
return response
|
|
@ -1,5 +1,7 @@
|
|||
from operator import itemgetter
|
||||
|
||||
import zipfile, tempfile
|
||||
|
||||
from celery.result import AsyncResult
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
|
@ -63,7 +65,7 @@ class ManageProblemSubmissionView(TitleMixin, ManageProblemSubmissionMixin, Deta
|
|||
return context
|
||||
|
||||
|
||||
class BaseRejudgeSubmissionsView(PermissionRequiredMixin, ManageProblemSubmissionActionMixin, BaseDetailView):
|
||||
class BaseActionSubmissionsView(PermissionRequiredMixin, ManageProblemSubmissionActionMixin, BaseDetailView):
|
||||
permission_required = 'judge.rejudge_submission_lot'
|
||||
|
||||
def perform_action(self):
|
||||
|
@ -88,16 +90,45 @@ class BaseRejudgeSubmissionsView(PermissionRequiredMixin, ManageProblemSubmissio
|
|||
raise NotImplementedError()
|
||||
|
||||
|
||||
class RejudgeSubmissionsView(BaseRejudgeSubmissionsView):
|
||||
def generate_response(self, id_range, languages, results):
|
||||
class ActionSubmissionsView(BaseActionSubmissionsView):
|
||||
def rejudge_response(self, id_range, languages, results):
|
||||
status = rejudge_problem_filter.delay(self.object.id, id_range, languages, results)
|
||||
return redirect_to_task_status(
|
||||
status, message=_('Rejudging selected submissions for %s...') % (self.object.name,),
|
||||
redirect=reverse('problem_submissions_rejudge_success', args=[self.object.code, status.id]),
|
||||
)
|
||||
|
||||
def download_response(self, id_range, languages, results):
|
||||
if not self.request.user.is_superuser:
|
||||
raise Http404
|
||||
|
||||
class PreviewRejudgeSubmissionsView(BaseRejudgeSubmissionsView):
|
||||
queryset = Submission.objects.filter(problem_id=self.object.id)
|
||||
submissions = apply_submission_filter(queryset, id_range, languages, results)
|
||||
|
||||
with tempfile.SpooledTemporaryFile() as tmp:
|
||||
with zipfile.ZipFile(tmp, 'w', zipfile.ZIP_DEFLATED) as archive:
|
||||
for submission in submissions:
|
||||
file_name = str(submission.id) + '_' + str(submission.user) + '.' + str(submission.language.key)
|
||||
archive.writestr(file_name, submission.source.source)
|
||||
|
||||
# Reset file pointer
|
||||
tmp.seek(0)
|
||||
|
||||
# Write file data to response
|
||||
response = HttpResponse(tmp.read(), content_type='application/x-zip-compressed')
|
||||
response['Content-Disposition'] = 'attachment; filename="%s"' % (str(self.object.code) + '_submissions.zip')
|
||||
return response
|
||||
|
||||
def generate_response(self, id_range, languages, results):
|
||||
action = self.request.POST.get('action')
|
||||
if (action == 'rejudge'):
|
||||
return self.rejudge_response(id_range, languages, results)
|
||||
elif (action == 'download'):
|
||||
return self.download_response(id_range, languages, results)
|
||||
else:
|
||||
return Http404()
|
||||
|
||||
class PreviewActionSubmissionsView(BaseActionSubmissionsView):
|
||||
def generate_response(self, id_range, languages, results):
|
||||
queryset = apply_submission_filter(self.object.submission_set.all(), id_range, languages, results)
|
||||
return HttpResponse(str(queryset.count()))
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
.pane {
|
||||
display: block;
|
||||
max-width: 20em;
|
||||
max-width: 25em;
|
||||
border: 1px #ccc solid;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
|
@ -70,7 +70,8 @@
|
|||
var $use_id = $('#by-range-check');
|
||||
var $id_start = $('#by-range-start');
|
||||
var $id_end = $('#by-range-end');
|
||||
$('#rejudge-selected').click(function (e) {
|
||||
|
||||
var actionClick = function (e) {
|
||||
e.preventDefault();
|
||||
if ($use_id.prop('checked')) {
|
||||
var start = parseInt($id_start.val());
|
||||
|
@ -84,24 +85,35 @@
|
|||
}
|
||||
}
|
||||
|
||||
var $form = $(this).parents('form');
|
||||
var $form = $('#form-action');
|
||||
var input = $("<input>")
|
||||
.attr("type", "hidden")
|
||||
.attr("name", "action").val(e.data.action);
|
||||
$form.append(input);
|
||||
|
||||
$.post('{{ url('problem_submissions_rejudge_preview', problem.code) }}', $form.serialize(), 'text')
|
||||
.done(function (count) {
|
||||
if (confirm("{{ _('You are about to rejudge {count} submissions. Are you sure you want to do this?') }}"
|
||||
.replace('{count}', count))) {
|
||||
if (confirm("{{ _('You are about to {action} {count} submissions. Are you sure you want to do this?') }}"
|
||||
.replace('{count}', count)
|
||||
.replace('{action}', e.data.action))) {
|
||||
$form.submit();
|
||||
}
|
||||
})
|
||||
.fail(function () {
|
||||
if (confirm("{{ _('You are about to rejudge a few submissions. Are you sure you want to do this?') }}")) {
|
||||
if (confirm("{{ _('You are about to {action} a few submissions. Are you sure you want to do this?') }}".replace('{action}', e.data.action))) {
|
||||
$form.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$('#rejudge-selected').on('click', {action: 'rejudge'}, actionClick);
|
||||
$('#download-selected').on('click', {action: 'download'}, actionClick);
|
||||
|
||||
|
||||
$use_id.change(function () {
|
||||
$('#by-range-filter').find('input').prop('disabled', !this.checked);
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -112,8 +124,8 @@
|
|||
<div class="panes">
|
||||
{% if request.user.has_perm('judge.rejudge_submission_lot') %}
|
||||
<div class="pane">
|
||||
<h3>{{ _('Rejudge Submissions') }}</h3>
|
||||
<form action="{{ url('problem_submissions_rejudge', problem.code) }}" method="post">
|
||||
<h3>{{ _('Filter submissions') }}</h3>
|
||||
<form action="{{ url('problem_submissions_action', problem.code) }}" method="post" id="form-action">
|
||||
{% csrf_token %}
|
||||
<div class="control-group">
|
||||
<label><input id="by-range-check" type="checkbox" name="use_range" value="on">
|
||||
|
@ -146,16 +158,19 @@
|
|||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="pane">
|
||||
<h3> {{ _('Action') }} </h3>
|
||||
<a id="rejudge-selected" class="unselectable button full" href="#">
|
||||
{{ _('Rejudge selected submissions') }}
|
||||
</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
</br>
|
||||
|
||||
<div class="pane">
|
||||
<h3>{{ _('Rescore Everything') }}</h3>
|
||||
<p id="rescore-warning">{{ _('This will rescore %(count)d submissions.', count=submission_count) }}</p>
|
||||
<a id="download-selected" class="unselectable button full" href="#">
|
||||
{{ _('Download selected submissions') }}
|
||||
</a>
|
||||
<br>
|
||||
<form action="{{ url('problem_submissions_rescore_all', problem.code) }}" method="post">
|
||||
{% csrf_token %}
|
||||
<a id="rescore-all" class="unselectable button full" href="#"
|
||||
|
@ -164,5 +179,6 @@
|
|||
</a>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -126,12 +126,6 @@
|
|||
{% endif %}
|
||||
<div><a href="{{ url('chronological_submissions', problem.code) }}">{{ _('All submissions') }}</a></div>
|
||||
<div><a href="{{ url('ranked_submissions', problem.code) }}">{{ _('Best submissions') }}</a></div>
|
||||
{% if request.user.is_superuser %}
|
||||
<div>
|
||||
<a href="{{ url('download_submissions', problem.code) }}"> {{ _('Download AC submissions') }} </a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if editorial and editorial.is_public and
|
||||
not (request.user.is_authenticated and request.profile.current_contest) %}
|
||||
<hr>
|
||||
|
|
Loading…
Reference in a new issue