Revision a70dacde

b/snf-astakos-app/astakos/im/forms.py
1 1
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2
# 
2
#
3 3
# Redistribution and use in source and binary forms, with or
4 4
# without modification, are permitted provided that the following
5 5
# conditions are met:
6
# 
6
#
7 7
#   1. Redistributions of source code must retain the above
8 8
#      copyright notice, this list of conditions and the following
9 9
#      disclaimer.
10
# 
10
#
11 11
#   2. Redistributions in binary form must reproduce the above
12 12
#      copyright notice, this list of conditions and the following
13 13
#      disclaimer in the documentation and/or other materials
14 14
#      provided with the distribution.
15
# 
15
#
16 16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
......
25 25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 27
# POSSIBILITY OF SUCH DAMAGE.
28
# 
28
#
29 29
# The views and conclusions contained in the software and
30 30
# documentation are those of the authors and should not be
31 31
# interpreted as representing official policies, either expressed
......
42 42
from django.utils.http import int_to_base36
43 43
from django.core.urlresolvers import reverse
44 44
from django.utils.functional import lazy
45
from django.utils.safestring import mark_safe
45 46

  
46 47
from astakos.im.models import AstakosUser
47 48
from astakos.im.settings import INVITATIONS_PER_LEVEL, DEFAULT_FROM_EMAIL, BASEURL, SITENAME, RECAPTCHA_PRIVATE_KEY, DEFAULT_CONTACT_EMAIL, RECAPTCHA_ENABLED
......
58 59
class LocalUserCreationForm(UserCreationForm):
59 60
    """
60 61
    Extends the built in UserCreationForm in several ways:
61
    
62

  
62 63
    * Adds email, first_name, last_name, recaptcha_challenge_field, recaptcha_response_field field.
63 64
    * The username field isn't visible and it is assigned a generated id.
64
    * User created is not active. 
65
    * User created is not active.
65 66
    """
66 67
    recaptcha_challenge_field = forms.CharField(widget=DummyWidget)
67 68
    recaptcha_response_field = forms.CharField(widget=RecaptchaWidget, label='')
68
    
69

  
69 70
    class Meta:
70 71
        model = AstakosUser
71 72
        fields = ("email", "first_name", "last_name", "has_signed_terms")
72 73
        widgets = {"has_signed_terms":ApprovalTermsWidget(terms_uri=reverse_lazy('latest_terms'))}
73
    
74

  
74 75
    def __init__(self, *args, **kwargs):
75 76
        """
76 77
        Changes the order of fields, and removes the username field.
......
86 87
        if RECAPTCHA_ENABLED:
87 88
            self.fields.keyOrder.extend(['recaptcha_challenge_field',
88 89
                                         'recaptcha_response_field',])
89
    
90

  
91
        if 'has_signed_terms' in self.fields:
92
            # Overriding field label since we need to apply a link
93
            # to the terms within the label
94
            terms_link_html = '<a href="%s" target="_blank">%s</a>' \
95
                    % (reverse('latest_terms'), _("the terms"))
96
            self.fields['has_signed_terms'].label = \
97
                    mark_safe("I agree with %s" % terms_link_html)
98

  
90 99
    def clean_email(self):
91 100
        email = self.cleaned_data['email']
92 101
        if not email:
......
96 105
            raise forms.ValidationError(_("This email is already used"))
97 106
        except AstakosUser.DoesNotExist:
98 107
            return email
99
    
108

  
100 109
    def clean_has_signed_terms(self):
101 110
        has_signed_terms = self.cleaned_data['has_signed_terms']
102 111
        if not has_signed_terms:
103 112
            raise forms.ValidationError(_('You have to agree with the terms'))
104 113
        return has_signed_terms
105
    
114

  
106 115
    def clean_recaptcha_response_field(self):
107 116
        if 'recaptcha_challenge_field' in self.cleaned_data:
108 117
            self.validate_captcha()
......
119 128
        check = captcha.submit(rcf, rrf, RECAPTCHA_PRIVATE_KEY, self.ip)
120 129
        if not check.is_valid:
121 130
            raise forms.ValidationError(_('You have not entered the correct words'))
122
    
131

  
123 132
    def save(self, commit=True):
124 133
        """
125 134
        Saves the email, first_name and last_name properties, after the normal
......
137 146
    """
138 147
    Extends the LocalUserCreationForm: adds an inviter readonly field.
139 148
    """
140
    
149

  
141 150
    inviter = forms.CharField(widget=forms.TextInput(), label=_('Inviter Real Name'))
142
    
151

  
143 152
    class Meta:
144 153
        model = AstakosUser
145 154
        fields = ("email", "first_name", "last_name", "has_signed_terms")
146 155
        widgets = {"has_signed_terms":ApprovalTermsWidget(terms_uri=reverse_lazy('latest_terms'))}
147
    
156

  
148 157
    def __init__(self, *args, **kwargs):
149 158
        """
150 159
        Changes the order of fields, and removes the username field.
151 160
        """
152 161
        super(InvitedLocalUserCreationForm, self).__init__(*args, **kwargs)
153
        
162

  
154 163
        #set readonly form fields
155 164
        self.fields['inviter'].widget.attrs['readonly'] = True
156 165
        self.fields['email'].widget.attrs['readonly'] = True
157 166
        self.fields['username'].widget.attrs['readonly'] = True
158
    
167

  
159 168
    def save(self, commit=True):
160 169
        user = super(InvitedLocalUserCreationForm, self).save(commit=False)
161 170
        level = user.invitation.inviter.level + 1
......
173 182
    """
174 183
    Subclass of ``ModelForm`` for permiting user to edit his/her profile.
175 184
    Most of the fields are readonly since the user is not allowed to change them.
176
    
185

  
177 186
    The class defines a save method which sets ``is_verified`` to True so as the user
178 187
    during the next login will not to be redirected to profile page.
179 188
    """
180 189
    renew = forms.BooleanField(label='Renew token', required=False)
181
    
190

  
182 191
    class Meta:
183 192
        model = AstakosUser
184 193
        fields = ('email', 'first_name', 'last_name', 'auth_token', 'auth_token_expires')
185
    
194

  
186 195
    def __init__(self, *args, **kwargs):
187 196
        super(ProfileForm, self).__init__(*args, **kwargs)
188 197
        instance = getattr(self, 'instance', None)
......
190 199
        if instance and instance.id:
191 200
            for field in ro_fields:
192 201
                self.fields[field].widget.attrs['readonly'] = True
193
    
202

  
194 203
    def save(self, commit=True):
195 204
        user = super(ProfileForm, self).save(commit=False)
196 205
        user.is_verified = True
......
204 213
    class Meta:
205 214
        model = AstakosUser
206 215
        fields = ('email', 'last_name', 'first_name', 'affiliation', 'provider', 'third_party_identifier')
207
    
216

  
208 217
    def __init__(self, *args, **kwargs):
209 218
        if 'ip' in kwargs:
210 219
            self.ip = kwargs['ip']
211 220
            kwargs.pop('ip')
212 221
        super(ThirdPartyUserCreationForm, self).__init__(*args, **kwargs)
213 222
        self.fields.keyOrder = ['email']
214
    
223

  
215 224
    def clean_email(self):
216 225
        email = self.cleaned_data['email']
217 226
        if not email:
......
221 230
            raise forms.ValidationError(_("This email is already used"))
222 231
        except AstakosUser.DoesNotExist:
223 232
            return email
224
    
233

  
225 234
    def save(self, commit=True):
226 235
        user = super(ThirdPartyUserCreationForm, self).save(commit=False)
227 236
        user.verified = False
......
250 259
    """
251 260
    Form for sending an invitations
252 261
    """
253
    
262

  
254 263
    email = forms.EmailField(required = True, label = 'Email address')
255 264
    first_name = forms.EmailField(label = 'First name')
256 265
    last_name = forms.EmailField(label = 'Last name')
......
259 268
    """
260 269
    Extends PasswordResetForm by overriding save method:
261 270
    passes a custom from_email in send_mail.
262
    
271

  
263 272
    Since Django 1.3 this is useless since ``django.contrib.auth.views.reset_password``
264 273
    accepts a from_email argument.
265 274
    """
......
289 298
    class Meta:
290 299
        model = AstakosUser
291 300
        fields = ("has_signed_terms",)
292
    
301

  
293 302
    def __init__(self, *args, **kwargs):
294 303
        super(SignApprovalTermsForm, self).__init__(*args, **kwargs)
295
    
304

  
296 305
    def clean_has_signed_terms(self):
297 306
        has_signed_terms = self.cleaned_data['has_signed_terms']
298 307
        if not has_signed_terms:
299 308
            raise forms.ValidationError(_('You have to agree with the terms'))
300 309
        return has_signed_terms
301
    
310

  
302 311
    def save(self, commit=True):
303 312
        """
304 313
        Saves the , after the normal
......
308 317
        user.date_signed_terms = datetime.now()
309 318
        if commit:
310 319
            user.save()
311
        return user
320
        return user
b/snf-astakos-app/astakos/im/static/im/css/styles.css
844 844
  background-color: #3582ac;
845 845
}
846 846
.rightcol {
847
  margin-left: 511px;
847
  display: inline;
848
  float: left;
849
  margin-left: 22px;
848 850
  width: 306px;
851
  margin-left: 102px;
849 852
}
850 853
.rightcol.narrow {
851
  margin-left: 593px;
854
  display: inline;
855
  float: left;
856
  margin-left: 22px;
852 857
  width: 224px;
858
  margin-left: 102px;
853 859
}
854 860
.rightcol input[type=text], .rightcol input[type=password] {
855 861
  width: 273px;
......
994 1000
form .form-row.submit {
995 1001
  margin-top: 22px;
996 1002
}
1003
form .form-row.with-checkbox {
1004
  margin-top: 7px;
1005
}
997 1006
form .form-row .extra-link {
998 1007
  color: #808080;
999 1008
  text-decoration: none;
......
1012 1021
  color: #aaa;
1013 1022
}
1014 1023
form.innerlabels p {
1015
  position: relative;
1016 1024
  display: table;
1025
  position: relative;
1017 1026
}
1018 1027
form textarea,
1019 1028
form input.text,
......
1192 1201
  color: inherit;
1193 1202
  font-weight: bold;
1194 1203
}
1204
form.innerlabels label.checkbox-label {
1205
  position: relative !important;
1206
  margin-left: 10px !important;
1207
  padding-top: 1em !important;
1208
  top: 11px !important;
1209
  left: 10px;
1210
  cursor: pointer;
1211
}
1195 1212
.service-desc {
1196 1213
  margin-top: 4em;
1197 1214
}
......
1481 1498
  margin-bottom: 2em;
1482 1499
  font-size: 0.8em;
1483 1500
}
1484
.initial_hidden {
1501
.initially-hidden {
1485 1502
  display: none;
1486 1503
}
1487 1504
/* recaptcha */
......
1497 1514
#recaptcha_widget_div th, #recaptcha_widget_div td {
1498 1515
  line-height: 1;
1499 1516
}
1500
form.innerlabels label.checkbox-label {
1501
  position: relative !important;
1502
  margin-left: 10px !important;
1503
  padding-top: 1em !important;
1504
  top: 7px !important;
1505
  left: 10px;
1506
  cursor: pointer;
1507
}
1508 1517
.checkbox-widget.checked {
1509 1518
  background-color: #f00;
1510 1519
  background-image: url("../images/checkbox.png");
b/snf-astakos-app/astakos/im/static/im/css/styles.less
431 431
            margin-top: 1.5*@verticalSpacing;
432 432
        }
433 433

  
434
        &.with-checkbox {
435
            margin-top: 7px;    
436
        }
437

  
434 438
        .extra-link {
435 439
            color: @gray;
436 440
            text-decoration: none;
......
569 573
    position: relative !important; 
570 574
    margin-left: 10px !important;
571 575
    padding-top: 1em !important;
572
    top:7px !important; 
576
    top:11px !important; 
573 577
    left:10px;
574 578
    cursor: pointer;
575 579
}
b/snf-astakos-app/astakos/im/static/im/js/forms.js
3 3
  $.fn.formCheckBoxes = function(options) {
4 4
    
5 5
    return this.each(function() {
6
      // process checkboxes
6 7
      var $this = $(this);
7 8
      var el = $('<span class="checkbox-widget" />');
9
      var form = $this.closest(".form-row");
10

  
11
      // add class to identify form rows which contain a checkbox
12
      form.addClass("with-checkbox");
8 13
      
9 14
      if ($this.prev().length > 0) {
10 15
        var lbl = $this.prev()[0];
11 16
        if (lbl.nodeName == "LABEL" || lbl.nodeName == "label") {
12 17
            $(lbl).addClass("checkbox-label");
13 18

  
14
            $(lbl).click(function(){
15
                el.toggleClass("checked");
19
            $(lbl).click(function(e){
20
                var src = e.srcElement.nodeName;
21
                if (src == "LABEL" || src == "label") {
22
                    el.toggleClass("checked");
23
                };
16 24
            })
17 25
        }
18 26
      }
b/snf-astakos-app/astakos/im/widgets.py
71 71
        super(ApprovalTermsWidget, self).__init__(attrs, check_test)
72 72
        self.uri = terms_uri
73 73
        self.label = terms_label
74
    
74

  
75 75
    def render(self, name, value, attrs=None):
76 76
        html = super(ApprovalTermsWidget, self).render(name, value, attrs)
77
        return html + mark_safe('<a href=%s target="_blank">%s</a>' % (self.uri, self.label))
77
        return html

Also available in: Unified diff