Add set scoreboard view

This commit is contained in:
cuom1999 2020-12-27 19:59:57 -06:00
parent 8e1e3b246a
commit b3d80b5100
6 changed files with 34 additions and 1 deletions

View file

@ -86,6 +86,7 @@ class ContestForm(ModelForm):
else: else:
self.fields['rate_exclude'].queryset = Profile.objects.none() self.fields['rate_exclude'].queryset = Profile.objects.none()
self.fields['banned_users'].widget.can_add_related = False self.fields['banned_users'].widget.can_add_related = False
self.fields['view_contest_scoreboard'].widget.can_add_related = False
def clean(self): def clean(self):
cleaned_data = super(ContestForm, self).clean() cleaned_data = super(ContestForm, self).clean()
@ -100,6 +101,8 @@ class ContestForm(ModelForm):
'tags': AdminSelect2MultipleWidget, 'tags': AdminSelect2MultipleWidget,
'banned_users': AdminHeavySelect2MultipleWidget(data_view='profile_select2', 'banned_users': AdminHeavySelect2MultipleWidget(data_view='profile_select2',
attrs={'style': 'width: 100%'}), attrs={'style': 'width: 100%'}),
'view_contest_scoreboard': AdminHeavySelect2MultipleWidget(data_view='profile_select2',
attrs={'style': 'width: 100%'}),
} }
if HeavyPreviewAdminPageDownWidget is not None: if HeavyPreviewAdminPageDownWidget is not None:
@ -116,7 +119,7 @@ class ContestAdmin(VersionAdmin):
(_('Format'), {'fields': ('format_name', 'format_config')}), (_('Format'), {'fields': ('format_name', 'format_config')}),
(_('Rating'), {'fields': ('is_rated', 'rate_all', 'rating_floor', 'rating_ceiling', 'rate_exclude')}), (_('Rating'), {'fields': ('is_rated', 'rate_all', 'rating_floor', 'rating_ceiling', 'rate_exclude')}),
(_('Access'), {'fields': ('access_code', 'is_private', 'private_contestants', 'is_organization_private', (_('Access'), {'fields': ('access_code', 'is_private', 'private_contestants', 'is_organization_private',
'organizations')}), 'organizations', 'view_contest_scoreboard')}),
(_('Justice'), {'fields': ('banned_users',)}), (_('Justice'), {'fields': ('banned_users',)}),
) )
list_display = ('key', 'name', 'is_visible', 'is_rated', 'start_time', 'end_time', 'time_limit', 'user_count') list_display = ('key', 'name', 'is_visible', 'is_rated', 'start_time', 'end_time', 'time_limit', 'user_count')

View file

@ -0,0 +1,18 @@
# Generated by Django 2.2.17 on 2020-12-28 01:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('judge', '0111_contest_decimal_points'),
]
operations = [
migrations.AddField(
model_name='contest',
name='view_contest_scoreboard',
field=models.ManyToManyField(blank=True, help_text='These users will be able to view the scoreboard.', related_name='view_contest_scoreboard', to='judge.Profile', verbose_name='view contest scoreboard'),
),
]

View file

@ -68,6 +68,9 @@ class Contest(models.Model):
help_text=_('Whether the scoreboard should remain hidden for the duration ' help_text=_('Whether the scoreboard should remain hidden for the duration '
'of the contest.'), 'of the contest.'),
default=False) default=False)
view_contest_scoreboard = models.ManyToManyField(Profile, verbose_name=_('view contest scoreboard'), blank=True,
related_name='view_contest_scoreboard',
help_text=_('These users will be able to view the scoreboard.'))
use_clarifications = models.BooleanField(verbose_name=_('no comments'), use_clarifications = models.BooleanField(verbose_name=_('no comments'),
help_text=_("Use clarification system instead of comments."), help_text=_("Use clarification system instead of comments."),
default=True) default=True)
@ -142,6 +145,8 @@ class Contest(models.Model):
return True return True
if user.is_authenticated and self.organizers.filter(id=user.profile.id).exists(): if user.is_authenticated and self.organizers.filter(id=user.profile.id).exists():
return True return True
if user.is_authenticated and self.view_contest_scoreboard.filter(id=user.profile.id).exists():
return True
if not self.is_visible: if not self.is_visible:
return False return False
if self.start_time is not None and self.start_time > timezone.now(): if self.start_time is not None and self.start_time > timezone.now():
@ -212,6 +217,8 @@ class Contest(models.Model):
# User is in the group of private contestants # User is in the group of private contestants
if self.private_contestants.filter(id=user.profile.id).exists(): if self.private_contestants.filter(id=user.profile.id).exists():
return True return True
if self.view_contest_scoreboard.filter(id=user.profile.id).exists():
return True
# If the user can view all contests # If the user can view all contests
if user.has_perm('judge.see_private_contest'): if user.has_perm('judge.see_private_contest'):

View file

@ -80,6 +80,7 @@ class PostList(ListView):
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
q |= Q(is_organization_private=True, organizations__in=user.organizations.all()) q |= Q(is_organization_private=True, organizations__in=user.organizations.all())
q |= Q(is_private=True, private_contestants=user) q |= Q(is_private=True, private_contestants=user)
q |= Q(view_contest_scoreboard=user)
visible_contests = visible_contests.filter(q) visible_contests = visible_contests.filter(q)
context['current_contests'] = visible_contests.filter(start_time__lte=now, end_time__gt=now).distinct() context['current_contests'] = visible_contests.filter(start_time__lte=now, end_time__gt=now).distinct()
context['future_contests'] = visible_contests.filter(start_time__gt=now).distinct() context['future_contests'] = visible_contests.filter(start_time__gt=now).distinct()

View file

@ -70,6 +70,7 @@ class ContestListMixin(object):
if self.request.user.is_authenticated: if self.request.user.is_authenticated:
q |= Q(is_organization_private=True, organizations__in=self.request.profile.organizations.all()) q |= Q(is_organization_private=True, organizations__in=self.request.profile.organizations.all())
q |= Q(is_private=True, private_contestants=self.request.profile) q |= Q(is_private=True, private_contestants=self.request.profile)
q |= Q(view_contest_scoreboard=self.request.profile)
queryset = queryset.filter(q) queryset = queryset.filter(q)
return queryset.distinct() return queryset.distinct()
@ -254,6 +255,7 @@ class ContestClone(ContestMixin, PermissionRequiredMixin, TitleMixin, SingleObje
tags = contest.tags.all() tags = contest.tags.all()
organizations = contest.organizations.all() organizations = contest.organizations.all()
private_contestants = contest.private_contestants.all() private_contestants = contest.private_contestants.all()
view_contest_scoreboard = contest.view_contest_scoreboard.all()
contest_problems = contest.contest_problems.all() contest_problems = contest.contest_problems.all()
contest.pk = None contest.pk = None
@ -265,6 +267,7 @@ class ContestClone(ContestMixin, PermissionRequiredMixin, TitleMixin, SingleObje
contest.tags.set(tags) contest.tags.set(tags)
contest.organizations.set(organizations) contest.organizations.set(organizations)
contest.private_contestants.set(private_contestants) contest.private_contestants.set(private_contestants)
contest.view_contest_scoreboard.set(view_contest_scoreboard)
contest.organizers.add(self.request.profile) contest.organizers.add(self.request.profile)
for problem in contest_problems: for problem in contest_problems:

View file

@ -74,6 +74,7 @@ class ContestSelect2View(Select2View):
q |= Q(is_organization_private=True, q |= Q(is_organization_private=True,
organizations__in=self.request.profile.organizations.all()) organizations__in=self.request.profile.organizations.all())
q |= Q(is_private=True, private_contestants=self.request.profile) q |= Q(is_private=True, private_contestants=self.request.profile)
q |= Q(view_contest_scoreboard=self.request.profile)
queryset = queryset.filter(q) queryset = queryset.filter(q)
return queryset return queryset