Fix group contest m2m fields (authors, curators, etc)
This commit is contained in:
parent
93d032fc72
commit
27586b25b8
6 changed files with 271 additions and 260 deletions
|
@ -11,7 +11,6 @@ from django.contrib.auth.models import User
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
from django.core.exceptions import ValidationError, ObjectDoesNotExist
|
from django.core.exceptions import ValidationError, ObjectDoesNotExist
|
||||||
from django.core.validators import RegexValidator
|
from django.core.validators import RegexValidator
|
||||||
from django.db import transaction
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.forms import (
|
from django.forms import (
|
||||||
CharField,
|
CharField,
|
||||||
|
@ -52,7 +51,6 @@ from judge.widgets import (
|
||||||
DateTimePickerWidget,
|
DateTimePickerWidget,
|
||||||
ImageWidget,
|
ImageWidget,
|
||||||
)
|
)
|
||||||
from judge.tasks import rescore_contest
|
|
||||||
|
|
||||||
|
|
||||||
def fix_unicode(string, unsafe=tuple("\u202a\u202b\u202d\u202e")):
|
def fix_unicode(string, unsafe=tuple("\u202a\u202b\u202d\u202e")):
|
||||||
|
@ -282,16 +280,9 @@ class EditOrganizationContestForm(ModelForm):
|
||||||
"view_contest_scoreboard",
|
"view_contest_scoreboard",
|
||||||
]:
|
]:
|
||||||
self.fields[field].widget.data_url = (
|
self.fields[field].widget.data_url = (
|
||||||
self.fields[field].widget.get_url() + "?org_id=1"
|
self.fields[field].widget.get_url() + f"?org_id={self.org_id}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def save(self, commit=True):
|
|
||||||
res = super(EditOrganizationContestForm, self).save(commit=False)
|
|
||||||
if commit:
|
|
||||||
res.save()
|
|
||||||
transaction.on_commit(rescore_contest.s(res.key).delay)
|
|
||||||
return res
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Contest
|
model = Contest
|
||||||
fields = (
|
fields = (
|
||||||
|
|
|
@ -99,11 +99,13 @@ class Contest(models.Model, PageVotable, Bookmarkable):
|
||||||
)
|
)
|
||||||
authors = models.ManyToManyField(
|
authors = models.ManyToManyField(
|
||||||
Profile,
|
Profile,
|
||||||
|
verbose_name=_("authors"),
|
||||||
help_text=_("These users will be able to edit the contest."),
|
help_text=_("These users will be able to edit the contest."),
|
||||||
related_name="authors+",
|
related_name="authors+",
|
||||||
)
|
)
|
||||||
curators = models.ManyToManyField(
|
curators = models.ManyToManyField(
|
||||||
Profile,
|
Profile,
|
||||||
|
verbose_name=_("curators"),
|
||||||
help_text=_(
|
help_text=_(
|
||||||
"These users will be able to edit the contest, "
|
"These users will be able to edit the contest, "
|
||||||
"but will not be listed as authors."
|
"but will not be listed as authors."
|
||||||
|
@ -113,6 +115,7 @@ class Contest(models.Model, PageVotable, Bookmarkable):
|
||||||
)
|
)
|
||||||
testers = models.ManyToManyField(
|
testers = models.ManyToManyField(
|
||||||
Profile,
|
Profile,
|
||||||
|
verbose_name=_("testers"),
|
||||||
help_text=_(
|
help_text=_(
|
||||||
"These users will be able to view the contest, " "but not edit it."
|
"These users will be able to view the contest, " "but not edit it."
|
||||||
),
|
),
|
||||||
|
|
|
@ -419,7 +419,14 @@ class ContestDetail(
|
||||||
return []
|
return []
|
||||||
res = []
|
res = []
|
||||||
for organization in self.object.organizations.all():
|
for organization in self.object.organizations.all():
|
||||||
|
can_edit = False
|
||||||
if self.request.profile.can_edit_organization(organization):
|
if self.request.profile.can_edit_organization(organization):
|
||||||
|
can_edit = True
|
||||||
|
if self.request.profile in organization and self.object.is_editable_by(
|
||||||
|
self.request.user
|
||||||
|
):
|
||||||
|
can_edit = True
|
||||||
|
if can_edit:
|
||||||
res.append(organization)
|
res.append(organization)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@ from judge.views.problem import ProblemList
|
||||||
from judge.views.contests import ContestList
|
from judge.views.contests import ContestList
|
||||||
from judge.views.submission import AllSubmissions, SubmissionsListBase
|
from judge.views.submission import AllSubmissions, SubmissionsListBase
|
||||||
from judge.views.feed import FeedView
|
from judge.views.feed import FeedView
|
||||||
|
from judge.tasks import rescore_contest
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"OrganizationList",
|
"OrganizationList",
|
||||||
|
@ -394,7 +395,7 @@ class OrganizationContestMixin(
|
||||||
model = Contest
|
model = Contest
|
||||||
|
|
||||||
def is_contest_editable(self, request, contest):
|
def is_contest_editable(self, request, contest):
|
||||||
return request.profile in contest.authors.all() or self.can_edit_organization(
|
return contest.is_editable_by(request.user) or self.can_edit_organization(
|
||||||
self.organization
|
self.organization
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -947,7 +948,7 @@ class EditOrganizationContest(
|
||||||
|
|
||||||
def get_content_title(self):
|
def get_content_title(self):
|
||||||
href = reverse("contest_view", args=[self.contest.key])
|
href = reverse("contest_view", args=[self.contest.key])
|
||||||
return mark_safe(f'Edit <a href="{href}">{self.contest.key}</a>')
|
return mark_safe(_("Edit") + f' <a href="{href}">{self.contest.key}</a>')
|
||||||
|
|
||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self.contest
|
return self.contest
|
||||||
|
@ -960,6 +961,19 @@ class EditOrganizationContest(
|
||||||
self.object.organizations.add(self.organization)
|
self.object.organizations.add(self.organization)
|
||||||
self.object.is_organization_private = True
|
self.object.is_organization_private = True
|
||||||
self.object.save()
|
self.object.save()
|
||||||
|
|
||||||
|
if any(
|
||||||
|
f in form.changed_data
|
||||||
|
for f in (
|
||||||
|
"start_time",
|
||||||
|
"end_time",
|
||||||
|
"time_limit",
|
||||||
|
"format_config",
|
||||||
|
"format_name",
|
||||||
|
"freeze_after",
|
||||||
|
)
|
||||||
|
):
|
||||||
|
transaction.on_commit(rescore_contest.s(self.object.key).delay)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def get_problem_formset(self, post=False):
|
def get_problem_formset(self, post=False):
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,12 +29,6 @@
|
||||||
height: 2em;
|
height: 2em;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
}
|
}
|
||||||
@media(min-width: 800px) {
|
|
||||||
#content {
|
|
||||||
width: 99%;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media(max-width: 799px) {
|
@media(max-width: 799px) {
|
||||||
#content {
|
#content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
Loading…
Reference in a new issue