forms.py 7.32 KB
Newer Older
1
# Django Imports
2
from django import forms
3
from django.core.exceptions import ValidationError
4
from django.utils.safestring import mark_safe
Matthew Rodgers's avatar
Matthew Rodgers committed
5
from django.utils import timezone
6 7 8 9 10

# App Imports
from go.models import URL, RegisteredUser

# Other Imports
David Haynes's avatar
David Haynes committed
11
from crispy_forms.helper import FormHelper
12 13
from crispy_forms.layout import Layout, Fieldset, Submit, HTML, Div, Field
from crispy_forms.bootstrap import StrictButton, PrependedText, Accordion, AccordionGroup
14
from bootstrap3_datetime.widgets import DateTimePicker
15
from datetime import date, datetime, timedelta
16 17

class URLForm(forms.ModelForm):
18

19 20 21 22 23 24 25 26
    # Prevent redirect loop links
    def clean_target(self):
        target = self.cleaned_data.get('target')
        if self.host in target:
            raise ValidationError("You can't make a Go link to Go silly!")
        else:
            return target

27 28 29
    # Custom target URL field
    target = forms.URLField(
        required=True,
30
        label='Long URL (Required)',
31 32
        max_length=1000,
        widget=forms.URLInput(attrs={
33
            'placeholder': 'https://yoursite.com/'
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
        })
    )

    # Check to make sure the short url has not been used
    def unique_short(value):
        try:
            URL.objects.get(short__iexact=value)
        except URL.DoesNotExist:
            return
        raise ValidationError('Short url already exists.')

    # Custom short-url field with validators.
    short = forms.SlugField(
        required=False,
        label='Short URL (Optional)',
        widget=forms.TextInput(),
        validators=[unique_short],
        max_length=20,
        min_length=3,
    )

    DAY = '1 Day'
    WEEK = '1 Week'
    MONTH = '1 Month'
58
    CUSTOM = 'Custom Date'
59 60 61 62 63 64 65
    NEVER = 'Never'

    EXPIRATION_CHOICES = (
        (DAY, DAY),
        (WEEK, WEEK),
        (MONTH, MONTH),
        (NEVER, NEVER),
66
        (CUSTOM, CUSTOM),
67 68
    )

Matthew Rodgers's avatar
Matthew Rodgers committed
69
    # Add preset expiration choices.
70 71
    expires = forms.ChoiceField(
        required=True,
72
        label='Expiration (Required)',
73 74 75 76 77
        choices=EXPIRATION_CHOICES,
        initial=NEVER,
        widget=forms.RadioSelect(),
    )

Matthew Rodgers's avatar
Matthew Rodgers committed
78 79 80 81
    def valid_date(value):
        if value > timezone.now():
            return
        else:
82
            raise ValidationError('Date must be after today.')
Matthew Rodgers's avatar
Matthew Rodgers committed
83 84


Matthew Rodgers's avatar
Matthew Rodgers committed
85
    # Add a custom expiration choice.
86
    expires_custom = forms.DateTimeField(
Matthew Rodgers's avatar
Matthew Rodgers committed
87 88
        required = False,
        label='Custom Date',
89
        input_formats=['%m-%d-%Y'],
Matthew Rodgers's avatar
Matthew Rodgers committed
90
        validators=[valid_date],
91
        initial=lambda: datetime.now() + timedelta(days=1),
92 93 94 95 96 97 98
        widget=DateTimePicker(
            options={
                "format": "MM-DD-YYYY",
                "pickTime": False,
            },
            icon_attrs={
                "class": "fa fa-calendar",
Matthew Rodgers's avatar
Matthew Rodgers committed
99
            })
100 101
    )

102
    def __init__(self, *args, **kwargs):
103 104
        # Grab that host info
        self.host = kwargs.pop('host', None)
105
        super(URLForm, self).__init__(*args, **kwargs)
106
        # Define the basics for crispy-forms
107
        self.helper = FormHelper()
108
        self.helper.form_method = 'POST'
109

110
        # Some xtra vars for form css purposes
111 112 113 114
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-1'
        self.helper.field_class = 'col-md-6'

115
        # The main "layout" defined
116
        self.helper.layout = Layout(
117 118
            Fieldset('',
            #######################
119
                Accordion(
120
                    # Step 1: Long URL
121 122 123 124
                    AccordionGroup('Step 1: Long URL',
                        Div(
                            HTML("""
                                <h4>Paste the URL you would like to shorten:</h4>
125
                                <br />"""),
126
                            'target',
127
                            style="background: rgb(#F6F6F6);"),
128
                        active=True,
129 130 131
                        template='crispy/accordian-group.html'),

                    # Step 2: Short URL
132 133 134 135
                    AccordionGroup('Step 2: Short URL',
                        Div(
                            HTML("""
                                <h4>Create a custom Go address:</h4>
136 137
                                <br />"""),
                            PrependedText(
138
                            'short', 'https://go.gmu.edu/', template='crispy/customPrepended.html'),
139
                            style="background: rgb(#F6F6F6);"),
140
                        active=True,
141 142 143
                        template='crispy/accordian-group.html',),

                    # Step 3: Expiration
144 145 146 147
                    AccordionGroup('Step 3: URL Expiration',
                        Div(
                            HTML("""
                                <h4>Set when you would like your Go address to expire:</h4>
148
                                <br />"""),
149
                            'expires',
150
                            Field('expires_custom', template="crispy/customDateField.html"),
151
                            style="background: rgb(#F6F6F6);"),
152
                        active=True,
153
                        template='crispy/accordian-group.html'),
154

155 156 157 158 159 160
                    # FIN
                    template='crispy/accordian.html'),
            #######################
            HTML("""
                <br />"""),
            StrictButton('Shorten', css_class="btn btn-primary btn-md col-md-4", type='submit')))
161

162 163 164 165 166 167
    class Meta:
        model = URL
        fields = ('target',)
        exclude = ('owner', 'short', 'date_created', 'clicks', 'expires')


168
class SignupForm(forms.ModelForm):
169

170
    full_name = forms.CharField(
171
        required=True,
172
        label='Full Name (Required)',
173 174
        max_length=100,
        widget=forms.TextInput(attrs={
175 176
        }),
    )
177 178 179 180 181 182 183
    organization = forms.CharField(
        required=True,
        label='Organization (Required)',
        max_length=100,
        widget=forms.TextInput(attrs={
        })
    )
184
    description = forms.CharField(
185 186 187 188
        required=False,
        label='Description (Optional)',
        max_length=200,
        widget=forms.Textarea(attrs={
189 190
        }),
    )
191 192
    # A user becomes registered when they agree to the TOS
    registered = forms.BooleanField(
193
        required=True,
194 195
        # ***Need to replace lower url with production URL*** ie. go.gmu.edu/about#terms
        label = mark_safe('Do you accept the <a href="http://127.0.0.1:8000/about#terms">Terms of Service</a>?'),
196 197
    )

198 199 200 201
    def __init__(self, request, *args, **kwargs):
        # Necessary to call request in forms.py, is otherwise restricted to views.py and models.py
        self.request = request
        super(SignupForm, self).__init__(*args, **kwargs)
David Haynes's avatar
David Haynes committed
202
        self.helper = FormHelper()
203 204 205 206 207
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-4'
        self.helper.field_class = 'col-md-6'

        self.helper.layout = Layout(
208
            Fieldset('',
209
                Div(
210
                    # Place in form fields
211 212 213 214
                    Div(
                        'full_name',
                        'organization',
                        'description',
215
                        'registered',
216 217 218
                        css_class='well'),

                    # Extras at bottom
219
                    StrictButton('Submit',css_class='btn btn-primary btn-md col-md-4', type='submit'),
220
                    css_class='col-md-6')))
221 222
    class Meta:
        model = RegisteredUser
223 224
        fields = ('full_name', 'organization', 'description', 'registered',)
        exclude = ('user',)