diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 2fce8c079..9692cc778 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -22,9 +22,9 @@ class UsersController < ApplicationController def update password_changed = false - if u = params[:user] - @user = current_user + @user = current_user + if u = params[:user] u.delete(:password) if u[:password].blank? u.delete(:password_confirmation) if u[:password].blank? and u[:password_confirmation].blank? u.delete(:language) if u[:language].blank? @@ -57,6 +57,8 @@ class UsersController < ApplicationController flash[:error] = I18n.t 'users.update.unconfirmed_email_not_changed' end end + elsif aspect_order = params[:reorder_aspects] + @user.reorder_aspects(aspect_order) end respond_to do |format| diff --git a/app/models/aspect.rb b/app/models/aspect.rb index 0955e637f..feeec4af1 100644 --- a/app/models/aspect.rb +++ b/app/models/aspect.rb @@ -15,7 +15,7 @@ class Aspect < ActiveRecord::Base validates_length_of :name, :maximum => 20 validates_uniqueness_of :name, :scope => :user_id, :case_sensitive => false - attr_accessible :name, :contacts_visible + attr_accessible :name, :contacts_visible, :order_id before_validation do name.strip! diff --git a/app/models/user.rb b/app/models/user.rb index fdd391b7f..b6be53b8a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -34,7 +34,7 @@ class User < ActiveRecord::Base has_many :invitations_from_me, :class_name => 'Invitation', :foreign_key => :sender_id, :dependent => :destroy has_many :invitations_to_me, :class_name => 'Invitation', :foreign_key => :recipient_id, :dependent => :destroy - has_many :aspects + has_many :aspects, :order => 'order_id ASC' has_many :aspect_memberships, :through => :aspects has_many :contacts has_many :contact_people, :through => :contacts, :source => :person @@ -394,4 +394,12 @@ class User < ActiveRecord::Base self.confirm_email_token = unconfirmed_email ? ActiveSupport::SecureRandom.hex(15) : nil end end + + def reorder_aspects(aspect_order) + i = 0 + aspect_order.each do |id| + self.aspects.find(id).update_attributes({ :order_id => i }) + i += 1 + end + end end diff --git a/app/views/aspects/_aspect_listings.haml b/app/views/aspects/_aspect_listings.haml index 82219dcc8..7d25d5dfa 100644 --- a/app/views/aspects/_aspect_listings.haml +++ b/app/views/aspects/_aspect_listings.haml @@ -11,7 +11,7 @@ %ul.sub_nav - for aspect in all_aspects - %li{:class => ("active" if params["a_id"].to_i == aspect.id)} + %li{:id => aspect.id, :class => ("active" if params["a_id"].to_i == aspect.id)} .edit = link_to image_tag("icons/pencil.svg", :height => 12), edit_aspect_path(aspect), :rel => "facebox" @@ -36,3 +36,15 @@ = only_sharing_count = t('contacts.index.only_sharing_with_me') + :javascript + $(document).ready(function() { + jQuery('#aspect_nav.left_nav .all_aspects .sub_nav').sortable({ + items: 'li[id]', + update: function(event, ui) { + var order = jQuery(this).sortable('toArray'); + var obj = { 'reorder_aspects': order, 'authenticity_token': '#{form_authenticity_token}', '_method': 'put' }; + jQuery.ajax('/user', { type: 'post', dataType: 'script', data: obj }); + } + }); + }); + diff --git a/db/migrate/20110710102747_add_order_id_to_aspects.rb b/db/migrate/20110710102747_add_order_id_to_aspects.rb new file mode 100644 index 000000000..ab70b1d32 --- /dev/null +++ b/db/migrate/20110710102747_add_order_id_to_aspects.rb @@ -0,0 +1,9 @@ +class AddOrderIdToAspects < ActiveRecord::Migration + def self.up + add_column :aspects, :order_id, :integer + end + + def self.down + remove_column :aspects, :order_id + end +end diff --git a/db/schema.rb b/db/schema.rb index 4ce633fcb..02a0cb94c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20110707234802) do +ActiveRecord::Schema.define(:version => 20110710102747) do create_table "aspect_memberships", :force => true do |t| t.integer "aspect_id", :null => false @@ -40,6 +40,7 @@ ActiveRecord::Schema.define(:version => 20110707234802) do t.datetime "created_at" t.datetime "updated_at" t.boolean "contacts_visible", :default => true, :null => false + t.integer "order_id" end add_index "aspects", ["user_id", "contacts_visible"], :name => "index_aspects_on_user_id_and_contacts_visible" diff --git a/public/javascripts/vendor/jquery-ui-1.8.9.custom.min.js b/public/javascripts/vendor/jquery-ui-1.8.9.custom.min.js index c93e18a71..72b4f512c 100755 --- a/public/javascripts/vendor/jquery-ui-1.8.9.custom.min.js +++ b/public/javascripts/vendor/jquery-ui-1.8.9.custom.min.js @@ -342,4 +342,101 @@ var i={};i[g]=(f=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+e;a.animate(i,{q */ (function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('
').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); b.dequeue()})})}})(jQuery); -; \ No newline at end of file +; +/* + * jQuery UI Sortable 1.8.9 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Sortables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function($,undefined){$.widget("ui.sortable",$.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:'auto',cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:'> *',opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000},_create:function(){var o=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?(/left|right/).test(this.items[0].item.css('float')):false;this.offset=this.element.offset();this._mouseInit();},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var i=this.items.length-1;i>=0;i--) +this.items[i].item.removeData("sortable-item");return this;},_setOption:function(key,value){if(key==="disabled"){this.options[key]=value;this.widget() +[value?"addClass":"removeClass"]("ui-sortable-disabled");}else{$.Widget.prototype._setOption.apply(this,arguments);}},_mouseCapture:function(event,overrideHandle){if(this.reverting){return false;} +if(this.options.disabled||this.options.type=='static')return false;this._refreshItems(event);var currentItem=null,self=this,nodes=$(event.target).parents().each(function(){if($.data(this,'sortable-item')==self){currentItem=$(this);return false;}});if($.data(event.target,'sortable-item')==self)currentItem=$(event.target);if(!currentItem)return false;if(this.options.handle&&!overrideHandle){var validHandle=false;$(this.options.handle,currentItem).find("*").andSelf().each(function(){if(this==event.target)validHandle=true;});if(!validHandle)return false;} +this.currentItem=currentItem;this._removeCurrentsFromItems();return true;},_mouseStart:function(event,overrideHandle,noActivation){var o=this.options,self=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(event);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");$.extend(this.offset,{click:{left:event.pageX-this.offset.left,top:event.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(event);this.originalPageX=event.pageX;this.originalPageY=event.pageY;(o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt));this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};if(this.helper[0]!=this.currentItem[0]){this.currentItem.hide();} +this._createPlaceholder();if(o.containment) +this._setContainment();if(o.cursor){if($('body').css("cursor"))this._storedCursor=$('body').css("cursor");$('body').css("cursor",o.cursor);} +if(o.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",o.opacity);} +if(o.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",o.zIndex);} +if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!='HTML') +this.overflowOffset=this.scrollParent.offset();this._trigger("start",event,this._uiHash());if(!this._preserveHelperProportions) +this._cacheHelperProportions();if(!noActivation){for(var i=this.containers.length-1;i>=0;i--){this.containers[i]._trigger("activate",event,self._uiHash(this));}} +if($.ui.ddmanager) +$.ui.ddmanager.current=this;if($.ui.ddmanager&&!o.dropBehaviour) +$.ui.ddmanager.prepareOffsets(this,event);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(event);return true;},_mouseDrag:function(event){this.position=this._generatePosition(event);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs;} +if(this.options.scroll){var o=this.options,scrolled=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!='HTML'){if((this.overflowOffset.top+this.scrollParent[0].offsetHeight)-event.pageY