コード例 #1
0
 def clean_level(self):
     """ Remove extra whitespace from the level, strip if not WS. """
     program = self.cleaned_data.get('program')
     program_enum = enums.Program(program) if program else None
     if program_enum and not program_enum.winter_rules_apply():
         return None
     return self.cleaned_data.get('level', '').strip()
コード例 #2
0
    def get(self, context, **response_kwargs):
        try:
            program_enum = enums.Program(self.kwargs['program'])
        except ValueError:
            return JsonResponse({}, status=404)

        return JsonResponse({
            'leaders':
            sorted(self.describe_leaders(program_enum),
                   key=lambda par: par['name'])
        })
コード例 #3
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['is_currently_iap'] = is_currently_iap()

        # There is separate logic for determining if we allow choosing the WS program.
        # Rather than duplicate that logic here, just see if it's a selectable choice.
        form: forms.TripForm = context['form']
        context['can_select_ws_program'] = any(
            enums.Program(value) == enums.Program.WINTER_SCHOOL
            for category, choices in form.fields['program'].choices
            for value, label in choices)
        return context
コード例 #4
0
    def __init__(self, *args, **kwargs):
        allowed_programs = kwargs.pop("allowed_programs", None)
        super().__init__(*args, **kwargs)
        trip = self.instance

        if trip.pk is None:  # New trips must have *all* dates/times in the future
            now = local_now()
            # (the `datetime-local` inputs don't take timezones at all)
            # We specify only to the minutes' place so that we don't display seconds
            naive_iso_now = now.replace(tzinfo=None).isoformat(
                timespec='minutes')

            self.fields['trip_date'].widget.attrs['min'] = now.date(
            ).isoformat()
            # There is *extra* dynamic logic that (open < close at <= trip date)
            # However, we can at minimum enforce that times occur in the future
            self.fields['signups_open_at'].widget.attrs['min'] = naive_iso_now
            self.fields['signups_close_at'].widget.attrs['min'] = naive_iso_now

        # Use the participant queryset to cover an edge case:
        # editing an old trip where one of the leaders is no longer a leader!
        self.fields[
            'leaders'].queryset = models.Participant.objects.get_queryset()
        self.fields['leaders'].help_text = None  # Disable "Hold command..."

        # We'll dynamically hide the level widget on GET if it's not a winter trip
        # On POST, we only want this field required for winter trips
        program = self.data.get('program')
        program_enum = enums.Program(program) if program else None
        self.fields['level'].required = (program_enum
                                         and program_enum.winter_rules_apply())

        initial_program: Optional[
            enums.Program] = trip.pk and trip.program_enum

        if allowed_programs is not None:
            self.fields['program'].choices = list(
                self._allowed_program_choices(allowed_programs))

            # If it's currently WS, the WS program is almost certainly what's desired for new trips.
            if (enums.Program.WINTER_SCHOOL in allowed_programs
                    and is_currently_iap() and not trip.pk):
                initial_program = enums.Program.WINTER_SCHOOL

        self._init_wimp()

        # (No need for `ng-init`, we have a custom directive)
        self.fields['leaders'].widget.attrs['data-ng-model'] = 'leaders'

        _bind_input(self,
                    'program',
                    initial=initial_program and initial_program.value)
        _bind_input(self, 'algorithm', initial=trip and trip.algorithm)
コード例 #5
0
    def _allowed_program_choices(self, allowed_program_enums):
        # If editing an existing trip, the old program can persist.
        if self.instance and self.instance.program_enum not in allowed_program_enums:
            allowed_program_enums = [
                self.instance.program_enum, *allowed_program_enums
            ]

        for category, choices in enums.Program.choices():
            assert isinstance(category, str) and isinstance(choices, list)
            valid_choices = [(value, label) for (value, label) in choices
                             if enums.Program(value) in allowed_program_enums]
            if valid_choices:
                yield (category, valid_choices)
コード例 #6
0
    def __init__(self, *args, **kwargs):
        allowed_programs = kwargs.pop("allowed_programs", None)
        super().__init__(*args, **kwargs)
        # Use the participant queryset to cover an edge case:
        # editing an old trip where one of the leaders is no longer a leader!
        self.fields[
            'leaders'].queryset = models.Participant.objects.get_queryset()
        self.fields['leaders'].help_text = None  # Disable "Hold command..."

        # We'll dynamically hide the level widget on GET if it's not a winter trip
        # On POST, we only want this field required for winter trips
        program = self.data.get('program')
        program_enum = enums.Program(program) if program else None
        self.fields['level'].required = (program_enum
                                         and program_enum.winter_rules_apply())

        if allowed_programs is not None:
            self.fields['program'].choices = list(
                self._allowed_program_choices(allowed_programs))

        self._init_wimp()
コード例 #7
0
    def clean(self):
        """ Ensure that all leaders can lead the trip. """
        super().clean()

        if 'program' not in self.cleaned_data or 'leaders' not in self.cleaned_data:
            return self.cleaned_data
        leaders = self.cleaned_data['leaders']
        program_enum = enums.Program(self.cleaned_data['program'])

        # To allow editing old trips with lapsed leaders, only check new additions
        trip = self.instance
        if trip.pk:
            leaders = leaders.exclude(pk__in=trip.leaders.all())

        lacking_privs = [
            par for par in leaders if not par.can_lead(program_enum)
        ]

        if lacking_privs:
            names = ', '.join(leader.name for leader in lacking_privs)
            self.add_error('leaders',
                           f"{names} can't lead {program_enum.label} trips")
        return self.cleaned_data