From b3ec4d10c2b7beef7e7e95c3ea106b2bbb41ba94 Mon Sep 17 00:00:00 2001
From: danielvincent <danielgrippi@gmail.com>
Date: Sat, 20 Nov 2010 21:54:03 -0800
Subject: [PATCH] user can now remove contact from aspects on contact's profile
 page.  a contact's posts are retained in a given aspect reflecting the
 duration of said contact's inclusion.

---
 app/controllers/aspects_controller.rb       | 21 ++++-----
 app/models/aspect.rb                        |  2 +-
 app/models/contact.rb                       |  1 -
 app/models/user.rb                          | 37 ++++++++--------
 app/views/people/_profile_sidebar.html.haml | 21 +++++++--
 app/views/users/getting_started.html.haml   | 19 ++++----
 public/stylesheets/sass/application.sass    | 18 ++++++--
 spec/controllers/aspects_controller_spec.rb | 22 ++++++----
 spec/models/aspect_spec.rb                  | 48 ++++++++++-----------
 spec/models/contact_spec.rb                 |  6 ---
 10 files changed, 108 insertions(+), 87 deletions(-)

diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb
index 3fa87c0cc8..d6619b4ce4 100644
--- a/app/controllers/aspects_controller.rb
+++ b/app/controllers/aspects_controller.rb
@@ -51,7 +51,11 @@ class AspectsController < ApplicationController
       render :file => "#{Rails.root}/public/404.html", :layout => false, :status => 404
     else
       @aspect_contacts = @aspect.contacts
-      @posts           = current_user.visible_posts( :by_members_of => @aspect, :_type => "StatusMessage" ).paginate :per_page => 15, :order => 'created_at DESC'
+      #@posts           = current_user.visible_posts( :by_members_of => @aspect, :_type => "StatusMessage" ).paginate :per_page => 15, :order => 'created_at DESC'
+      @posts           = @aspect.posts.find_all_by__type("StatusMessage", :order => 'created_at desc').paginate :per_page => 15
+
+      pp @aspect.post_ids
+
       respond_with @aspect
     end
   end
@@ -97,15 +101,12 @@ class AspectsController < ApplicationController
   end
 
   def remove_from_aspect
-    if current_user.delete_person_from_aspect( params[:person_id], params[:aspect_id])
-      flash[:notice] =  I18n.t 'aspects.remove_from_aspect.success'
-    else 
-      flash[:error] =  I18n.t 'aspects.remove_from_aspect.failure'
-    end
-    if params[:manage]
-      redirect_to aspects_manage_path
-    else
-      redirect_to aspect_path(params[:aspect_id])
+    begin current_user.delete_person_from_aspect(params[:person_id], params[:aspect_id])
+      flash.now[:notice] = I18n.t 'aspects.remove_from_aspect.success'
+      render :nothing => true, :status => 200
+    rescue Exception => e
+      flash.now[:error] = I18n.t 'aspects.remove_from_aspect.failure'
+      render :text => e, :status => 403
     end
   end
 end
diff --git a/app/models/aspect.rb b/app/models/aspect.rb
index 21c10cb246..e9671a442e 100644
--- a/app/models/aspect.rb
+++ b/app/models/aspect.rb
@@ -9,7 +9,7 @@ class Aspect
   key :request_ids, Array
   key :post_ids,    Array
 
-  many :contacts,   :foreign_key => 'aspect_ids', :class_name => 'Contact'
+  many :contacts, :foreign_key => 'aspect_ids', :class_name => 'Contact'
   many :requests, :in => :request_ids, :class_name => 'Request'
   many :posts,    :in => :post_ids,    :class_name => 'Post'
 
diff --git a/app/models/contact.rb b/app/models/contact.rb
index 5aef552926..8e7ddfc9be 100644
--- a/app/models/contact.rb
+++ b/app/models/contact.rb
@@ -13,6 +13,5 @@ class Contact
 
   key :aspect_ids, Array, :typecast => 'ObjectId'  
   many :aspects, :in => :aspect_ids, :class_name => 'Aspect'
-  validates_presence_of :aspects
  
 end
diff --git a/app/models/user.rb b/app/models/user.rb
index 01862c09f9..2698041117 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -98,40 +98,39 @@ class User
   end
 
   def move_contact(opts = {})
-    return true if opts[:to] == opts[:from]
-    if opts[:person_id] && opts[:to] && opts[:from]
-      from_aspect = self.aspects.first(:_id => opts[:from])
-      posts_to_move = from_aspect.posts.find_all_by_person_id(opts[:person_id])
-      if add_person_to_aspect(opts[:person_id], opts[:to], :posts => posts_to_move)
-        delete_person_from_aspect(opts[:person_id], opts[:from], :posts => posts_to_move)
-        return true
+    if opts[:to] == opts[:from]
+      true
+    elsif opts[:person_id] && opts[:to] && opts[:from]
+      from_aspect = self.aspects.find_by_id(opts[:from])
+
+      if add_person_to_aspect(opts[:person_id], opts[:to])
+        delete_person_from_aspect(opts[:person_id], opts[:from])
       end
     end
-    false
   end
 
-  def add_person_to_aspect(person_id, aspect_id, opts = {})
+  def add_person_to_aspect(person_id, aspect_id)
     contact = contact_for(Person.find(person_id))
     raise "Can not add person to an aspect you do not own" unless aspect = self.aspects.find_by_id(aspect_id)
     raise "Can not add person you are not connected to" unless contact
     raise 'Can not add person who is already in the aspect' if aspect.contacts.include?(contact)
     contact.aspects << aspect
-    opts[:posts] ||= self.raw_visible_posts.all(:person_id => person_id)
-
-    aspect.posts += opts[:posts]
-    contact.save
-    aspect.save
+    contact.save!
+    aspect.save!
   end
 
   def delete_person_from_aspect(person_id, aspect_id, opts = {})
     aspect = Aspect.find(aspect_id)
     raise "Can not delete a person from an aspect you do not own" unless aspect.user == self
     contact = contact_for Person.find(person_id)
-    contact.aspect_ids.delete aspect.id
-    opts[:posts] ||= aspect.posts.all(:person_id => person_id)
-    aspect.posts -= opts[:posts]
-    contact.save
-    aspect.save
+
+    if opts[:force] || contact.aspect_ids.count > 1
+      contact.aspect_ids.delete aspect.id
+      contact.save!
+      aspect.save!
+    else
+      raise "Can not delete a person from last aspect"
+    end
   end
 
   ######## Posting ########
diff --git a/app/views/people/_profile_sidebar.html.haml b/app/views/people/_profile_sidebar.html.haml
index 882c64d4b9..954fcc92b9 100644
--- a/app/views/people/_profile_sidebar.html.haml
+++ b/app/views/people/_profile_sidebar.html.haml
@@ -2,6 +2,19 @@
 -#   licensed under the Affero General Public License version 3 or later.  See
 -#   the COPYRIGHT file.
 
+- content_for :head do
+  :javascript
+    $(document).ready(function(){
+      $('.delete').bind('ajax:success', function() {
+        $(this).closest('li').fadeOut(200);
+      });
+
+      $('.delete').bind('ajax:failure', function() {
+        alert("Cannot remove #{person.real_name} from last aspect.");
+      });
+    });
+
+
 #profile
   .profile_photo
     = person_image_link(person, :to => :photos)
@@ -9,16 +22,16 @@
   = action_link(person, is_contact)
 
   %ul
-    /- if @posts.first
-    /%li
-    /%i= t(".last_seen",:how_long_ago => how_long_ago(@posts.first))
     - if is_contact
       %li
         %ul#aspects_for_person
           %b= t('.in_aspects')
           %br
           - for aspect in @aspects_with_person
-            %li= link_to aspect.name, aspect
+            %li
+              = link_to aspect.name, aspect
+              = link_to "x", {:controller => "aspects", :action => "remove_from_aspect", :person_id => person.id, :aspect_id => aspect.id}, :confirm => "Remove #{person.real_name} from #{aspect}?", :remote => true, :class => "delete"
+              
 
   -if is_contact || person == current_user.person
     %ul#profile_information
diff --git a/app/views/users/getting_started.html.haml b/app/views/users/getting_started.html.haml
index 668f6a9187..68e8222616 100644
--- a/app/views/users/getting_started.html.haml
+++ b/app/views/users/getting_started.html.haml
@@ -5,17 +5,20 @@
 
 - content_for :head do
   :javascript
-    $("#new_aspect").live("ajax:success", function(data,stat,xhr){
-      window.location.reload();
-    });
+    $(document).ready(function(){
+      $("#new_aspect").live("ajax:success", function(data,stat,xhr){
+        window.location.reload();
+      });
 
-    $(".aspects li").find(".delete").live("click", function(){
-      var aspectElement = $(this).parent("li");
-      if (confirm("are you sure?")){
-        aspectElement.fadeOut(300, function(){aspectElement.remove();});
-      }
+      $(".aspects li").find(".delete").live("click", function(){
+        var aspectElement = $(this).parent("li");
+        if (confirm("are you sure?")){
+          aspectElement.fadeOut(300, function(){aspectElement.remove();});
+        }
+      });
     });
     
+    
   - if current_user.getting_started == true
     :javascript
       $("#getting_started_skip").live("click", function(evt){
diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass
index e43ddadd03..ef1683f6be 100644
--- a/public/stylesheets/sass/application.sass
+++ b/public/stylesheets/sass/application.sass
@@ -1561,15 +1561,14 @@ h3 span.current_gs_step
     
 #profile
   ul#aspects_for_person
-  
     > li
-
       :display inline-block
-      :padding 4px 2px 0 0
+      :padding 4px 6px 0 0
 
       a
-        :border-radius 6px
         :padding 2px 4px
+        :margin
+          :left -3px
         :background
           :color #eee
         :font
@@ -1601,6 +1600,17 @@ h3 span.current_gs_step
           :color #eee
           :text-shadow none
 
+      a:first-child
+        :-webkit-border-radius 6px 0 0 6px
+        :-moz-border-radius 6px 0 0 6px
+        :border-radius 6px 0 0 6px
+
+      a:last-child
+        :-webkit-border-radius 0 6px 6px 0
+        :-moz-border-radius 0 6px 6px 0
+        :border-radius 0 6px 6px 0
+
+
 ul#request_result
   :list-style none
   :padding 0
diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb
index 947bbc4259..e9b62b22fb 100644
--- a/spec/controllers/aspects_controller_spec.rb
+++ b/spec/controllers/aspects_controller_spec.rb
@@ -8,13 +8,17 @@ describe AspectsController do
   render_views
 
   before do
-    @user                       = make_user
-    @aspect                     = @user.aspects.create(:name => "lame-os")
-    @aspect1                    = @user.aspects.create(:name => "another aspect")
-    @user2                      = make_user
-    @aspect2                    = @user2.aspects.create(:name => "party people")
+    @user     = make_user
+    @user2    = make_user
+
+    @aspect   = @user.aspects.create(:name => "lame-os")
+    @aspect1  = @user.aspects.create(:name => "another aspect")
+    @aspect2  = @user2.aspects.create(:name => "party people")
+
     connect_users(@user, @aspect, @user2, @aspect2)
+
     @contact                    = @user.contact_for(@user2.person)
+
     sign_in :user, @user
     request.env["HTTP_REFERER"] = 'http://' + request.host
   end
@@ -116,15 +120,17 @@ describe AspectsController do
   describe "#add_to_aspect" do
     it 'adds the users to the aspect' do
       @aspect1.reload
-      @aspect1.contacts.include?(@contact).should be false
+      @aspect1.contacts.include?(@contact).should be_false
       post 'add_to_aspect', {:person_id => @user2.person.id, :aspect_id => @aspect1.id}
       @aspect1.reload
-      @aspect1.contacts.include?(@contact).should be true
+      @aspect1.contacts.include?(@contact).should be_true
     end
   end
 
   describe "#remove_from_aspect" do
-    it 'adds the users to the aspect' do
+    it 'removes contacts from an aspect' do
+      pending 'this needs to test with another aspect present'
+
       @aspect.reload
       @aspect.contacts.include?(@contact).should be true
       post 'remove_from_aspect', {:person_id => @user2.person.id, :aspect_id => @aspect1.id}
diff --git a/spec/models/aspect_spec.rb b/spec/models/aspect_spec.rb
index 9eabde8be3..271e3d5761 100644
--- a/spec/models/aspect_spec.rb
+++ b/spec/models/aspect_spec.rb
@@ -177,11 +177,11 @@ describe Aspect do
 
     describe '#delete_person_from_aspect' do
       it 'deletes a user from the aspect' do
-         user.add_person_to_aspect(user2.person.id, aspect1.id)
-         user.reload
-         user.delete_person_from_aspect(user2.person.id, aspect1.id)
-         user.reload
-         aspect1.reload.contacts.include?(contact).should be false
+        user.add_person_to_aspect(user2.person.id, aspect1.id)
+        user.reload
+        user.delete_person_from_aspect(user2.person.id, aspect1.id)
+        user.reload
+        aspect1.reload.contacts.include?(contact).should be false
       end
 
       it 'should check to make sure you have the aspect ' do
@@ -196,11 +196,21 @@ describe Aspect do
            user.delete_person_from_aspect(user2.person.id, aspect1.id)
          }.should_not change(Post, :count)
       end
-    end
 
-    context 'moving and removing posts' do
+      it 'should not allow removing a contact from their last aspect' do
+        proc{user.delete_person_from_aspect(user2.person.id, aspect.id) }.should raise_error /Can not delete a person from last aspect/
+      end
+
+      it 'should allow a force removal of a contact from an aspect' do
+        contact.aspect_ids.should_receive(:count).exactly(0).times
+
+        user.add_person_to_aspect(user2.person.id, aspect1.id)
+        user.delete_person_from_aspect(user2.person.id, aspect.id, :force => true)
+      end
 
+    end
 
+    context 'moving and removing posts' do
       before do
         @message  = user2.post(:status_message, :message => "Hey Dude", :to => aspect2.id)
         aspect.reload
@@ -210,22 +220,17 @@ describe Aspect do
         user.reload
       end
       
-      it 'moves the persons posts into the new aspect' do
-        user.add_person_to_aspect(user2.person.id, aspect1.id, :posts => [@message] )
-        aspect1.reload
-        aspect1.posts.should == [@message]
-      end
+      it 'should keep the contact\'s posts in previous aspect' do
+        aspect.post_ids.count.should == 1
+        user.delete_person_from_aspect(user2.person.id, aspect.id, :force => true)
 
-      
-      it 'should remove the users posts from that aspect' do
-        user.delete_person_from_aspect(user2.person.id, aspect.id)
         aspect.reload
-        aspect.posts.count.should == @post_count - 1
+        aspect.post_ids.count.should == 1
       end
 
       it 'should not delete other peoples posts' do
         connect_users(user, aspect, user3, aspect3)
-        user.delete_person_from_aspect(user3.person.id, aspect.id)
+        user.delete_person_from_aspect(user3.person.id, aspect.id, :force => true)
         aspect.reload
         aspect.posts.should == [@message]
       end
@@ -256,15 +261,6 @@ describe Aspect do
           aspect2.contacts.include?(contact).should be false
         end
 
-        it 'should move all posts by that user to the new aspect' do
-          user.move_contact(:person_id => user2.person.id, :from => aspect.id, :to => aspect1.id)
-          aspect.reload
-          aspect1.reload
-
-          aspect1.posts.count.should == @post_count1 + 1
-          aspect.posts.count.should == @post_count - 1
-        end
-
         it 'does not try to delete if add person did not go through' do
           user.should_receive(:add_person_to_aspect).and_return(false)
           user.should_not_receive(:delete_person_from_aspect)
diff --git a/spec/models/contact_spec.rb b/spec/models/contact_spec.rb
index 5bc480289c..d645d5a2e3 100644
--- a/spec/models/contact_spec.rb
+++ b/spec/models/contact_spec.rb
@@ -21,11 +21,5 @@ describe Contact do
     it 'has many aspects' do
       contact.associations[:aspects].type.should == :many
     end
-
-    it 'has at least one aspect' do
-      contact.valid?
-      contact.errors.full_messages.should include "Aspects can't be blank"
-    end
-
   end
 end
-- 
GitLab