Commit 5ee0d0eebb51c4507e19adc86c9c8f1edd994a30
1 parent
f3421ecd
Exists in
master
and in
29 other branches
Signup interface improvements
Showing
37 changed files
with
710 additions
and
142 deletions
Show diff stats
app/controllers/public/account_controller.rb
| @@ -60,6 +60,10 @@ class AccountController < ApplicationController | @@ -60,6 +60,10 @@ class AccountController < ApplicationController | ||
| 60 | def signup | 60 | def signup |
| 61 | @invitation_code = params[:invitation_code] | 61 | @invitation_code = params[:invitation_code] |
| 62 | begin | 62 | begin |
| 63 | + if params[:user] | ||
| 64 | + params[:user].delete(:password_confirmation_clear) | ||
| 65 | + params[:user].delete(:password_clear) | ||
| 66 | + end | ||
| 63 | @user = User.new(params[:user]) | 67 | @user = User.new(params[:user]) |
| 64 | @user.terms_of_use = environment.terms_of_use | 68 | @user.terms_of_use = environment.terms_of_use |
| 65 | @user.environment = environment | 69 | @user.environment = environment |
| @@ -209,16 +213,26 @@ class AccountController < ApplicationController | @@ -209,16 +213,26 @@ class AccountController < ApplicationController | ||
| 209 | @identifier = params[:identifier] | 213 | @identifier = params[:identifier] |
| 210 | valid = Person.is_available?(@identifier, environment) | 214 | valid = Person.is_available?(@identifier, environment) |
| 211 | if valid | 215 | if valid |
| 212 | - @status = _('Available!') | 216 | + @status = _('This login name is available') |
| 213 | @status_class = 'available' | 217 | @status_class = 'available' |
| 214 | else | 218 | else |
| 215 | - @status = _('Unavailable!') | 219 | + @status = _('This login name is unavailable') |
| 216 | @status_class = 'unavailable' | 220 | @status_class = 'unavailable' |
| 217 | end | 221 | end |
| 218 | - @url = environment.top_url + '/' + @identifier | ||
| 219 | render :partial => 'identifier_status' | 222 | render :partial => 'identifier_status' |
| 220 | end | 223 | end |
| 221 | 224 | ||
| 225 | + def check_email | ||
| 226 | + if User.find_by_email_and_environment_id(params[:address], environment.id).nil? | ||
| 227 | + @status = _('This e-mail address is available') | ||
| 228 | + @status_class = 'available' | ||
| 229 | + else | ||
| 230 | + @status = _('This e-mail address is taken') | ||
| 231 | + @status_class = 'unavailable' | ||
| 232 | + end | ||
| 233 | + render :partial => 'email_status' | ||
| 234 | + end | ||
| 235 | + | ||
| 222 | def user_data | 236 | def user_data |
| 223 | user_data = | 237 | user_data = |
| 224 | if logged_in? | 238 | if logged_in? |
app/controllers/public/home_controller.rb
app/helpers/account_helper.rb
| 1 | module AccountHelper | 1 | module AccountHelper |
| 2 | 2 | ||
| 3 | + def validation_classes | ||
| 4 | + 'available unavailable valid invalid checking' | ||
| 5 | + end | ||
| 6 | + | ||
| 7 | + def checking_message(key) | ||
| 8 | + case key | ||
| 9 | + when :url | ||
| 10 | + _('Checking availability of login name...') | ||
| 11 | + when :email | ||
| 12 | + _('Checking if e-mail address is already taken...') | ||
| 13 | + end | ||
| 14 | + end | ||
| 3 | end | 15 | end |
app/helpers/application_helper.rb
| @@ -1317,4 +1317,14 @@ module ApplicationHelper | @@ -1317,4 +1317,14 @@ module ApplicationHelper | ||
| 1317 | ) + content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') | 1317 | ) + content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') |
| 1318 | end | 1318 | end |
| 1319 | end | 1319 | end |
| 1320 | + | ||
| 1321 | + def render_tabs(tabs) | ||
| 1322 | + titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') } | ||
| 1323 | + contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) } | ||
| 1324 | + | ||
| 1325 | + content_tag :div, :class => 'ui-tabs' do | ||
| 1326 | + content_tag(:ul, titles) + contents | ||
| 1327 | + end | ||
| 1328 | + end | ||
| 1329 | + | ||
| 1320 | end | 1330 | end |
app/helpers/profile_helper.rb
| @@ -15,12 +15,4 @@ module ProfileHelper | @@ -15,12 +15,4 @@ module ProfileHelper | ||
| 15 | end | 15 | end |
| 16 | end | 16 | end |
| 17 | 17 | ||
| 18 | - def render_tabs(tabs) | ||
| 19 | - titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') } | ||
| 20 | - contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) } | ||
| 21 | - | ||
| 22 | - content_tag :div, :class => 'ui-tabs' do | ||
| 23 | - content_tag(:ul, titles) + contents | ||
| 24 | - end | ||
| 25 | - end | ||
| 26 | end | 18 | end |
app/models/person.rb
| @@ -116,6 +116,7 @@ class Person < Profile | @@ -116,6 +116,7 @@ class Person < Profile | ||
| 116 | contact_phone | 116 | contact_phone |
| 117 | contact_information | 117 | contact_information |
| 118 | description | 118 | description |
| 119 | + image | ||
| 119 | ] | 120 | ] |
| 120 | 121 | ||
| 121 | validates_multiparameter_assignments | 122 | validates_multiparameter_assignments |
app/models/profile.rb
| @@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
| 1 | +<div class='status-identifier'> | ||
| 2 | + <p><span class='<%= @status_class %>'><%= @status %></span></p> | ||
| 3 | + <script type="text/javascript"> | ||
| 4 | + jQuery('#user_email').removeClass('<%= validation_classes %>'); | ||
| 5 | + jQuery('#user_email').addClass('<%= @status_class %>'); | ||
| 6 | + </script> | ||
| 7 | +</div> |
app/views/account/_identifier_status.rhtml
| 1 | <div class='status-identifier'> | 1 | <div class='status-identifier'> |
| 2 | - <p><%= @url %> <span class='<%= @status_class %>'><%= @status %></span> </p> | 2 | + <p><span class='<%= @status_class %>'><%= @status %></span></p> |
| 3 | + <script type="text/javascript"> | ||
| 4 | + jQuery('#user_login').removeClass('<%= validation_classes %>'); | ||
| 5 | + jQuery('#user_login').addClass('<%= @status_class %>'); | ||
| 6 | + </script> | ||
| 3 | </div> | 7 | </div> |
app/views/account/_signup_form.rhtml
| 1 | <%= error_messages_for :user, :person %> | 1 | <%= error_messages_for :user, :person %> |
| 2 | 2 | ||
| 3 | -<% if ! defined? hidden_atention || ! hidden_atention %> | ||
| 4 | -<p/> | ||
| 5 | -<div class="atention"> | ||
| 6 | -<%= _('Dear user, welcome to the %s network. To start your participation in this space, fill in the fields below. After this operation, your login and password will be registered, allowing you to create %s and %s in this environment.') % [environment.name, __('communities'), __('enterprises')] %> | ||
| 7 | -</div> | ||
| 8 | -<% end %> | ||
| 9 | - | ||
| 10 | -<% labelled_form_for :user, @user, :html => { :multipart => true } do |f| %> | 3 | +<% labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form' } do |f| %> |
| 11 | 4 | ||
| 12 | <%= hidden_field_tag :invitation_code, @invitation_code %> | 5 | <%= hidden_field_tag :invitation_code, @invitation_code %> |
| 13 | 6 | ||
| 14 | -<%= required_fields_message %> | 7 | +<div id='signup-form-header'> |
| 15 | 8 | ||
| 16 | -<div id='signup-email'> | ||
| 17 | - <%= required f.text_field(:email) %> | ||
| 18 | - <%= content_tag(:small,_('This e-mail address will be used to contact you.')) %> | ||
| 19 | -</div> | 9 | + <span id="signup-domain"><%= environment.default_hostname %>/</span> |
| 10 | + <div id='signup-login'> | ||
| 11 | + <div id='signup-login-field'> | ||
| 12 | + <%= required f.text_field(:login, :onchange => 'this.value = convToValidLogin(this.value);', :rel => s_('signup|Login')) %> | ||
| 13 | + <div id='url-check'><p> </p></div> | ||
| 14 | + </div> | ||
| 15 | + <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %> | ||
| 16 | + <br style="clear: both;" /> | ||
| 17 | + </div> | ||
| 18 | + <%= observe_field 'user_login', | ||
| 19 | + :url => { :action => 'check_url' }, | ||
| 20 | + :with => 'identifier', | ||
| 21 | + :update => 'url-check', | ||
| 22 | + :loading => "jQuery('#user_login').removeClass('#{validation_classes}').addClass('checking'); | ||
| 23 | + jQuery('#url-check').html('<p><span class=\"checking\">#{checking_message(:url)}</span></p>');", | ||
| 24 | + :complete => "jQuery('#user_login').removeClass('checking')" | ||
| 25 | + %> | ||
| 20 | 26 | ||
| 21 | -<%= required f.text_field(:login, :onchange => 'this.value = convToValidLogin( this.value )') %> | ||
| 22 | -<%= content_tag(:small,_('Insert your login')) %> | ||
| 23 | -<div id='url-check'></div> | 27 | + <div id='signup-password'> |
| 28 | + <%= required f.password_field(:password, :id => 'user_pw') %> | ||
| 29 | + <%= f.text_field(:password_clear, :value => _('password')) %> | ||
| 30 | + <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %> | ||
| 31 | + <div id='fake-check'><p> </p></div> | ||
| 32 | + </div> | ||
| 33 | + | ||
| 34 | + <div id='signup-password-confirmation'> | ||
| 35 | + <%= required f.password_field(:password_confirmation) %> | ||
| 36 | + <%= f.text_field(:password_confirmation_clear, :value => _('password confirmation')) %> | ||
| 37 | + <div id='password-check'><p> </p></div> | ||
| 38 | + </div> | ||
| 39 | + | ||
| 40 | + <div id='signup-email'> | ||
| 41 | + <%= required f.text_field(:email, :rel => _('e-Mail')) %> | ||
| 42 | + <%= content_tag(:small,_('This e-mail address will be used to contact you.')) %> | ||
| 43 | + <div id='email-check'><p> </p></div> | ||
| 44 | + </div> | ||
| 45 | + <%= observe_field "user_email", | ||
| 46 | + :url => { :action => "check_email" }, | ||
| 47 | + :with => "address", | ||
| 48 | + :update => "email-check", | ||
| 49 | + :loading => "jQuery('#user_email').removeClass('#{validation_classes}').addClass('checking'); | ||
| 50 | + jQuery('#email-check').html('<p><span class=\"checking\">#{checking_message(:email)}</span></p>');", | ||
| 51 | + :complete => "jQuery('#user_email').removeClass('checking')", | ||
| 52 | + :before => "if (!( jQuery('#user_email').valid() )) { | ||
| 53 | + jQuery('#user_email').removeClass('#{validation_classes}').addClass('unavailable'); | ||
| 54 | + jQuery('#email-check').html('<p><span class=\"unavailable\">#{_('This e-mail address is not valid')}</span></p>'); | ||
| 55 | + return false; | ||
| 56 | + }" | ||
| 57 | + %> | ||
| 24 | 58 | ||
| 25 | -<%= observe_field 'user_login', :url => {:action => 'check_url'}, :with => 'identifier', :update => 'url-check' %> | 59 | + <%= label :profile_data, :name %> |
| 60 | + <%= required text_field(:profile_data, :name, :rel => _('Full name')) %> | ||
| 26 | 61 | ||
| 27 | -<div id='signup-password'> | ||
| 28 | - <%= required f.password_field(:password) %> | ||
| 29 | - <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.')) %> | ||
| 30 | </div> | 62 | </div> |
| 31 | 63 | ||
| 32 | -<%= required f.password_field(:password_confirmation) %> | ||
| 33 | -<%= content_tag(:small,_('To confirm, repeat your password.')) %> | ||
| 34 | - | ||
| 35 | -<% labelled_fields_for :profile_data, @person do |f| %> | ||
| 36 | - <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %> | ||
| 37 | -<% end %> | ||
| 38 | - | ||
| 39 | -<% unless @terms_of_use.blank? %> | ||
| 40 | - <div id='terms-of-use-box' class='formfieldline'> | ||
| 41 | - <%= _("By clicking on 'I accept the terms of use' below you are agreeing to the %s") % | ||
| 42 | - link_to_function(_('Terms of use'), nil) do |page| | ||
| 43 | - page['terms-of-use'].show | ||
| 44 | - end %> | ||
| 45 | - | ||
| 46 | - <div id='terms-of-use' style='display: none;'> | ||
| 47 | - <%= @terms_of_use %> | ||
| 48 | - <%= link_to_function(_('Hide'), nil) do |page| | ||
| 49 | - page['terms-of-use'].hide | ||
| 50 | - end %> | 64 | +<div id="signup-form-profile"> |
| 65 | + | ||
| 66 | + <% labelled_fields_for :profile_data, @person do |f| %> | ||
| 67 | + <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %> | ||
| 68 | + <% end %> | ||
| 69 | + | ||
| 70 | + <% unless @terms_of_use.blank? %> | ||
| 71 | + <div id='terms-of-use-box' class='formfieldline'> | ||
| 72 | + <%= labelled_check_box(_('I accept the %s') % link_to(_('terms of use'), {:controller => 'home', :action => 'terms'}, :target => '_blank'), 'user[terms_accepted]') %> | ||
| 51 | </div> | 73 | </div> |
| 52 | - <p><%= labelled_check_box(environment.terms_of_use_acceptance_text.blank? ? _('I accept the terms of use') : environment.terms_of_use_acceptance_text, 'user[terms_accepted]') %></p> | ||
| 53 | - </div> | ||
| 54 | -<% end %> | ||
| 55 | - | ||
| 56 | -<% if params[:enterprise_code] %> | ||
| 57 | - <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %> | ||
| 58 | - <%= hidden_field_tag :answer, params[:answer] %> | ||
| 59 | - <%= hidden_field_tag :terms_accepted, params[:terms_accepted] %> | ||
| 60 | - <%= hidden_field_tag :new_user, true %> | ||
| 61 | -<% end %> | ||
| 62 | - | ||
| 63 | -<% button_bar do %> | ||
| 64 | - <%= submit_button('save', _('Sign up'), :cancel => {:action => 'index'}, :class => 'icon-menu-login') %> | ||
| 65 | -<% end %> | 74 | + <% end %> |
| 75 | + | ||
| 76 | + <% if params[:enterprise_code] %> | ||
| 77 | + <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %> | ||
| 78 | + <%= hidden_field_tag :answer, params[:answer] %> | ||
| 79 | + <%= hidden_field_tag :terms_accepted, params[:terms_accepted] %> | ||
| 80 | + <%= hidden_field_tag :new_user, true %> | ||
| 81 | + <% end %> | ||
| 82 | +</div> | ||
| 83 | + | ||
| 84 | +<p style="text-align: center"> | ||
| 85 | + <%= submit_button('save', _('Create my account')) %> | ||
| 86 | +</p> | ||
| 87 | + | ||
| 66 | <% end -%> | 88 | <% end -%> |
| 89 | + | ||
| 90 | +<script type="text/javascript"> | ||
| 91 | +jQuery(function($) { | ||
| 92 | + $('#signup-form input[type=text], #signup-form textarea').each(function() { | ||
| 93 | + if ($(this).attr('rel')) var default_value = $(this).attr('rel').toLowerCase(); | ||
| 94 | + if ($(this).val() == '') $(this).val(default_value); | ||
| 95 | + $(this).bind('focus', function() { | ||
| 96 | + if ($(this).val() == default_value) $(this).val(''); | ||
| 97 | + }); | ||
| 98 | + $(this).bind('blur', function() { | ||
| 99 | + if ($(this).val() == '') { | ||
| 100 | + $(this).val(default_value); | ||
| 101 | + $(this).removeClass('filled-in'); | ||
| 102 | + } | ||
| 103 | + else $(this).addClass('filled-in'); | ||
| 104 | + }); | ||
| 105 | + }); | ||
| 106 | + | ||
| 107 | + $('#signup-form').bind('submit', function() { | ||
| 108 | + $('#signup-form input[type=text], #signup-form textarea').each(function() { | ||
| 109 | + if ($(this).attr('rel')) var default_value = $(this).attr('rel').toLowerCase(); | ||
| 110 | + if ($(this).val() == default_value) $(this).val(''); | ||
| 111 | + }); | ||
| 112 | + return true; | ||
| 113 | + }); | ||
| 114 | + | ||
| 115 | + $('#user_password_clear, #user_password_confirmation_clear').show(); | ||
| 116 | + $('#user_password_clear, #user_password_confirmation_clear').unbind(); | ||
| 117 | + $('#user_pw, #user_password_confirmation').hide(); | ||
| 118 | + $('#user_password_clear').focus(function() { | ||
| 119 | + $(this).hide(); | ||
| 120 | + $('#user_pw').show(); | ||
| 121 | + $('#user_pw').focus(); | ||
| 122 | + }); | ||
| 123 | + $('#user_pw').focus(function() { | ||
| 124 | + $('#password-balloon').fadeIn('slow'); | ||
| 125 | + }); | ||
| 126 | + $('#user_pw').blur(function() { | ||
| 127 | + if ($(this).val() == '') { | ||
| 128 | + $('#user_password_clear').show(); | ||
| 129 | + $(this).hide(); | ||
| 130 | + } | ||
| 131 | + }); | ||
| 132 | + $('#user_password_confirmation_clear').focus(function() { | ||
| 133 | + $(this).hide(); | ||
| 134 | + $('#user_password_confirmation').show(); | ||
| 135 | + $('#user_password_confirmation').focus(); | ||
| 136 | + }); | ||
| 137 | + $('#user_password_confirmation, #user_pw').blur(function() { | ||
| 138 | + if ($('#user_password_confirmation').val() == '') { | ||
| 139 | + $('#user_password_confirmation_clear').show(); | ||
| 140 | + $('#user_password_confirmation').hide(); | ||
| 141 | + } else if ($('#user_password_confirmation').val() == $('#user_pw').val()) { | ||
| 142 | + $('#user_password_confirmation').addClass('passwords_match').removeClass('passwords_differ'); | ||
| 143 | + $('#user_pw').removeClass('invalid_input').addClass('valid_input'); | ||
| 144 | + $('#password-check').html("<p> </p>"); | ||
| 145 | + } else if ($('#user_password_confirmation').val() != $('#user_pw').val()) { | ||
| 146 | + $('#user_password_confirmation').removeClass('passwords_match').addClass('passwords_differ'); | ||
| 147 | + $('#user_pw').addClass('invalid_input').removeClass('valid_input'); | ||
| 148 | + $('#password-check').html("<p><span class='unavailable'><%= _('Passwords don\'t match') %></span></p>"); | ||
| 149 | + } | ||
| 150 | + $('#password-balloon').fadeOut('slow'); | ||
| 151 | + }); | ||
| 152 | + $('#user_login').focus(function() { | ||
| 153 | + $('#signup-balloon').fadeIn('slow'); | ||
| 154 | + }); | ||
| 155 | + $('#user_login').blur(function() { $('#signup-balloon').fadeOut('slow'); }); | ||
| 156 | + $('#signup-form').validate({ rules: { 'user[email]': { email: true } }, messages: { 'user[email]' : '' } }); | ||
| 157 | +}); | ||
| 158 | +</script> |
app/views/account/signup.rhtml
| 1 | -<h1><%= _('Signup') %></h1> | ||
| 2 | <% if @register_pending %> | 1 | <% if @register_pending %> |
| 3 | - <%= _('Thanks for signing up! Now check your e-mail to activate your account!') %> | ||
| 4 | - <p style="text-align: center"><%= link_to(_('Go to the homepage'), '/') %></p> | 2 | +<div id='thanks-for-signing'> |
| 3 | + <%= _("<h1>Welcome to %s!</h1> | ||
| 4 | + <h3>Thanks for signing up, we're thrilled to have you on our social network!</h3> | ||
| 5 | + <p>Firsty, some tips for getting started:</p> | ||
| 6 | + <h4>Confirm your account!</h4> | ||
| 7 | + <p>You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.</p> | ||
| 8 | + <p>You won't appear as a <a href=\"%s\">user</a> until your account is confirmed.</p> | ||
| 9 | + <h4>What to do next?</h4> | ||
| 10 | + <p><a href=\"/doc/user/editing-person-info\">Customize your profile</a>. Upload an avatar and sign up for activity notifications under Account.</p> | ||
| 11 | + <p>Learn the guidelines. Read the <a href=\"/doc\">Documentation</a> for more details on how to use new social network!</p> | ||
| 12 | + <p><a href=\"/profile/noosfero_person_template/invite/friends\">Invite and find</a> your Gmail, Yahoo and Hotmail contacts!</p> | ||
| 13 | + <p>Start exploring and Have fun!</p>" % [environment.name, url_for(:controller => :browse, :action => :people, :filter => 'more_recent')]) %> | ||
| 14 | +</div> | ||
| 5 | <% else %> | 15 | <% else %> |
| 16 | + <h1><%= _('Sign up for %s!') % environment.name %></h1> | ||
| 6 | <%= render :partial => 'signup_form' %> | 17 | <%= render :partial => 'signup_form' %> |
| 7 | <% end %> | 18 | <% end %> |
| @@ -0,0 +1,3 @@ | @@ -0,0 +1,3 @@ | ||
| 1 | +<%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %> | ||
| 2 | +<%= required f.text_field(:reports_lower_bound, :size => 3) %> | ||
| 3 | +<%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => 'mceEditor') %> |
| @@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
| 1 | +<%= f.text_area :terms_of_use, :cols => 40, :style => 'width: 90%', :class => 'mceEditor' %> |
app/views/admin_panel/index.rhtml
| @@ -15,7 +15,6 @@ | @@ -15,7 +15,6 @@ | ||
| 15 | <tr><td><%= link_to _('Edit Templates'), :action => 'edit_templates' %></td></tr> | 15 | <tr><td><%= link_to _('Edit Templates'), :action => 'edit_templates' %></td></tr> |
| 16 | <tr><td><%= link_to _('Manage Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> | 16 | <tr><td><%= link_to _('Manage Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> |
| 17 | <tr><td><%= link_to _('Set Portal'), :action => 'set_portal_community' %></td></tr> | 17 | <tr><td><%= link_to _('Set Portal'), :action => 'set_portal_community' %></td></tr> |
| 18 | - <tr><td><%= link_to _('Terms of use'), :action => 'terms_of_use' %></td></tr> | ||
| 19 | <% @plugins.map(:admin_panel_links).each do |link| %> | 18 | <% @plugins.map(:admin_panel_links).each do |link| %> |
| 20 | <tr><td><%= link_to link[:title], link[:url] %></td></tr> | 19 | <tr><td><%= link_to link[:title], link[:url] %></td></tr> |
| 21 | <% end %> | 20 | <% end %> |
app/views/admin_panel/site_info.rhtml
| @@ -5,10 +5,12 @@ | @@ -5,10 +5,12 @@ | ||
| 5 | <%= render :file => 'shared/tiny_mce' %> | 5 | <%= render :file => 'shared/tiny_mce' %> |
| 6 | 6 | ||
| 7 | <% labelled_form_for :environment, @environment, :url => {:host => @environment.default_hostname} do |f| %> | 7 | <% labelled_form_for :environment, @environment, :url => {:host => @environment.default_hostname} do |f| %> |
| 8 | - <%= required labelled_form_field(_('Site name'), text_field(:environment, :name)) %> | ||
| 9 | - <%= required f.text_field(:reports_lower_bound, :size => 3) %> | ||
| 10 | - <%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => 'mceEditor') %> | ||
| 11 | - | 8 | + <% tabs = [] %> |
| 9 | + <% tabs << {:title => _('Site info'), :id => 'site-info', | ||
| 10 | + :content => (render :partial => 'site_info', :locals => {:f => f})} %> | ||
| 11 | + <% tabs << {:title => _('Terms of use'), :id => 'terms-of-use', | ||
| 12 | + :content => (render :partial => 'terms_of_use', :locals => {:f => f})} %> | ||
| 13 | + <%= render_tabs(tabs) %> | ||
| 12 | <% button_bar do %> | 14 | <% button_bar do %> |
| 13 | <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> | 15 | <%= submit_button(:save, _('Save'), :cancel => {:action => 'index'}) %> |
| 14 | <% end %> | 16 | <% end %> |
app/views/admin_panel/terms_of_use.rhtml
| @@ -1,14 +0,0 @@ | @@ -1,14 +0,0 @@ | ||
| 1 | -<h2><%= _('Terms of use') %></h2> | ||
| 2 | - | ||
| 3 | -<%= render :file => 'shared/tiny_mce' %> | ||
| 4 | - | ||
| 5 | -<% labelled_form_for :environment, @environment, :url => {:action => 'site_info'} do |f| %> | ||
| 6 | - | ||
| 7 | - <%= f.text_area :terms_of_use, :cols => 40, :style => 'width: 90%' %> | ||
| 8 | - | ||
| 9 | - <% button_bar do %> | ||
| 10 | - <%= submit_button(:save, _('Save')) %> | ||
| 11 | - <%= button(:cancel, _('Cancel'), :action => 'index') %> | ||
| 12 | - <% end %> | ||
| 13 | - | ||
| 14 | -<% end %> |
app/views/layouts/application-ng.rhtml
| @@ -58,7 +58,7 @@ | @@ -58,7 +58,7 @@ | ||
| 58 | <%= usermenu_logged_in %> | 58 | <%= usermenu_logged_in %> |
| 59 | </span> | 59 | </span> |
| 60 | <span class='not-logged-in' style='display: none'> | 60 | <span class='not-logged-in' style='display: none'> |
| 61 | - <%= _("<span class='login'>%s</span> <span class='or'>or</span> <span class='signup'>%s</span>") % [thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login'), link_to('<strong>' + _('Register') + '</strong>', :controller => 'account', :action => 'signup') ] %> | 61 | + <%= _("<span class='login'>%s</span> <span class='or'>or</span> <span class='signup'>%s</span>") % [thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login'), link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup') ] %> |
| 62 | <div id='inlineLoginBox' style='display: none;'> | 62 | <div id='inlineLoginBox' style='display: none;'> |
| 63 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> | 63 | <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> |
| 64 | </div> | 64 | </div> |
app/views/profile_editor/_person.rhtml
| @@ -2,6 +2,8 @@ | @@ -2,6 +2,8 @@ | ||
| 2 | 2 | ||
| 3 | <%= required_fields_message %> | 3 | <%= required_fields_message %> |
| 4 | 4 | ||
| 5 | - <%= required f.text_field(:email)%> | 5 | + <%= required f.text_field(:name) %> |
| 6 | + | ||
| 7 | + <%= required f.text_field(:email) %> | ||
| 6 | 8 | ||
| 7 | <%= render :partial => 'person_form', :locals => {:f => f} %> | 9 | <%= render :partial => 'person_form', :locals => {:f => f} %> |
app/views/profile_editor/_person_form.rhtml
| 1 | <% @person ||= @profile %> | 1 | <% @person ||= @profile %> |
| 2 | 2 | ||
| 3 | -<%= required f.text_field(:name) %> | ||
| 4 | - | ||
| 5 | <% optional_field(@person, 'nickname') do %> | 3 | <% optional_field(@person, 'nickname') do %> |
| 6 | - <%= f.text_field(:nickname, :maxlength => 16, :size => 30) %> | 4 | + <%= f.text_field(:nickname, :maxlength => 16, :size => 30, :rel => _('Nickname')) %> |
| 7 | <div> | 5 | <div> |
| 8 | <small><%= _('A short name by which you like to be known. Will be used in friends listings, community member listings etc.') %></small> | 6 | <small><%= _('A short name by which you like to be known. Will be used in friends listings, community member listings etc.') %></small> |
| 9 | </div> | 7 | </div> |
| 10 | <% end %> | 8 | <% end %> |
| 11 | 9 | ||
| 12 | -<%= optional_field(@person, 'description', f.text_area(:description, :rows => 5)) %> | 10 | +<%= optional_field(@person, 'description', f.text_area(:description, :rows => 5, :rel => _('Description'))) %> |
| 13 | <%= optional_field(@person, 'preferred_domain', select_preferred_domain(:profile_data)) %> | 11 | <%= optional_field(@person, 'preferred_domain', select_preferred_domain(:profile_data)) %> |
| 14 | -<%= optional_field(@person, 'contact_information', f.text_field(:contact_information)) %> | ||
| 15 | -<%= optional_field(@person, 'contact_phone', labelled_form_field(_('Home phone'), text_field(:profile_data, :contact_phone))) %> | ||
| 16 | -<%= optional_field(@person, 'cell_phone', f.text_field(:cell_phone)) %> | ||
| 17 | -<%= optional_field(@person, 'comercial_phone', f.text_field(:comercial_phone)) %> | 12 | +<%= optional_field(@person, 'contact_information', f.text_field(:contact_information, :rel => _('Contact information'))) %> |
| 13 | +<%= optional_field(@person, 'contact_phone', labelled_form_field(_('Home phone'), text_field(:profile_data, :contact_phone, :rel => _('Contact phone')))) %> | ||
| 14 | +<%= optional_field(@person, 'cell_phone', f.text_field(:cell_phone, :rel => _('Cell phone'))) %> | ||
| 15 | +<%= optional_field(@person, 'comercial_phone', f.text_field(:comercial_phone, :rel => _('Comercial phone'))) %> | ||
| 18 | <%= optional_field(@person, 'sex', f.radio_group(:profile_data, :sex, [ ['male',_('Male')], ['female',_('Female')] ])) %> | 16 | <%= optional_field(@person, 'sex', f.radio_group(:profile_data, :sex, [ ['male',_('Male')], ['female',_('Female')] ])) %> |
| 19 | <%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %> | 17 | <%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %> |
| 20 | -<%= optional_field(@person, 'nationality', f.text_field(:nationality)) %> | 18 | +<%= optional_field(@person, 'nationality', f.text_field(:nationality, :rel => _('Nationality'))) %> |
| 21 | <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %> | 19 | <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %> |
| 22 | -<%= optional_field(@person, 'state', f.text_field(:state)) %> | ||
| 23 | -<%= optional_field(@person, 'city', f.text_field(:city)) %> | ||
| 24 | -<%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code))) %> | ||
| 25 | -<%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address))) %> | 20 | +<%= optional_field(@person, 'state', f.text_field(:state, :rel => _('State'))) %> |
| 21 | +<%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %> | ||
| 22 | +<%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %> | ||
| 23 | +<%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> | ||
| 26 | 24 | ||
| 27 | <% optional_field(@person, 'schooling') do %> | 25 | <% optional_field(@person, 'schooling') do %> |
| 28 | <div class="formfieldline"> | 26 | <div class="formfieldline"> |
| @@ -47,18 +45,25 @@ | @@ -47,18 +45,25 @@ | ||
| 47 | <%= optional_field(@person, 'formation', select_area(_('Education'), 'profile_data', 'formation', {:class => 'type-select-full-line'})) %> | 45 | <%= optional_field(@person, 'formation', select_area(_('Education'), 'profile_data', 'formation', {:class => 'type-select-full-line'})) %> |
| 48 | 46 | ||
| 49 | <span id='profile_data_custom_formation_span' <%= "style='display:none'" if ! ['Others', nil].include?(@person.formation) %> > | 47 | <span id='profile_data_custom_formation_span' <%= "style='display:none'" if ! ['Others', nil].include?(@person.formation) %> > |
| 50 | - <%= optional_field(@person, 'custom_formation', f.text_field(:custom_formation)) %> | 48 | + <%= optional_field(@person, 'custom_formation', f.text_field(:custom_formation, :rel => _('Custom formation'))) %> |
| 51 | </span> | 49 | </span> |
| 52 | <%= observe_field 'profile_data_formation', :function =>'toggle_text_field("profile_data_formation", "profile_data_custom_formation_span")' %> | 50 | <%= observe_field 'profile_data_formation', :function =>'toggle_text_field("profile_data_formation", "profile_data_custom_formation_span")' %> |
| 53 | 51 | ||
| 54 | <%= optional_field(@person, 'area_of_study', select_area(_('Area of study'), 'profile_data', 'area_of_study', {:class => 'type-select-full-line'})) %> | 52 | <%= optional_field(@person, 'area_of_study', select_area(_('Area of study'), 'profile_data', 'area_of_study', {:class => 'type-select-full-line'})) %> |
| 55 | 53 | ||
| 56 | <span id='profile_data_custom_area_of_study_span' <%= "style='display:none'" if ! ['Others', nil].include?(@person.area_of_study) %> > | 54 | <span id='profile_data_custom_area_of_study_span' <%= "style='display:none'" if ! ['Others', nil].include?(@person.area_of_study) %> > |
| 57 | - <%= optional_field(@person, 'custom_area_of_study', f.text_field(:custom_area_of_study)) %> | 55 | + <%= optional_field(@person, 'custom_area_of_study', f.text_field(:custom_area_of_study, :rel => _('Custom area of study'))) %> |
| 58 | </span> | 56 | </span> |
| 59 | <%= observe_field 'profile_data_area_of_study', :function =>'toggle_text_field("profile_data_area_of_study", "profile_data_custom_area_of_study_span")' %> | 57 | <%= observe_field 'profile_data_area_of_study', :function =>'toggle_text_field("profile_data_area_of_study", "profile_data_custom_area_of_study_span")' %> |
| 60 | 58 | ||
| 61 | -<%= optional_field(@person, 'professional_activity', f.text_field(:professional_activity)) %> | ||
| 62 | -<%= optional_field(@person, 'organization', f.text_field(:organization)) %> | ||
| 63 | -<%= optional_field(@person, 'organization_website', f.text_field(:organization_website)) %> | 59 | +<%= optional_field(@person, 'professional_activity', f.text_field(:professional_activity, :rel => _('Professional activity'))) %> |
| 60 | +<%= optional_field(@person, 'organization', f.text_field(:organization, :rel => _('Organization'))) %> | ||
| 61 | +<%= optional_field(@person, 'organization_website', f.text_field(:organization_website, :rel => _('Organization website'))) %> | ||
| 64 | 62 | ||
| 63 | +<% optional_field(@person, 'image') do %> | ||
| 64 | + <div id="profile_choose_picture"> | ||
| 65 | + <% f.fields_for :image_builder, @person.image do |i| %> | ||
| 66 | + <%= file_field_or_thumbnail(_('Image:'), @person.image, i) %><span class="person_image_maxsize"><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %></span> | ||
| 67 | + <% end %> | ||
| 68 | + </div> | ||
| 69 | +<% end %> |
app/views/profile_editor/edit.rhtml
| @@ -6,12 +6,14 @@ | @@ -6,12 +6,14 @@ | ||
| 6 | 6 | ||
| 7 | <%= render :partial => partial_for_class(@profile.class), :locals => { :f => f } %> | 7 | <%= render :partial => partial_for_class(@profile.class), :locals => { :f => f } %> |
| 8 | 8 | ||
| 9 | + <% unless @profile.person? && @environment.active_person_fields.include?('image') %> | ||
| 9 | <div id="profile_change_picture"> | 10 | <div id="profile_change_picture"> |
| 10 | <h2><%= _('Change picture') %></h2> | 11 | <h2><%= _('Change picture') %></h2> |
| 11 | <% f.fields_for :image_builder, @profile.image do |i| %> | 12 | <% f.fields_for :image_builder, @profile.image do |i| %> |
| 12 | <%= file_field_or_thumbnail(_('Image:'), @profile.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %> | 13 | <%= file_field_or_thumbnail(_('Image:'), @profile.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %> |
| 13 | <% end %> | 14 | <% end %> |
| 14 | </div> | 15 | </div> |
| 16 | + <% end %> | ||
| 15 | 17 | ||
| 16 | <h2><%= _('Privacy options') %></h2> | 18 | <h2><%= _('Privacy options') %></h2> |
| 17 | 19 |
config/routes.rb
| @@ -20,6 +20,7 @@ ActionController::Routing::Routes.draw do |map| | @@ -20,6 +20,7 @@ ActionController::Routing::Routes.draw do |map| | ||
| 20 | # -- just remember to delete public/index.html. | 20 | # -- just remember to delete public/index.html. |
| 21 | # You can have the root of your site routed by hooking up '' | 21 | # You can have the root of your site routed by hooking up '' |
| 22 | map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } | 22 | map.connect '', :controller => "home", :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } |
| 23 | + map.home 'site/:action', :controller => 'home' | ||
| 23 | 24 | ||
| 24 | map.connect 'images/*stuff', :controller => 'not_found', :action => 'index' | 25 | map.connect 'images/*stuff', :controller => 'not_found', :action => 'index' |
| 25 | map.connect 'stylesheets/*stuff', :controller => 'not_found', :action => 'index' | 26 | map.connect 'stylesheets/*stuff', :controller => 'not_found', :action => 'index' |
features/signup.feature
| @@ -13,19 +13,19 @@ Feature: signup | @@ -13,19 +13,19 @@ Feature: signup | ||
| 13 | | Password | secret | | 13 | | Password | secret | |
| 14 | | Password confirmation | secret | | 14 | | Password confirmation | secret | |
| 15 | | Name | José da Silva | | 15 | | Name | José da Silva | |
| 16 | - And I press "Sign up" | 16 | + And I press "Create my account" |
| 17 | Then I should not be logged in | 17 | Then I should not be logged in |
| 18 | - And I should receive an e-mail on josesilva@example.com | 18 | + And I should receive an e-mail on josesilva@example.com |
| 19 | When I go to login page | 19 | When I go to login page |
| 20 | - And I fill in "Username" with "josesilva" | ||
| 21 | - And I fill in "Password" with "secret" | ||
| 22 | - And I press "Log in" | 20 | + And I fill in "Username" with "josesilva" |
| 21 | + And I fill in "Password" with "secret" | ||
| 22 | + And I press "Log in" | ||
| 23 | Then I should not be logged in | 23 | Then I should not be logged in |
| 24 | When José da Silva's account is activated | 24 | When José da Silva's account is activated |
| 25 | And I go to login page | 25 | And I go to login page |
| 26 | - And I fill in "Username" with "josesilva" | ||
| 27 | - And I fill in "Password" with "secret" | ||
| 28 | - And I press "Log in" | 26 | + And I fill in "Username" with "josesilva" |
| 27 | + And I fill in "Password" with "secret" | ||
| 28 | + And I press "Log in" | ||
| 29 | Then I should be logged in as "josesilva" | 29 | Then I should be logged in as "josesilva" |
| 30 | 30 | ||
| 31 | Scenario: be redirected if user goes to signup page and is logged | 31 | Scenario: be redirected if user goes to signup page and is logged |
| @@ -44,7 +44,7 @@ Feature: signup | @@ -44,7 +44,7 @@ Feature: signup | ||
| 44 | And I fill in "Username" with "josesilva" | 44 | And I fill in "Username" with "josesilva" |
| 45 | And I fill in "Password" with "secret" | 45 | And I fill in "Password" with "secret" |
| 46 | And I fill in "Password confirmation" with "secret" | 46 | And I fill in "Password confirmation" with "secret" |
| 47 | - And I press "Sign up" | 47 | + And I press "Create my account" |
| 48 | Then I should see "Name can't be blank" | 48 | Then I should see "Name can't be blank" |
| 49 | 49 | ||
| 50 | Scenario: user cannot change his name to empty string | 50 | Scenario: user cannot change his name to empty string |
No preview for this file type
No preview for this file type
399 Bytes
1.09 KB
1.12 KB
191 Bytes
777 Bytes
374 Bytes
public/stylesheets/application.css
| @@ -6420,33 +6420,384 @@ h1#agenda-title { | @@ -6420,33 +6420,384 @@ h1#agenda-title { | ||
| 6420 | 6420 | ||
| 6421 | /* Captcha */ | 6421 | /* Captcha */ |
| 6422 | 6422 | ||
| 6423 | -.comment_reply #recaptcha_area { | ||
| 6424 | - margin-bottom: 3px !important; | ||
| 6425 | -} | 6423 | +/* Colorbox */ |
| 6426 | 6424 | ||
| 6427 | -.comment_reply .recaptchatable tr td + td + td { | 6425 | +#cboxClose { |
| 6428 | display: none !important; | 6426 | display: none !important; |
| 6429 | } | 6427 | } |
| 6430 | 6428 | ||
| 6431 | -.comment_reply .recaptcha-container { | 6429 | +/* Signup interface {{{ */ |
| 6430 | + | ||
| 6431 | +#url-check { | ||
| 6432 | + margin: 0 0 -5px 0; | ||
| 6432 | width: 100%; | 6433 | width: 100%; |
| 6433 | - overflow: hidden; | 6434 | + text-align: right; |
| 6434 | } | 6435 | } |
| 6435 | 6436 | ||
| 6436 | -.comment_reply .recaptcha-container:hover { | ||
| 6437 | - overflow: visible; | 6437 | +#email-check, |
| 6438 | +#fake-check, | ||
| 6439 | +#password-check { | ||
| 6440 | + margin: -2px 171px -5px 0; | ||
| 6441 | + text-align: right; | ||
| 6442 | + clear: both; | ||
| 6443 | +} | ||
| 6444 | + | ||
| 6445 | +#email-check p, | ||
| 6446 | +#fake-check p, | ||
| 6447 | +#password-check p { | ||
| 6448 | + margin: 0; | ||
| 6449 | +} | ||
| 6450 | + | ||
| 6451 | +.available { | ||
| 6452 | + color: #88BD00; | ||
| 6453 | +} | ||
| 6454 | + | ||
| 6455 | +.unavailable { | ||
| 6456 | + color: #FFA000; | ||
| 6457 | +} | ||
| 6458 | + | ||
| 6459 | +.checking { | ||
| 6460 | + color: #4A4A4A; | ||
| 6461 | +} | ||
| 6462 | + | ||
| 6463 | +#email-check p, | ||
| 6464 | +#password-check p, | ||
| 6465 | +#url-check p { | ||
| 6466 | + margin: 0; | ||
| 6467 | + text-transform: lowercase; | ||
| 6468 | + font-size: 11px; | ||
| 6469 | + clear: both; | ||
| 6470 | +} | ||
| 6471 | + | ||
| 6472 | +.action-account-signup #main-content-wrapper-8 { | ||
| 6473 | + background: #ECECEC; | ||
| 6474 | +} | ||
| 6475 | + | ||
| 6476 | +@font-face { | ||
| 6477 | + font-family: droidserif; | ||
| 6478 | + src: url('/fonts/DroidSerif-Regular.eot'); /* EOT file for IE */ | ||
| 6479 | + src: local("DroidSerif-Regular"), url('/fonts/DroidSerif-Regular.ttf'); | ||
| 6480 | +} | ||
| 6481 | + | ||
| 6482 | +.action-account-signup #content .no-boxes h1 { | ||
| 6483 | + font-variant: normal; | ||
| 6484 | + border-bottom: 0; | ||
| 6485 | + color: #666666; | ||
| 6486 | + font-family: droidserif, serif; | ||
| 6487 | + font-weight: lighter; | ||
| 6488 | + text-align: center; | ||
| 6489 | + margin-top: 35px; | ||
| 6490 | + margin-left: 12px; | ||
| 6491 | +} | ||
| 6492 | + | ||
| 6493 | +.action-account-signup #wrap-1 label, | ||
| 6494 | +.action-account-signup #wrap-1 small, | ||
| 6495 | +.action-account-signup #wrap-1 #user_password, | ||
| 6496 | +.action-account-signup #wrap-1 #user_password_confirmation { | ||
| 6497 | + display: none; | ||
| 6498 | +} | ||
| 6499 | + | ||
| 6500 | +.action-account-signup #wrap-1 #signup-form-header { | ||
| 6501 | + background: #E3E3E3; | ||
| 6502 | + padding: 22px 0; | ||
| 6503 | + -moz-border-radius: 8px; | ||
| 6504 | + border-radius: 8px; | ||
| 6505 | + -webkit-border-radius: 8px; | ||
| 6506 | + margin: 60px auto 20px; | ||
| 6507 | + position: relative; | ||
| 6508 | + width: 563px; | ||
| 6509 | +} | ||
| 6510 | + | ||
| 6511 | +.action-account-signup #wrap-1 .formfield input.invalid_input { | ||
| 6512 | + border: 2px solid #FFA000; | ||
| 6513 | + background: #FFF; | ||
| 6514 | + padding: 5px 30px 8px 5px; | ||
| 6515 | +} | ||
| 6516 | + | ||
| 6517 | +.action-account-signup #wrap-1 .formfield input.valid_input { | ||
| 6518 | + border: 2px solid #88BD00; | ||
| 6519 | + background: #FFF; | ||
| 6520 | + padding: 5px 30px 8px 5px; | ||
| 6438 | } | 6521 | } |
| 6439 | 6522 | ||
| 6440 | -.comment_reply .recaptcha-container tr:hover td { | 6523 | +.action-account-signup #wrap-1 .formfield select, |
| 6524 | +.action-account-signup #wrap-1 .formfield textarea, | ||
| 6525 | +.action-account-signup #wrap-1 #profile_data_name, | ||
| 6526 | +.action-account-signup #wrap-1 .formfield input { | ||
| 6527 | + background: transparent url(/images/field-bg.png) left top no-repeat; | ||
| 6528 | + padding: 7px 3px 10px 7px; | ||
| 6529 | + height: 24px; | ||
| 6530 | + width: 335px; | ||
| 6531 | + color: #6d786e; | ||
| 6532 | + font-size: 20px; | ||
| 6533 | + font-family: droidserif, serif; | ||
| 6534 | + margin: 9px 14px 0; | ||
| 6535 | + border: 0; | ||
| 6536 | + padding-right: 30px; | ||
| 6537 | +} | ||
| 6538 | + | ||
| 6539 | +.action-account-signup #wrap-1 #user_login.checking, | ||
| 6540 | +.action-account-signup #wrap-1 #user_login.available, | ||
| 6541 | +.action-account-signup #wrap-1 #user_login.unavailable, | ||
| 6542 | +.action-account-signup #wrap-1 #user_email.checking, | ||
| 6543 | +.action-account-signup #wrap-1 #user_email.available, | ||
| 6544 | +.action-account-signup #wrap-1 #user_email.unavailable, | ||
| 6545 | +.action-account-signup #wrap-1 .formfield input.passwords_differ, | ||
| 6546 | +.action-account-signup #wrap-1 .formfield input.passwords_match { | ||
| 6547 | + border-width: 2px; | ||
| 6548 | + border-style: solid; | ||
| 6549 | + background-color: #fff; | ||
| 6550 | + background-position: right center; | ||
| 6551 | + background-repeat: no-repeat; | ||
| 6552 | + padding: 5px 30px 8px 5px; | ||
| 6553 | +} | ||
| 6554 | + | ||
| 6555 | +.action-account-signup #wrap-1 .formfield select.filled-in, | ||
| 6556 | +.action-account-signup #wrap-1 .formfield textarea.filled-in, | ||
| 6557 | +.action-account-signup #wrap-1 #profile_data_name.filled-in, | ||
| 6558 | +.action-account-signup #wrap-1 .formfield input.filled-in { | ||
| 6559 | + color: #4A4A4A; | ||
| 6560 | +} | ||
| 6561 | + | ||
| 6562 | +.action-account-signup #wrap-1 .formfield select { | ||
| 6563 | + height: auto; | ||
| 6564 | + padding-right: 3px; | ||
| 6565 | + width: 365px; | ||
| 6566 | +} | ||
| 6567 | + | ||
| 6568 | +.action-account-signup #wrap-1 .formfield .select-birth-date select { | ||
| 6569 | + width: 93px; | ||
| 6570 | + margin-right: 2px; | ||
| 6571 | + margin-left: 0; | ||
| 6572 | +} | ||
| 6573 | + | ||
| 6574 | +.webkit.action-account-signup #wrap-1 .formfield select { | ||
| 6575 | + background: #fff; | ||
| 6576 | +} | ||
| 6577 | + | ||
| 6578 | +.action-account-signup #wrap-1 .formfield textarea { | ||
| 6579 | + background: #fff; | ||
| 6580 | + height: 100px; | ||
| 6581 | + padding-right: 3px; | ||
| 6582 | + width: 365px; | ||
| 6583 | +} | ||
| 6584 | + | ||
| 6585 | +.action-account-signup #wrap-1 .formfield input[type=file] { | ||
| 6586 | + font-size: 12px; | ||
| 6587 | +} | ||
| 6588 | + | ||
| 6589 | +.action-account-signup #wrap-1 input[type=radio] { | ||
| 6590 | + height: auto; | ||
| 6591 | + margin: 0; | ||
| 6592 | + margin-left: 3px; | ||
| 6593 | +} | ||
| 6594 | + | ||
| 6595 | +.action-account-signup #wrap-1 .fieldgroup { | ||
| 6596 | + margin: 5px 10px; | ||
| 6597 | +} | ||
| 6598 | + | ||
| 6599 | +.action-account-signup #wrap-1 label[for=profile_data_sex_female], | ||
| 6600 | +.action-account-signup #wrap-1 label[for=profile_data_sex_male] { | ||
| 6601 | + color: #6d786e; | ||
| 6602 | + font-size: 20px; | ||
| 6603 | + font-family: droidserif; | ||
| 6604 | + text-transform: lowercase; | ||
| 6605 | + display: inline; | ||
| 6606 | + margin-left: 8px; | ||
| 6607 | +} | ||
| 6608 | + | ||
| 6609 | +.action-account-signup #wrap-1 label[for=profile_data_country], | ||
| 6610 | +.action-account-signup #wrap-1 label[for=profile_data_preferred_domain_id], | ||
| 6611 | +.action-account-signup #wrap-1 label[for=profile_data_birth_date_2i], | ||
| 6612 | +.action-account-signup #wrap-1 label[for=profile_data_birth_date_3i], | ||
| 6613 | +.action-account-signup #wrap-1 label[for=profile_data_schooling], | ||
| 6614 | +.action-account-signup #wrap-1 label[for=profile_data_formation], | ||
| 6615 | +.action-account-signup #wrap-1 label[for=profile_data_area_of_study], | ||
| 6616 | +.action-account-signup #wrap-1 label[for=profile_data_image_builder_uploaded_data] { | ||
| 6617 | + display: block; | ||
| 6618 | +} | ||
| 6619 | + | ||
| 6620 | +.action-account-signup #wrap-1 #profile_data_name { | ||
| 6621 | + padding-left: 10px; | ||
| 6622 | +} | ||
| 6623 | + | ||
| 6624 | +.action-account-signup #wrap-1 #user_login.unavailable, | ||
| 6625 | +.action-account-signup #wrap-1 #user_email.unavailable, | ||
| 6626 | +.action-account-signup #wrap-1 .formfield input.passwords_differ { | ||
| 6627 | + border-color: #FFA000; | ||
| 6628 | + background-image: url(/images/passwords_nomatch.png); | ||
| 6629 | +} | ||
| 6630 | + | ||
| 6631 | +.action-account-signup #wrap-1 #user_email.checking, | ||
| 6632 | +.action-account-signup #wrap-1 #user_login.checking { | ||
| 6633 | + border-color: #4A4A4A; | ||
| 6634 | + background-image: url(/images/login_checking.png); | ||
| 6635 | +} | ||
| 6636 | + | ||
| 6637 | +.action-account-signup #wrap-1 #user_login.available, | ||
| 6638 | +.action-account-signup #wrap-1 #user_email.available, | ||
| 6639 | +.action-account-signup #wrap-1 .formfield input.passwords_match { | ||
| 6640 | + border-color: #88BD00; | ||
| 6641 | + background-image: url(/images/passwords_match.png); | ||
| 6642 | +} | ||
| 6643 | + | ||
| 6644 | +#signup-domain { | ||
| 6645 | + float: left; | ||
| 6646 | + display: inline-block; | ||
| 6647 | + vertical-align: middle; | ||
| 6648 | + background: #EAEAEA; | ||
| 6649 | + border-right: 2px solid #FFFFFF; | ||
| 6650 | + border-top: 2px solid #FFFFFF; | ||
| 6651 | + border-left: 2px solid #CFCFCF; | ||
| 6652 | + border-bottom: 2px solid #CFCFCF; | ||
| 6653 | + line-height: 37px; | ||
| 6654 | + padding: 0px 7px; | ||
| 6655 | + color: #4A4A4A; | ||
| 6656 | + font-size: 20px; | ||
| 6657 | + font-family: droidserif; | ||
| 6658 | + text-transform: lowercase; | ||
| 6659 | + margin-left: 14px; | ||
| 6660 | +} | ||
| 6661 | + | ||
| 6662 | +.action-account-signup #wrap-1 #signup-form-header #user_login { | ||
| 6663 | + margin: 0; | ||
| 6664 | + width: 200px; | ||
| 6665 | + padding-right: 30px; | ||
| 6666 | +} | ||
| 6667 | + | ||
| 6668 | +#url-check { | ||
| 6669 | + width: 239px; | ||
| 6670 | +} | ||
| 6671 | + | ||
| 6672 | +#signup-login-field { | ||
| 6673 | + float: left; | ||
| 6674 | +} | ||
| 6675 | + | ||
| 6676 | +.action-account-signup #wrap-1 #signup-password, | ||
| 6677 | +.action-account-signup #wrap-1 #signup-password-confirmation, | ||
| 6678 | +.action-account-signup #wrap-1 #signup-login { | ||
| 6679 | + position: relative; | ||
| 6680 | +} | ||
| 6681 | + | ||
| 6682 | +.action-account-signup #wrap-1 small#signup-balloon, | ||
| 6683 | +.action-account-signup #wrap-1 small#password-balloon { | ||
| 6684 | + display: none; | ||
| 6685 | + width: 142px; | ||
| 6686 | + height: 69px; | ||
| 6687 | + color: #FFFFFF; | ||
| 6688 | + font-weight: bold; | ||
| 6689 | + font-size: 11px; | ||
| 6690 | + padding: 5px 10px 45px 10px; | ||
| 6691 | + margin: 0; | ||
| 6692 | + line-height: 1.5em; | ||
| 6693 | + background: transparent url(/images/orange-balloon.png) bottom center no-repeat; | ||
| 6694 | + position: absolute; | ||
| 6695 | + z-index: 2; | ||
| 6696 | + right: -40px; | ||
| 6697 | + top: -100px; | ||
| 6698 | +} | ||
| 6699 | + | ||
| 6700 | +.action-account-signup #wrap-1 .required-field label, | ||
| 6701 | +.action-account-signup #wrap-1 .formlabel { | ||
| 6702 | + color: #b4b9b5; | ||
| 6703 | + font-size: 20px; | ||
| 6704 | + text-transform: lowercase; | ||
| 6705 | + font-weight: normal; | ||
| 6706 | + margin-left: 15px; | ||
| 6707 | + font-family: droidserif; | ||
| 6708 | +} | ||
| 6709 | + | ||
| 6710 | +.action-account-signup #wrap-1 .required-field label::after { | ||
| 6711 | + content: ''; | ||
| 6712 | +} | ||
| 6713 | + | ||
| 6714 | +.action-account-signup #wrap-1 div.fieldWithErrors { | ||
| 6441 | background: transparent; | 6715 | background: transparent; |
| 6442 | } | 6716 | } |
| 6443 | 6717 | ||
| 6444 | -.comment_reply .recaptcha_image_cell { | ||
| 6445 | - background: transparent !important; | 6718 | +.person_image_maxsize { |
| 6719 | + margin: 0 18px; | ||
| 6720 | + font: 13px sans-serif; | ||
| 6721 | + color: #BABABA; | ||
| 6446 | } | 6722 | } |
| 6447 | 6723 | ||
| 6448 | -/* Colorbox */ | 6724 | +#terms-of-use-box { |
| 6725 | + margin: 20px 0 30px 40px; | ||
| 6726 | + color: #4A4A4A; | ||
| 6727 | +} | ||
| 6449 | 6728 | ||
| 6450 | -#cboxClose { | ||
| 6451 | - display: none !important; | 6729 | +#terms-of-use-box input[type=checkbox] { |
| 6730 | + border: 1px solid #FFA514; | ||
| 6731 | + background: #FFF; | ||
| 6732 | +} | ||
| 6733 | + | ||
| 6734 | +.action-account-signup #terms-of-use-box label { | ||
| 6735 | + display: inline; | ||
| 6736 | + font-size: 16px; | ||
| 6737 | +} | ||
| 6738 | + | ||
| 6739 | +.action-account-signup #terms-of-use-box label a { | ||
| 6740 | + color: #FF7F2A; | ||
| 6741 | +} | ||
| 6742 | + | ||
| 6743 | +.action-account-signup #content form input.button.submit { | ||
| 6744 | + border: 0; | ||
| 6745 | + padding: 8px 36px 12px; | ||
| 6746 | + background: transparent url(/images/orange-bg.png) left center repeat-x; | ||
| 6747 | + font-size: 17px; | ||
| 6748 | + font-family: droidserif; | ||
| 6749 | + color: #FFFFD5; | ||
| 6750 | + text-align: center; | ||
| 6751 | + text-shadow: #d45500 0 -1px 0; | ||
| 6752 | + border-radius: 7px; | ||
| 6753 | + -moz-border-radius: 7px; | ||
| 6754 | + -webkit-border-radius: 7px; | ||
| 6755 | + max-height: none; | ||
| 6756 | + height: 39px; | ||
| 6757 | +} | ||
| 6758 | + | ||
| 6759 | +.action-account-signup .no-boxes { | ||
| 6760 | + margin-left: 128px; | ||
| 6761 | + margin-right: 128px; | ||
| 6762 | +} | ||
| 6763 | + | ||
| 6764 | +#signup-form-profile { | ||
| 6765 | + margin: 30px 0 0 40px; | ||
| 6766 | +} | ||
| 6767 | + | ||
| 6768 | +.select-birth-date { | ||
| 6769 | + margin-left: 14px; | ||
| 6770 | +} | ||
| 6771 | + | ||
| 6772 | +#thanks-for-signing { | ||
| 6773 | + font-size: 15px; | ||
| 6774 | + text-align: center; | ||
| 6775 | +} | ||
| 6776 | + | ||
| 6777 | +.action-account-signup .formfieldline { | ||
| 6778 | + padding: 0; | ||
| 6452 | } | 6779 | } |
| 6780 | + | ||
| 6781 | +#thanks-for-signing { | ||
| 6782 | + text-align: left; | ||
| 6783 | +} | ||
| 6784 | + | ||
| 6785 | +#thanks-for-signing h3 { | ||
| 6786 | + color: #FF7F2A; | ||
| 6787 | + font-family: 'Liberation Sans', Arial, sans-serif; | ||
| 6788 | + font-size: 16px; | ||
| 6789 | + font-weight: normal; | ||
| 6790 | + text-align: center; | ||
| 6791 | +} | ||
| 6792 | + | ||
| 6793 | +#thanks-for-signing a { | ||
| 6794 | + color: #333; | ||
| 6795 | +} | ||
| 6796 | + | ||
| 6797 | +#thanks-for-signing h4 { | ||
| 6798 | + font-family: droidserif, serif; | ||
| 6799 | + color: #6D786E; | ||
| 6800 | + font-size: 20px; | ||
| 6801 | +} | ||
| 6802 | + | ||
| 6803 | +/* }}} */ |
test/functional/account_controller_test.rb
| @@ -666,6 +666,22 @@ class AccountControllerTest < Test::Unit::TestCase | @@ -666,6 +666,22 @@ class AccountControllerTest < Test::Unit::TestCase | ||
| 666 | assert_equal 'unavailable', assigns(:status_class) | 666 | assert_equal 'unavailable', assigns(:status_class) |
| 667 | end | 667 | end |
| 668 | 668 | ||
| 669 | + should 'check if e-mail is available on environment' do | ||
| 670 | + env = fast_create(Environment, :name => 'Environment test') | ||
| 671 | + @controller.expects(:environment).returns(env).at_least_once | ||
| 672 | + profile = create_user('mylogin', :email => 'mylogin@noosfero.org', :environment_id => fast_create(Environment).id) | ||
| 673 | + get :check_email, :address => 'mylogin@noosfero.org' | ||
| 674 | + assert_equal 'available', assigns(:status_class) | ||
| 675 | + end | ||
| 676 | + | ||
| 677 | + should 'check if e-mail is not available on environment' do | ||
| 678 | + env = fast_create(Environment, :name => 'Environment test') | ||
| 679 | + @controller.expects(:environment).returns(env).at_least_once | ||
| 680 | + profile = create_user('mylogin', :email => 'mylogin@noosfero.org', :environment_id => env) | ||
| 681 | + get :check_email, :address => 'mylogin@noosfero.org' | ||
| 682 | + assert_equal 'unavailable', assigns(:status_class) | ||
| 683 | + end | ||
| 684 | + | ||
| 669 | should 'merge user data with extra stuff from plugins' do | 685 | should 'merge user data with extra stuff from plugins' do |
| 670 | class Plugin1 < Noosfero::Plugin | 686 | class Plugin1 < Noosfero::Plugin |
| 671 | def user_data_extras | 687 | def user_data_extras |
| @@ -719,6 +735,42 @@ class AccountControllerTest < Test::Unit::TestCase | @@ -719,6 +735,42 @@ class AccountControllerTest < Test::Unit::TestCase | ||
| 719 | assert_redirected_to '/bli' | 735 | assert_redirected_to '/bli' |
| 720 | end | 736 | end |
| 721 | 737 | ||
| 738 | + should 'be able to upload an image' do | ||
| 739 | + new_user({}, :profile_data => { :image_builder => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') } }) | ||
| 740 | + assert_not_nil Person.last.image | ||
| 741 | + end | ||
| 742 | + | ||
| 743 | + should 'not be able to upload an image bigger than max size' do | ||
| 744 | + Image.any_instance.stubs(:size).returns(Image.attachment_options[:max_size] + 1024) | ||
| 745 | + new_user({}, :profile_data => { :image_builder => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') } }) | ||
| 746 | + assert_nil Person.last.image | ||
| 747 | + end | ||
| 748 | + | ||
| 749 | + should 'display error message when image has more than max size' do | ||
| 750 | + Image.any_instance.stubs(:size).returns(Image.attachment_options[:max_size] + 1024) | ||
| 751 | + new_user({}, :profile_data => { :image_builder => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') } }) | ||
| 752 | + assert_tag :tag => 'div', :attributes => { :class => 'errorExplanation', :id => 'errorExplanation' } | ||
| 753 | + end | ||
| 754 | + | ||
| 755 | + should 'not display error message when image has less than max size' do | ||
| 756 | + Image.any_instance.stubs(:size).returns(Image.attachment_options[:max_size] - 1024) | ||
| 757 | + new_user({}, :profile_data => { :image_builder => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') } }) | ||
| 758 | + assert_no_tag :tag => 'div', :attributes => { :class => 'errorExplanation', :id => 'errorExplanation' } | ||
| 759 | + end | ||
| 760 | + | ||
| 761 | + should 'not redirect when some file has errors' do | ||
| 762 | + Image.any_instance.stubs(:size).returns(Image.attachment_options[:max_size] + 1024) | ||
| 763 | + new_user({}, :profile_data => { :image_builder => { :uploaded_data => fixture_file_upload('/files/rails.png', 'image/png') } }) | ||
| 764 | + assert_response :success | ||
| 765 | + assert_template 'signup' | ||
| 766 | + end | ||
| 767 | + | ||
| 768 | + should 'remove useless user data on signup' do | ||
| 769 | + assert_nothing_raised do | ||
| 770 | + new_user :password_clear => 'nothing', :password_confirmation_clear => 'nothing' | ||
| 771 | + end | ||
| 772 | + end | ||
| 773 | + | ||
| 722 | protected | 774 | protected |
| 723 | def new_user(options = {}, extra_options ={}) | 775 | def new_user(options = {}, extra_options ={}) |
| 724 | data = {:profile_data => person_data} | 776 | data = {:profile_data => person_data} |
test/functional/admin_panel_controller_test.rb
| @@ -67,15 +67,11 @@ class AdminPanelControllerTest < Test::Unit::TestCase | @@ -67,15 +67,11 @@ class AdminPanelControllerTest < Test::Unit::TestCase | ||
| 67 | assert_tag :tag => 'a', :attributes => { :href => '/admin/admin_panel/message_for_disabled_enterprise' } | 67 | assert_tag :tag => 'a', :attributes => { :href => '/admin/admin_panel/message_for_disabled_enterprise' } |
| 68 | end | 68 | end |
| 69 | 69 | ||
| 70 | - should 'link to define terms of use' do | ||
| 71 | - get :index | ||
| 72 | - assert_tag :tag => 'a', :attributes => { :href => '/admin/admin_panel/terms_of_use' } | ||
| 73 | - end | ||
| 74 | - | ||
| 75 | should 'display form for editing site info' do | 70 | should 'display form for editing site info' do |
| 76 | get :site_info | 71 | get :site_info |
| 77 | assert_template 'site_info' | 72 | assert_template 'site_info' |
| 78 | assert_tag :tag => 'textarea', :attributes => { :name => 'environment[description]'} | 73 | assert_tag :tag => 'textarea', :attributes => { :name => 'environment[description]'} |
| 74 | + assert_tag :tag => 'textarea', :attributes => { :name => 'environment[terms_of_use]'} | ||
| 79 | end | 75 | end |
| 80 | 76 | ||
| 81 | should 'display form for editing message for disabled enterprise' do | 77 | should 'display form for editing message for disabled enterprise' do |
| @@ -84,12 +80,6 @@ class AdminPanelControllerTest < Test::Unit::TestCase | @@ -84,12 +80,6 @@ class AdminPanelControllerTest < Test::Unit::TestCase | ||
| 84 | assert_tag :tag => 'textarea', :attributes => { :name => 'environment[message_for_disabled_enterprise]'} | 80 | assert_tag :tag => 'textarea', :attributes => { :name => 'environment[message_for_disabled_enterprise]'} |
| 85 | end | 81 | end |
| 86 | 82 | ||
| 87 | - should 'display form for editing terms of use' do | ||
| 88 | - get :terms_of_use | ||
| 89 | - assert_template 'terms_of_use' | ||
| 90 | - assert_tag :tag => 'textarea', :attributes => { :name => 'environment[terms_of_use]'} | ||
| 91 | - end | ||
| 92 | - | ||
| 93 | should 'save site description' do | 83 | should 'save site description' do |
| 94 | post :site_info, :environment => { :description => "This is my new environment" } | 84 | post :site_info, :environment => { :description => "This is my new environment" } |
| 95 | assert_redirected_to :action => 'index' | 85 | assert_redirected_to :action => 'index' |
test/functional/home_controller_test.rb
| @@ -86,5 +86,11 @@ all_fixtures | @@ -86,5 +86,11 @@ all_fixtures | ||
| 86 | assert block.visible? | 86 | assert block.visible? |
| 87 | end | 87 | end |
| 88 | 88 | ||
| 89 | + should 'access terms of use of environment' do | ||
| 90 | + env = Environment.default | ||
| 91 | + env.update_attribute(:terms_of_use, 'Noosfero terms of use') | ||
| 92 | + get :terms | ||
| 93 | + assert_tag :content => /Noosfero terms of use/ | ||
| 94 | + end | ||
| 89 | 95 | ||
| 90 | end | 96 | end |
test/functional/profile_editor_controller_test.rb
| @@ -893,4 +893,22 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | @@ -893,4 +893,22 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | ||
| 893 | assert_tag :tag => 'input', :attributes => {:id => 'field_added_by_plugin', :value => 'value_of_field_added_by_plugin'} | 893 | assert_tag :tag => 'input', :attributes => {:id => 'field_added_by_plugin', :value => 'value_of_field_added_by_plugin'} |
| 894 | end | 894 | end |
| 895 | 895 | ||
| 896 | + should 'show image upload field from environment person fields' do | ||
| 897 | + env = Environment.default | ||
| 898 | + env.custom_person_fields = { 'image' => {'active' => 'true', 'required' => 'true'} } | ||
| 899 | + env.save! | ||
| 900 | + get :edit, :profile => profile.identifier | ||
| 901 | + assert_tag :tag => 'input', :attributes => { :name => 'profile_data[image_builder][uploaded_data]' } | ||
| 902 | + assert_no_tag :tag => 'div', :attributes => { :id => 'profile_change_picture' } | ||
| 903 | + end | ||
| 904 | + | ||
| 905 | + should 'show image upload field from profile editor' do | ||
| 906 | + env = Environment.default | ||
| 907 | + env.custom_person_fields = { } | ||
| 908 | + env.save! | ||
| 909 | + get :edit, :profile => profile.identifier | ||
| 910 | + assert_tag :tag => 'input', :attributes => { :name => 'profile_data[image_builder][uploaded_data]' } | ||
| 911 | + assert_tag :tag => 'div', :attributes => { :id => 'profile_change_picture' } | ||
| 912 | + end | ||
| 913 | + | ||
| 896 | end | 914 | end |
test/unit/person_test.rb
| @@ -64,7 +64,7 @@ class PersonTest < Test::Unit::TestCase | @@ -64,7 +64,7 @@ class PersonTest < Test::Unit::TestCase | ||
| 64 | 64 | ||
| 65 | should "have person info fields" do | 65 | should "have person info fields" do |
| 66 | p = Person.new(:environment => Environment.default) | 66 | p = Person.new(:environment => Environment.default) |
| 67 | - [ :name, :photo, :contact_information, :birth_date, :sex, :address, :city, :state, :country, :zip_code ].each do |i| | 67 | + [ :name, :photo, :contact_information, :birth_date, :sex, :address, :city, :state, :country, :zip_code, :image ].each do |i| |
| 68 | assert_respond_to p, i | 68 | assert_respond_to p, i |
| 69 | end | 69 | end |
| 70 | end | 70 | end |