forms.py 11.4 KB
Newer Older
1 2
"""
go/forms.py
3

4 5
Configure the layout and styling of the Go's forms.
"""
6
# Django Imports
7
from django.forms import (BooleanField, CharField, ChoiceField, DateTimeField,
David Haynes's avatar
David Haynes committed
8 9
                          ModelForm, RadioSelect, Textarea, TextInput,
                          URLField, URLInput)
10
from django.utils.safestring import mark_safe
11
from django.utils import timezone
12

13
# Third party imports
14 15 16
from crispy_forms.bootstrap import (Accordion, AccordionGroup, PrependedText,
                                    StrictButton)
from crispy_forms.helper import FormHelper
David Haynes's avatar
David Haynes committed
17
from crispy_forms.layout import HTML, Div, Field, Fieldset, Layout
18

19

20 21 22 23
# App Imports
from .models import URL, RegisteredUser
from .validators import regex_short_validator, valid_date

24
class URLForm(ModelForm):
25
    """
David Haynes's avatar
David Haynes committed
26
    The form that is used in URL creation.
David Haynes's avatar
David Haynes committed
27

28 29
    Define custom fields and then render them onto the template.
    """
30
    # destination -------------------------------------------------------------
31
    destination = URLField(
32
        required=True,
33
        label='Long URL (Required)',
34
        max_length=1000,
35
        widget=URLInput(attrs={
36
            'placeholder': 'https://yoursite.com/'
37 38 39
        })
    )

40
    # short -------------------------------------------------------------------
41
    short = CharField(
42 43
        required=False,
        label='Short URL (Optional)',
44
        widget=TextInput(),
45
        validators=[regex_short_validator],
46
        max_length=20,
47
        min_length=1,
48 49
    )

50
    # expires -----------------------------------------------------------------
51 52 53
    DAY = '1 Day'
    WEEK = '1 Week'
    MONTH = '1 Month'
54
    CUSTOM = 'Custom Date'
55 56
    NEVER = 'Never'

David Haynes's avatar
David Haynes committed
57
    # Define a tuple of string date standards to be used as our date choices
58 59 60 61 62
    EXPIRATION_CHOICES = (
        (DAY, DAY),
        (WEEK, WEEK),
        (MONTH, MONTH),
        (NEVER, NEVER),
63
        (CUSTOM, CUSTOM),
64 65
    )

66
    expires = ChoiceField(
67 68 69 70
        required=True,
        label='Expiration (Required)',
        choices=EXPIRATION_CHOICES,
        initial=NEVER,
71
        widget=RadioSelect(),
72 73
    )

74
    expires_custom = DateTimeField(
75 76 77 78
        required=False,
        label='Custom Date',
        input_formats=['%m-%d-%Y'],
        validators=[valid_date],
79
        initial=lambda: timezone.now() + timezone.timedelta(days=1)
80 81
    )

82
    def __init__(self, *args, **kwargs):
83 84
        # Grab that host info
        self.host = kwargs.pop('host', None)
85
        super(URLForm, self).__init__(*args, **kwargs)
86
        # Define the basics for crispy-forms
87
        self.helper = FormHelper()
88
        self.helper.form_method = 'POST'
89

90
        # Some extra vars for form css purposes
91 92 93 94
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-1'
        self.helper.field_class = 'col-md-6'

95
        # The main "layout" defined
96
        self.helper.layout = Layout(
97
            Fieldset('',
David Haynes's avatar
David Haynes committed
98 99 100 101 102 103
                     #######################
                     Accordion(
                         # Step 1: Long URL
                         AccordionGroup('Step 1: Long URL',
                                        Div(
                                            HTML("""
104
                                <h4>Paste the URL you would like to shorten:</h4>
105
                                <br />"""),
106
                                            'destination',
David Haynes's avatar
David Haynes committed
107 108 109 110 111 112 113 114
                                            style="background: rgb(#F6F6F6);"),
                                        active=True,
                                        template='crispy/accordian-group.html'),

                         # Step 2: Short URL
                         AccordionGroup('Step 2: Short URL',
                                        Div(
                                            HTML("""
115
                                <h4>Create a custom Go address:</h4>
116
                                <br />"""),
David Haynes's avatar
David Haynes committed
117 118 119 120 121 122 123 124 125 126
                                            PrependedText(
                                                'short', 'https://go.gmu.edu/', template='crispy/customPrepended.html'),
                                            style="background: rgb(#F6F6F6);"),
                                        active=True,
                                        template='crispy/accordian-group.html',),

                         # Step 3: Expiration
                         AccordionGroup('Step 3: URL Expiration',
                                        Div(
                                            HTML("""
127
                                <h4>Set when you would like your Go address to expire:</h4>
128
                                <br />"""),
David Haynes's avatar
David Haynes committed
129 130 131 132 133 134 135 136 137 138
                                            'expires',
                                            Field('expires_custom'),
                                            style="background: rgb(#F6F6F6);"),
                                        active=True,
                                        template='crispy/accordian-group.html'),

                         # FIN
                         template='crispy/accordian.html'),
                     #######################
                     HTML("""
139
                <br />"""),
David Haynes's avatar
David Haynes committed
140
                     StrictButton('Shorten', css_class="btn btn-primary btn-md col-md-4", type='submit')))
141

142
    class Meta:
David Haynes's avatar
David Haynes committed
143 144 145
        """
        Metadata about this ModelForm
        """
David Haynes's avatar
David Haynes committed
146
        # what model this form is for
147
        model = URL
David Haynes's avatar
David Haynes committed
148
        # what attributes are included
149
        fields = ['destination']
150

David Haynes's avatar
David Haynes committed
151

152
class EditForm(URLForm):
153 154
    """
    The form that is used in editing URLs.
155

156 157 158
    A modification of the URL creation form... now for editing URLs. Inherit
    custom form fields for DRY purposes.
    """
David Haynes's avatar
David Haynes committed
159

160 161
    def __init__(self, *args, **kwargs):
        """
162
        On initialization of the form, crispy forms renders this layout.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
        """
        # Grab that host info
        self.host = kwargs.pop('host', None)
        super(URLForm, self).__init__(*args, **kwargs)
        # Define the basics for crispy-forms
        self.helper = FormHelper()
        self.helper.form_method = 'POST'

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

        # The main "layout" defined
        self.helper.layout = Layout(
            Fieldset('',
David Haynes's avatar
David Haynes committed
179 180 181 182 183 184
                     #######################
                     Accordion(
                         # Step 1: Long URL
                         AccordionGroup('Step 1: Long URL',
                                        Div(
                                            HTML("""
185 186
                                <h4>Modify the URL you would like to shorten:</h4>
                                <br />"""),
187
                                            'destination',
David Haynes's avatar
David Haynes committed
188 189 190 191 192 193 194 195
                                            style="background: rgb(#F6F6F6);"),
                                        active=True,
                                        template='crispy/accordian-group.html'),

                         # Step 2: Short URL
                         AccordionGroup('Step 2: Short URL',
                                        Div(
                                            HTML("""
196 197
                                <h4>Modify the Go address:</h4>
                                <br />"""),
David Haynes's avatar
David Haynes committed
198 199 200 201 202 203 204 205 206 207
                                            PrependedText(
                                                'short', 'https://go.gmu.edu/', template='crispy/customPrepended.html'),
                                            style="background: rgb(#F6F6F6);"),
                                        active=True,
                                        template='crispy/accordian-group.html',),

                         # Step 3: Expiration
                         AccordionGroup('Step 3: URL Expiration',
                                        Div(
                                            HTML("""
208 209
                                <h4>Modify the expiration date:</h4>
                                <br />"""),
David Haynes's avatar
David Haynes committed
210 211 212 213 214 215 216 217 218 219 220
                                            'expires',
                                            Field('expires_custom',
                                                  template="crispy/customDateField.html"),
                                            style="background: rgb(#F6F6F6);"),
                                        active=True,
                                        template='crispy/accordian-group.html'),

                         # FIN
                         template='crispy/accordian.html'),
                     #######################
                     HTML("""
221
                <br />"""),
David Haynes's avatar
David Haynes committed
222
                     StrictButton('Submit Changes', css_class="btn btn-primary btn-md col-md-4", type='submit')))
223

224
    class Meta(URLForm.Meta):
225 226 227
        """
        Metadata about this ModelForm
        """
228 229 230
        # what attributes are included
        fields = URLForm.Meta.fields

David Haynes's avatar
David Haynes committed
231

232
class SignupForm(ModelForm):
233
    """
David Haynes's avatar
David Haynes committed
234
    The form that is used when a user is signing up to be a RegisteredUser
235
    """
236
    full_name = CharField(
237 238 239
        required=True,
        label='Full Name (Required)',
        max_length=100,
240
        widget=TextInput(),
David Haynes's avatar
David Haynes committed
241
        help_text="We can fill in this field based on information provided by https://peoplefinder.gmu.edu.",
242
    )
David Haynes's avatar
David Haynes committed
243

244
    organization = CharField(
245 246 247
        required=True,
        label='Organization (Required)',
        max_length=100,
248
        widget=TextInput(),
David Haynes's avatar
David Haynes committed
249
        help_text="Or whatever \"group\" you would associate with on campus.",
250
    )
David Haynes's avatar
David Haynes committed
251

252
    description = CharField(
253 254 255
        required=False,
        label='Description (Optional)',
        max_length=200,
256
        widget=Textarea(),
David Haynes's avatar
David Haynes committed
257
        help_text="Describe what type of links you would intend to create with Go.",
258
    )
David Haynes's avatar
David Haynes committed
259

260
    # A user becomes registered when they agree to the TOS
261
    registered = BooleanField(
262
        required=True,
David Haynes's avatar
David Haynes committed
263 264
        # ***Need to replace lower url with production URL***
        # ie. go.gmu.edu/about#terms
265
        label=mark_safe(
266
            'Do you accept the <a href="about">Terms of Service</a>?'
267
        ),
David Haynes's avatar
David Haynes committed
268
        help_text="Esssentially the GMU Responsible Use of Computing policies.",
269 270
    )

271
    def __init__(self, request, *args, **kwargs):
David Haynes's avatar
David Haynes committed
272
        """
273
        On initialization of the form, crispy forms renders this layout.
David Haynes's avatar
David Haynes committed
274 275 276
        """
        # Necessary to call request in forms.py, is otherwise restricted to
        # views.py and models.py
277 278
        self.request = request
        super(SignupForm, self).__init__(*args, **kwargs)
279
        self.helper = FormHelper()
280 281 282 283 284
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-md-4'
        self.helper.field_class = 'col-md-6'

        self.helper.layout = Layout(
285
            Fieldset('',
David Haynes's avatar
David Haynes committed
286 287 288 289 290 291 292 293 294 295 296 297 298
                     Div(
                         # Place in form fields
                         Div(
                             'full_name',
                             'organization',
                             'description',
                             'registered',
                             css_class='well'),

                         # Extras at bottom
                         StrictButton(
                             'Submit', css_class='btn btn-primary btn-md col-md-4', type='submit'),
                         css_class='col-md-6')))
David Haynes's avatar
David Haynes committed
299

300
    class Meta:
David Haynes's avatar
David Haynes committed
301 302 303
        """
        Metadata about this ModelForm
        """
David Haynes's avatar
David Haynes committed
304
        # what model this form is for
305
        model = RegisteredUser
David Haynes's avatar
David Haynes committed
306
        # what attributes are included
307
        fields = ['full_name', 'organization', 'description', 'registered']