Commit 68934890fe022493063c10ab0b2cab46b6703b46
Committed by
Antonio Terceiro
1 parent
4a8583d3
Exists in
master
and in
28 other branches
ActionItem1126: organization can change address
Showing
12 changed files
with
130 additions
and
20 deletions
Show diff stats
app/controllers/my_profile/profile_editor_controller.rb
| @@ -17,7 +17,7 @@ class ProfileEditorController < MyProfileController | @@ -17,7 +17,7 @@ class ProfileEditorController < MyProfileController | ||
| 17 | Profile.transaction do | 17 | Profile.transaction do |
| 18 | Image.transaction do | 18 | Image.transaction do |
| 19 | if profile.update_attributes!(params[:profile_data]) | 19 | if profile.update_attributes!(params[:profile_data]) |
| 20 | - redirect_to :action => 'index' | 20 | + redirect_to :action => 'index', :profile => profile.identifier |
| 21 | end | 21 | end |
| 22 | end | 22 | end |
| 23 | end | 23 | end |
app/models/environment.rb
| @@ -127,6 +127,7 @@ class Environment < ActiveRecord::Base | @@ -127,6 +127,7 @@ class Environment < ActiveRecord::Base | ||
| 127 | 'display_header_footer_explanation' => N_("Display explanation about header and footer"), | 127 | 'display_header_footer_explanation' => N_("Display explanation about header and footer"), |
| 128 | 'articles_dont_accept_comments_by_default' => N_("Articles don't accept comments by default"), | 128 | 'articles_dont_accept_comments_by_default' => N_("Articles don't accept comments by default"), |
| 129 | 'organizations_are_moderated_by_default' => N_("Organizations have moderated publication by default"), | 129 | 'organizations_are_moderated_by_default' => N_("Organizations have moderated publication by default"), |
| 130 | + 'enable_organization_url_change' => N_("Enable organizations to change its address"), | ||
| 130 | } | 131 | } |
| 131 | end | 132 | end |
| 132 | 133 |
app/models/person.rb
| @@ -12,6 +12,15 @@ class Person < Profile | @@ -12,6 +12,15 @@ class Person < Profile | ||
| 12 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } | 12 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } |
| 13 | end | 13 | end |
| 14 | 14 | ||
| 15 | + # Sets the identifier for this person. Raises an exception when called on a | ||
| 16 | + # existing person (since peoples' identifiers cannot be changed) | ||
| 17 | + def identifier=(value) | ||
| 18 | + unless self.new_record? | ||
| 19 | + raise ArgumentError.new(_('An existing person cannot be renamed.')) | ||
| 20 | + end | ||
| 21 | + self[:identifier] = value | ||
| 22 | + end | ||
| 23 | + | ||
| 15 | settings_items :last_lang, :type => :string | 24 | settings_items :last_lang, :type => :string |
| 16 | def last_lang | 25 | def last_lang |
| 17 | if self.data[:last_lang].nil? or self.data[:last_lang].empty? | 26 | if self.data[:last_lang].nil? or self.data[:last_lang].empty? |
app/models/profile.rb
| @@ -194,15 +194,6 @@ class Profile < ActiveRecord::Base | @@ -194,15 +194,6 @@ class Profile < ActiveRecord::Base | ||
| 194 | end | 194 | end |
| 195 | @top_level_articles ||= Article.top_level_for(self) | 195 | @top_level_articles ||= Article.top_level_for(self) |
| 196 | end | 196 | end |
| 197 | - | ||
| 198 | - # Sets the identifier for this profile. Raises an exception when called on a | ||
| 199 | - # existing profile (since profiles cannot be renamed) | ||
| 200 | - def identifier=(value) | ||
| 201 | - unless self.new_record? | ||
| 202 | - raise ArgumentError.new(_('An existing profile cannot be renamed.')) | ||
| 203 | - end | ||
| 204 | - self[:identifier] = value | ||
| 205 | - end | ||
| 206 | 197 | ||
| 207 | def self.is_available?(identifier) | 198 | def self.is_available?(identifier) |
| 208 | !(identifier =~ IDENTIFIER_FORMAT).nil? && !RESERVED_IDENTIFIERS.include?(identifier) && Profile.find(:first, :conditions => ['environment_id = ? and identifier = ?', Environment.default.id, identifier]).nil? | 199 | !(identifier =~ IDENTIFIER_FORMAT).nil? && !RESERVED_IDENTIFIERS.include?(identifier) && Profile.find(:first, :conditions => ['environment_id = ? and identifier = ?', Environment.default.id, identifier]).nil? |
app/views/profile_editor/_organization.rhtml
| @@ -2,14 +2,59 @@ | @@ -2,14 +2,59 @@ | ||
| 2 | 2 | ||
| 3 | <%= required_fields_message if @profile.required_fields.any? %> | 3 | <%= required_fields_message if @profile.required_fields.any? %> |
| 4 | 4 | ||
| 5 | +<% if @environment.enabled?('enable_organization_url_change') %> | ||
| 6 | + <script type="text/javascript"> | ||
| 7 | + function updateUrlField(name_field, id) { | ||
| 8 | + url_field = $(id); | ||
| 9 | + url_field.value = convToValidIdentifier(name_field.value, "-"); | ||
| 10 | + warn_value_change(url_field); | ||
| 11 | + } | ||
| 12 | + </script> | ||
| 13 | +<% end %> | ||
| 14 | + | ||
| 5 | <div class="formfieldline"> | 15 | <div class="formfieldline"> |
| 6 | <label class="formlabel" for="profile_data_nickname"><%= _('Display name') %></label> | 16 | <label class="formlabel" for="profile_data_nickname"><%= _('Display name') %></label> |
| 7 | <div class="formfield type-text"> | 17 | <div class="formfield type-text"> |
| 8 | - <%= text_field_tag 'profile_data[nickname]', @profile_data.nickname, :id => 'profile_data_nickname', :size => 30, :maxlength => 16 %> | 18 | + <%= text_field_tag 'profile_data[nickname]', @profile_data.nickname, :id => 'profile_data_nickname', :size => 30, :maxlength => 16, :onchange => (@environment.enabled?('enable_organization_url_change') ? "updateUrlField(this, 'profile_data_identifier')" : "") %> |
| 9 | <em><%= _('A short name by which the organization is know.')%></em> | 19 | <em><%= _('A short name by which the organization is know.')%></em> |
| 20 | + </div> | ||
| 10 | </div> | 21 | </div> |
| 11 | 22 | ||
| 12 | - </div> | 23 | +<% if @environment.enabled?('enable_organization_url_change') %> |
| 24 | + <script type="text/javascript"> | ||
| 25 | + function submit_button() { | ||
| 26 | + return $("profile_data_identifier").form.select("input.submit")[0]; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + function warn_value_change(field) { | ||
| 30 | + new Effect.Highlight($("profile-identifier-formitem"), {duration:3}); | ||
| 31 | + $("identifier-change-confirmation").show(); | ||
| 32 | + submit_button().disable(); | ||
| 33 | + submit_button().addClassName("disabled"); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + function hide_warning() { | ||
| 37 | + submit_button().enable(); | ||
| 38 | + submit_button().removeClassName("disabled"); | ||
| 39 | + $("identifier-change-confirmation").hide() | ||
| 40 | + } | ||
| 41 | + </script> | ||
| 42 | + | ||
| 43 | + <%= hidden_field_tag 'old_profile_identifier', @profile.identifier %> | ||
| 44 | + <div id="profile-identifier-formitem"> | ||
| 45 | + <%= labelled_form_field( _('Address'), | ||
| 46 | + '<code>' + url_for(profile.url).gsub(/#{profile.identifier}$/, '') + | ||
| 47 | + text_field(:profile_data, :identifier, :onchange => "warn_value_change(this)", :size => 15) + '</code>' + | ||
| 48 | + content_tag('div', '<strong>' + _('WARNING:') + '</strong> ' + _("the address was changed, this might break any external links to this profile and articles in this profile, you really want to change? ") + | ||
| 49 | + '<div>' + button_to_function(:ok, _("Yes"), 'hide_warning()') + ' ' + | ||
| 50 | + button_to_function(:cancel, _('No'), '$("profile_data_identifier").value = $("old_profile_identifier").value; hide_warning()') + '</div>', | ||
| 51 | + :id => 'identifier-change-confirmation' | ||
| 52 | + ) | ||
| 53 | + ) | ||
| 54 | + %> | ||
| 55 | + </div> | ||
| 56 | +<% end %> | ||
| 57 | + | ||
| 13 | <%= f.text_field(:acronym) %> | 58 | <%= f.text_field(:acronym) %> |
| 14 | <%= f.text_field(:foundation_year) %> | 59 | <%= f.text_field(:foundation_year) %> |
| 15 | <%= optional_field(@profile, 'contact_person', f.text_field(:contact_person)) %> | 60 | <%= optional_field(@profile, 'contact_person', f.text_field(:contact_person)) %> |
public/javascripts/application.js
| @@ -29,6 +29,11 @@ function focus_first_field() { | @@ -29,6 +29,11 @@ function focus_first_field() { | ||
| 29 | 29 | ||
| 30 | /* * * Convert a string to a valid login name * * */ | 30 | /* * * Convert a string to a valid login name * * */ |
| 31 | function convToValidLogin( str ) { | 31 | function convToValidLogin( str ) { |
| 32 | + return convToValidIdentifier(str, '') | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +/* * * Convert a string to a valid login name * * */ | ||
| 36 | +function convToValidIdentifier( str, sep ) { | ||
| 32 | return str.toLowerCase() | 37 | return str.toLowerCase() |
| 33 | .replace( /@.*$/, "" ) | 38 | .replace( /@.*$/, "" ) |
| 34 | .replace( /á|à|ã|â/g, "a" ) | 39 | .replace( /á|à|ã|â/g, "a" ) |
| @@ -38,7 +43,7 @@ function convToValidLogin( str ) { | @@ -38,7 +43,7 @@ function convToValidLogin( str ) { | ||
| 38 | .replace( /ú|ũ|ü/g, "u" ) | 43 | .replace( /ú|ũ|ü/g, "u" ) |
| 39 | .replace( /ñ/g, "n" ) | 44 | .replace( /ñ/g, "n" ) |
| 40 | .replace( /ç/g, "c" ) | 45 | .replace( /ç/g, "c" ) |
| 41 | - .replace( /[^-_a-z0-9]+/g, "" ) | 46 | + .replace( /[^-_a-z0-9]+/g, sep ) |
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | document.observe("dom:loaded", function() { | 49 | document.observe("dom:loaded", function() { |
public/stylesheets/button.css
public/stylesheets/controller_profile_editor.css
| @@ -31,6 +31,21 @@ | @@ -31,6 +31,21 @@ | ||
| 31 | -moz-border-radius: 3px; | 31 | -moz-border-radius: 3px; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | +#identifier-change-confirmation { | ||
| 35 | + background-color: #EE4444; | ||
| 36 | + padding: 3px 20px 3px 20px; | ||
| 37 | + margin: 5px 30px 10px 30px; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +#identifier-change-confirmation div { | ||
| 41 | + text-align: right; | ||
| 42 | + padding: 0px 10px 5px 0px; | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +code input { | ||
| 46 | + font-family: monospace; | ||
| 47 | +} | ||
| 48 | + | ||
| 34 | a.control-panel-groups { background-image: url(../images/control-panel/system-users.png) } | 49 | a.control-panel-groups { background-image: url(../images/control-panel/system-users.png) } |
| 35 | .msie6 a.control-panel-groups { background-image: url(../images/control-panel/system-users.gif) } | 50 | .msie6 a.control-panel-groups { background-image: url(../images/control-panel/system-users.gif) } |
| 36 | 51 | ||
| @@ -87,3 +102,4 @@ a.control-panel-validation {background-image: url(../images/control-panel/applic | @@ -87,3 +102,4 @@ a.control-panel-validation {background-image: url(../images/control-panel/applic | ||
| 87 | 102 | ||
| 88 | a.control-panel-mail {background-image: url(../images/control-panel/email.png)} | 103 | a.control-panel-mail {background-image: url(../images/control-panel/email.png)} |
| 89 | .msie6 a.control-panel-mail {background-image: url(../images/control-panel/email.gif)} | 104 | .msie6 a.control-panel-mail {background-image: url(../images/control-panel/email.gif)} |
| 105 | + |
test/functional/profile_editor_controller_test.rb
| @@ -724,5 +724,37 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | @@ -724,5 +724,37 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | ||
| 724 | assert_no_tag :tag => 'div', :attributes => { :id => 'activation_enterprise' }, :descendant => {:tag => 'form', :attributes => {:action => '/account/activation_question'}} | 724 | assert_no_tag :tag => 'div', :attributes => { :id => 'activation_enterprise' }, :descendant => {:tag => 'form', :attributes => {:action => '/account/activation_question'}} |
| 725 | end | 725 | end |
| 726 | 726 | ||
| 727 | + should 'have url field for identifier when environment allows' do | ||
| 728 | + c = Community.create!(:name => 'test community', :identifier => 'test_comm') | ||
| 729 | + env = c.environment | ||
| 730 | + env.enable('enable_organization_url_change') | ||
| 731 | + env.save! | ||
| 732 | + | ||
| 733 | + get :edit, :profile => c.identifier | ||
| 734 | + assert_tag :tag => 'div', | ||
| 735 | + :attributes => { :class => 'formfield type-text' }, | ||
| 736 | + :content => /https?:\/\/#{c.environment.default_hostname}\//, | ||
| 737 | + :descendant => {:tag => 'input', :attributes => {:id => 'profile_data_identifier'} } | ||
| 738 | + end | ||
| 739 | + | ||
| 740 | + should 'not have url field for identifier when environment not allows' do | ||
| 741 | + c = Community.create!(:name => 'test community', :identifier => 'test_comm') | ||
| 742 | + env = c.environment | ||
| 743 | + env.disable('enable_organization_url_change') | ||
| 744 | + env.save! | ||
| 745 | + | ||
| 746 | + get :edit, :profile => c.identifier | ||
| 747 | + assert_no_tag :tag => 'div', | ||
| 748 | + :attributes => { :class => 'formfield type-text' }, | ||
| 749 | + :content => /https?:\/\/#{c.environment.default_hostname}\//, | ||
| 750 | + :descendant => {:tag => 'input', :attributes => {:id => 'profile_data_identifier'} } | ||
| 751 | + end | ||
| 752 | + | ||
| 753 | + should 'redirect to new url when is changed' do | ||
| 754 | + c = Community.create!(:name => 'test community', :identifier => 'test_comm') | ||
| 755 | + post :edit, :profile => c.identifier, :profile_data => {:identifier => 'new_address'} | ||
| 756 | + assert_response :redirect | ||
| 757 | + assert_redirected_to :action => 'index', :profile => 'new_address' | ||
| 758 | + end | ||
| 727 | 759 | ||
| 728 | end | 760 | end |
test/unit/organization_test.rb
| @@ -232,4 +232,11 @@ class OrganizationTest < Test::Unit::TestCase | @@ -232,4 +232,11 @@ class OrganizationTest < Test::Unit::TestCase | ||
| 232 | assert p.has_permission?(:moderate_comments, o) | 232 | assert p.has_permission?(:moderate_comments, o) |
| 233 | end | 233 | end |
| 234 | 234 | ||
| 235 | + should 'be able to change identifier' do | ||
| 236 | + o = Organization.create!(:name => 'Test Org', :identifier => 'test_org') | ||
| 237 | + assert_nothing_raised do | ||
| 238 | + o.identifier = 'test_org_new_url' | ||
| 239 | + end | ||
| 240 | + end | ||
| 241 | + | ||
| 235 | end | 242 | end |
test/unit/person_test.rb
| @@ -574,4 +574,11 @@ class PersonTest < Test::Unit::TestCase | @@ -574,4 +574,11 @@ class PersonTest < Test::Unit::TestCase | ||
| 574 | end | 574 | end |
| 575 | end | 575 | end |
| 576 | 576 | ||
| 577 | + should 'not rename' do | ||
| 578 | + assert_valid p = create_user('test_user').person | ||
| 579 | + assert_raise ArgumentError do | ||
| 580 | + p.identifier = 'other_person_name' | ||
| 581 | + end | ||
| 582 | + end | ||
| 583 | + | ||
| 577 | end | 584 | end |
test/unit/profile_test.rb
| @@ -72,13 +72,6 @@ class ProfileTest < Test::Unit::TestCase | @@ -72,13 +72,6 @@ class ProfileTest < Test::Unit::TestCase | ||
| 72 | assert_equal Environment.default, e | 72 | assert_equal Environment.default, e |
| 73 | end | 73 | end |
| 74 | 74 | ||
| 75 | - def test_cannot_rename | ||
| 76 | - assert_valid p = Profile.create(:name => 'new_profile', :identifier => 'new_profile') | ||
| 77 | - assert_raise ArgumentError do | ||
| 78 | - p.identifier = 'other_profile' | ||
| 79 | - end | ||
| 80 | - end | ||
| 81 | - | ||
| 82 | should 'provide access to home page' do | 75 | should 'provide access to home page' do |
| 83 | profile = Profile.create!(:identifier => 'newprofile', :name => 'New Profile') | 76 | profile = Profile.create!(:identifier => 'newprofile', :name => 'New Profile') |
| 84 | assert_kind_of Article, profile.home_page | 77 | assert_kind_of Article, profile.home_page |