Пример #1
0
class EditPageForm(MarkupContentMixin(field_name='markup_content'), EditPageFileForm):
    title = forms.CharField(max_length=60, widget=forms.TextInput(attrs={'size':50}))
    markup_content = MarkupContentField(label='Content', with_wysiwyg=True)
    comment = CommentField()

    def __init__(self, instance=None, *args, **kwargs):
        if instance:
            # push the initial values into the page object, to make MarkupContentMixin happy
            version = instance.current_version()
            instance.markup_content = version.wikitext
            instance.markup = version.markup()
            instance.math = version.math()
        super(EditPageForm, self).__init__(instance=instance, *args, **kwargs)

    @transaction.atomic
    def save(self, editor, *args, **kwargs):
        # create the PageVersion object: distribute the self.cleaned_data values appropriately
        wikitext = self.cleaned_data['markup_content']
        comment = self.cleaned_data['comment']
        title = self.cleaned_data['title']
        pv = PageVersion(title=title, wikitext=wikitext, comment=comment, editor=editor)
        pv.set_markup(self.cleaned_data['_markup'])
        pv.set_math(self.cleaned_data['_math'])

        self.instance.offering = self.offering
        pg = super(EditPageForm, self).save(*args, **kwargs)
        pv.page=self.instance
        pv.save()
        return pg
Пример #2
0
class AdvisorNoteForm(MarkupContentMixin(field_name='text'), forms.ModelForm):
    text = MarkupContentField(label="Content",
                              default_markup='plain',
                              allow_math=False,
                              restricted=False,
                              with_wysiwyg=True)
    email_student = forms.BooleanField(
        required=False,
        help_text="Should the student be emailed the contents of this note?")

    def __init__(self, student, *args, **kwargs):
        # Only needed for the clean_email_student below, so that we may check for an email and display a validation
        # error if needed.  The view handles sending the actual email afterwards.
        self.student = student
        super().__init__(*args, **kwargs)

    def clean_email_student(self):
        email = self.cleaned_data['email_student']
        if email and not self.student.email():
            raise ValidationError(
                "We don't have an email address for this student: cannot email them here."
            )
        return email

    class Meta:
        model = AdvisorNote
        exclude = ('hidden', 'emailed', 'created_at', 'config')
Пример #3
0
class _DiscussionTopicForm(MarkupContentMixin(field_name='content'), forms.ModelForm):
    title = forms.CharField(widget=TextInput(attrs={'size': 60}), help_text="What is this topic about?")
    content = MarkupContentField(label='Content', with_wysiwyg=True, restricted=True, rows=10)

    class Meta:
        model = DiscussionTopic
        exclude = ('offering', 'last_activity_at', 'created_at', 'message_count', 'author', 'config', 'status', 'pinned')
Пример #4
0
class DiscussionMessageForm(MarkupContentMixin(field_name='content'),
                            forms.ModelForm):
    content = MarkupContentField(label='Content',
                                 with_wysiwyg=True,
                                 restricted=True,
                                 rows=10)

    class Meta:
        model = DiscussionMessage
        exclude = ('topic', 'created_at', 'modified_at', 'status', 'author',
                   'config')
Пример #5
0
class MessageForm(MarkupContentMixin(), forms.ModelForm):
    content = MarkupContentField(rows=10,
                                 with_wysiwyg=False,
                                 default_markup='textile',
                                 allow_math=False,
                                 restricted=True)

    class Meta:
        model = NewsItem
        # these fields are decided from the request at the time the form is submitted
        exclude = [
            'user', 'author', 'published', 'updated', 'source_app', 'course',
            'read', 'config'
        ]
Пример #6
0
class AnnouncementForm(MarkupContentMixin(field_name='message'),
                       forms.ModelForm):
    message = MarkupContentField(default_markup='plain',
                                 allow_math=False,
                                 restricted=False,
                                 with_wysiwyg=True)

    class Meta:
        model = Announcement
        exclude = ('hidden', 'author', 'created_at', 'config')

    def __init__(self, units: Iterable[Unit], *args, **kwargs):
        super().__init__(*args, **kwargs)
        # force unit choice to be as specified:
        self.fields['unit'].queryset = Unit.objects.filter(
            id__in=(u.id for u in units))
        self.fields['unit'].empty_label = None
Пример #7
0
class QuizForm(MarkupContentMixin(field_name='intro'), QuizTimeBaseForm):
    grace = forms.IntegerField(required=True, min_value=0, max_value=3600, initial=300, label='Grace time',
                               help_text=mark_safe('Number of seconds after the “true” end of the quiz that '
                                                   'students may submit their answers (but not reload the quiz to continue working).'))
    honour_code = forms.BooleanField(required=False, initial=True, help_text="Require students to agree to the honour code before they can proceed with the quiz?")
    photo_verification = forms.BooleanField(required=False, initial=True, help_text="Require students to take a photo with their webcam when submitting the quiz?")
    intro = MarkupContentField(required=False, label='Introductory Text (displayed at the top of the quiz, optional)',
                               default_markup=DEFAULT_QUIZ_MARKUP, with_wysiwyg=True)
    review = forms.ChoiceField(required=True, label='Student Review', initial='none', choices=REVIEW_CHOICES, help_text="Allow students to review the quiz?")
    honour_code_text = MarkupContentField(required=False, label='Honour Code Text', initial=(HONOUR_CODE_DEFAULT, DEFAULT_QUIZ_MARKUP, False),
                               default_markup=DEFAULT_QUIZ_MARKUP, with_wysiwyg=True, allow_math=False)

    class Meta:
        model = Quiz
        fields = ['start', 'end']
        widgets = {}

    def __init__(self, activity: Activity, instance: Optional[Quiz] = None, *args, **kwargs):
        self.activity = activity
        super().__init__(instance=instance, *args, **kwargs)
        if instance:
            self.initial['grace'] = instance.grace
            self.initial['honour_code'] = instance.honour_code
            self.initial['photo_verification'] = instance.photos
            self.initial['review'] = instance.review
            self.initial['honour_code_text'] = instance.honour_code_text, instance.honour_code_markup, instance.honour_code_math

    def clean(self):
        cleaned_data = super().clean()
        # all Quiz instances must have the activity where we're editing
        self.instance.activity = self.activity
        self.instance.grace = cleaned_data['grace']
        self.instance.honour_code = cleaned_data['honour_code']
        self.instance.photos = cleaned_data['photo_verification']
        self.instance.review = cleaned_data['review']

        hc_text, hc_markup, hc_math = cleaned_data['honour_code_text']
        if self.instance.honour_code and not hc_text:
            self.add_error('honour_code_text', 'Must give text for honour code if that functionality is enabled.')
        self.instance.honour_code_text = hc_text
        self.instance.honour_code_markup = hc_markup
        self.instance.honour_code_math = hc_math
        return cleaned_data
Пример #8
0
class ReminderForm(MarkupContentMixin(), forms.ModelForm):
    content = MarkupContentField(allow_math=False, restricted=True)
    role_unit = forms.ChoiceField(label='Role', choices=[],
                                  required=False)  # choices filled by __init__

    def __init__(self, person, *args, **kwargs):
        self.person = person
        courses_set = Reminder.relevant_courses(person)
        courses = sorted(list(courses_set))
        course_choices = [(c.id, str(c)) for c in courses]
        role_unit_choices = [('%s %s' % (r.role, r.unit_id),
                              '%s(s) in %s' % (ROLES[r.role], r.unit.label))
                             for r in Role.objects_fresh.filter(person=person)]

        super().__init__(*args, **kwargs)

        # set initial for the role_unit field
        if 'role' in self.initial and self.initial[
                'role'] and 'unit' in self.initial and self.initial['unit']:
            self.initial['role_unit'] = '%s %i' % (self.initial['role'],
                                                   self.initial['unit'])
        else:
            self.initial['role_unit'] = None

        self.fields['course'].choices = [(None, '\u2014')] + course_choices
        # don't show nulls, or INST if user isn't an instructor of anything
        self.fields['reminder_type'].choices = [
            (k, v) for k, v in self.fields['reminder_type'].choices
            if k and (courses_set or k != 'INST')
        ]
        self.fields['date_type'].choices = [
            (k, v) for k, v in self.fields['date_type'].choices if k
        ]
        self.fields['role_unit'].choices = role_unit_choices

        # reorder fields... painfully.
        role_unit = self.fields['role_unit']
        new_order = OrderedDict()
        for n, f in self.fields.items():
            if n in ['role_unit', 'role', 'unit']:
                continue
            elif n == 'course':
                new_order['role_unit'] = role_unit
            new_order[n] = f

        self.fields = new_order

    class Meta:
        model = Reminder
        exclude = ['person', 'config', 'status']
        widgets = {
            'reminder_type': forms.RadioSelect,
            'date_type': forms.RadioSelect,
        }

    def clean_week(self):
        week = self.cleaned_data['week']
        if week is not None and week < 0:
            raise forms.ValidationError('Week number must be positive.')
        if week is not None and week > 16:
            raise forms.ValidationError('Week number can be no more than 16.')
        return week

    def require_null(self, cleaned_data, fields):
        """
        Make sure the field is null. Should only be an issue if the form is fiddled with: UI hides these fields.
        """
        for f in fields:
            cleaned_data[f] = None

    def require_non_null(self, cleaned_data, fields):
        """
        Make sure these situationally-required fields are non-null.
        """
        for f in fields:
            if f not in cleaned_data or not bool(cleaned_data[f]):
                self.add_error(f, 'This field is required.')

    def clean(self):
        cleaned_data = super().clean()

        # instructor reminders can only be semesterly
        if 'reminder_type' in cleaned_data and cleaned_data['reminder_type'] == 'INST' \
                and 'date_type' in cleaned_data and cleaned_data['date_type'] != 'SEM':
            self.add_error(
                'date_type',
                'Course-teaching reminders can only be semesterly.')

        # make sure the right fields are null/non-null for the various reminder_types and date_types
        if 'reminder_type' in cleaned_data:
            if cleaned_data['reminder_type'] == 'PERS':
                self.require_null(cleaned_data, ['role_unit', 'course'])
            elif cleaned_data['reminder_type'] == 'INST':
                self.require_null(cleaned_data, ['role_unit'])
                self.require_non_null(cleaned_data, ['course'])
            elif cleaned_data['reminder_type'] == 'ROLE':
                self.require_null(cleaned_data, ['course'])
                self.require_non_null(cleaned_data, ['role_unit'])
            else:
                raise forms.ValidationError('Unknown reminder type')

        if 'date_type' in cleaned_data:
            if cleaned_data['date_type'] == 'SEM':
                self.require_null(cleaned_data, ['month', 'day'])
                self.require_non_null(cleaned_data, ['week', 'weekday'])
            elif cleaned_data['date_type'] == 'YEAR':
                self.require_null(cleaned_data, ['week', 'weekday'])
                self.require_non_null(cleaned_data, ['month', 'day'])
            else:
                raise forms.ValidationError('Unknown date type')

        if 'role_unit' in cleaned_data and cleaned_data[
                'role_unit'] is not None:
            # fill role and unit from role_unit
            role_unit = cleaned_data['role_unit']
            role_name, unit_id = role_unit.split(' ')
            unit = Unit.objects.get(id=unit_id)
            cleaned_data['unit'] = unit
            cleaned_data['role'] = role_name
        else:
            cleaned_data['unit'] = None
            cleaned_data['role'] = None

        # make sure month/day forms a valid date
        if 'month' in cleaned_data and cleaned_data['month'] is not None \
                and 'day' in cleaned_data and cleaned_data['day'] is not None:
            try:
                # poor Feb 29, never getting the respect it deserves.
                datetime.date(year=2001,
                              month=int(cleaned_data['month']),
                              day=cleaned_data['day'])
            except ValueError:
                self.add_error('day', 'Not a valid day in that month.')

        return cleaned_data