diff --git a/app/controllers/aspects_controller.rb b/app/controllers/aspects_controller.rb index 56c34f0bc..b6f7124f8 100644 --- a/app/controllers/aspects_controller.rb +++ b/app/controllers/aspects_controller.rb @@ -6,7 +6,7 @@ class AspectsController < ApplicationController before_filter :authenticate_user! respond_to :html - respond_to :json, :only => :show + respond_to :json, :only => [:show, :create] respond_to :js def index @@ -47,6 +47,22 @@ class AspectsController < ApplicationController redirect_to :back elsif request.env['HTTP_REFERER'].include?("aspects/manage") redirect_to :back + elsif params[:aspect][:share_with] + @contact = Contact.where(:id => params[:aspect][:contact_id]).first + @person = Person.where(:id => params[:aspect][:person_id]).first + @contact = current_user.contact_for(@person) + + invite_or_add_contact_to_aspect(@aspect, @person, @contact) + + @contact = current_user.contact_for(@person) + respond_to do |format| + format.js { render :json => {:html => render_to_string( + :partial => 'aspects/aspect_list_item', + :locals => {:aspect => @aspect, + :person => @person, + :contact => @contact} + )},:status => 201 } + end else respond_with @aspect end @@ -142,17 +158,8 @@ class AspectsController < ApplicationController @aspect = current_user.aspects.find(params[:aspect_id]) @contact = current_user.contact_for(@person) - if @contact - current_user.add_contact_to_aspect(@contact, @aspect) - else - current_user.send_contact_request_to(@person, @aspect) - contact = current_user.contact_for(@person) + invite_or_add_contact_to_aspect(@aspect, @person, @contact) - if request = Request.where(:sender_id => @person.id, :recipient_id => current_user.person.id).first - request.destroy - contact.update_attributes(:pending => false) - end - end flash.now[:notice] = I18n.t 'aspects.add_to_aspect.success' respond_to do |format| @@ -195,4 +202,20 @@ class AspectsController < ApplicationController end end end + + private + def invite_or_add_contact_to_aspect( aspect, person, contact) + if contact + current_user.add_contact_to_aspect(contact, aspect) + else + current_user.send_contact_request_to(person, aspect) + contact = current_user.contact_for(person) + + if request = Request.where(:sender_id => person.id, :recipient_id => current_user.person.id).first + request.destroy + contact.update_attributes(:pending => false) + end + end + + end end diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb index 95de0e13c..2bd519c75 100644 --- a/app/controllers/invitations_controller.rb +++ b/app/controllers/invitations_controller.rb @@ -8,7 +8,7 @@ class InvitationsController < Devise::InvitationsController def new @sent_invitations = current_user.invitations_from_me.includes(:recipient) - #emails_delivered = sent_invitations.map!{ |i| i.recipient.email } + render :layout => false end def create diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 9193b06f4..b50a401ce 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -1,5 +1,5 @@ # Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. +# licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. class ServicesController < ApplicationController before_filter :authenticate_user! @@ -46,7 +46,7 @@ class ServicesController < ApplicationController def finder service = current_user.services.where(:type => "Services::#{params[:provider].titleize}").first - @friends = service ? service.finder : {} + @friends = service ? service.finder(:remote => params[:remote]) : {} render :layout => false end @@ -67,7 +67,7 @@ class ServicesController < ApplicationController @subject = t('services.inviter.join_me_on_diaspora') @message = < invited_user.invitation_token)} diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 61196f288..d1222e176 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -21,10 +21,8 @@ class UsersController < ApplicationController params[:user].delete(:password) if params[:user][:password].blank? params[:user].delete(:password_confirmation) if params[:user][:password].blank? and params[:user][:password_confirmation].blank? params[:user].delete(:language) if params[:user][:language].blank? - - - # change email notifications + # change email notifications if params[:user][:disable_mail] @user.update_attributes(:disable_mail => params[:user][:disable_mail]) flash[:notice] = I18n.t 'users.update.email_notifications_changed' @@ -78,21 +76,33 @@ class UsersController < ApplicationController @person = @user.person @profile = @user.profile @services = @user.services - @requests = Request.where(:recipient_id => @person.id).all + service = current_user.services.where(:type => "Services::Facebook").first - @step = ((params[:step].to_i>0)&&(params[:step].to_i<5)) ? params[:step].to_i : 1 + @step = ((params[:step].to_i>0)&&(params[:step].to_i<4)) ? params[:step].to_i : 1 @step ||= 1 - if @step == 4 - @user.getting_started = false - @user.save + if @step == 2 && SERVICES['facebook']['app_id'] == "" + @step = 3 + end + + if @step == 3 + @requests = Request.where(:recipient_id => @person.id).includes(:sender => :profile).all + @friends = service ? service.finder(:local => true) : {} + @friends.delete_if{|key, value| @requests.any?{ |r| r.sender_id == value[:person].id} } + end + + + if @step == 3 && @requests.length == 0 && @friends.length == 0 + @user.update_attributes(:getting_started => false) + redirect_to root_path + else + render "users/getting_started" end - render "users/getting_started" end def getting_started_completed user = current_user - user.update_attributes( :getting_started => false ) + user.update_attributes(:getting_started => false) redirect_to root_path end diff --git a/app/models/aspect.rb b/app/models/aspect.rb index 0b113701b..b6a99cef8 100644 --- a/app/models/aspect.rb +++ b/app/models/aspect.rb @@ -13,7 +13,7 @@ class Aspect < ActiveRecord::Base validates_presence_of :name validates_length_of :name, :maximum => 20 - validates_uniqueness_of :name, :scope => :user_id + validates_uniqueness_of :name, :scope => :user_id, :case_sensitive => false attr_accessible :name diff --git a/app/models/post.rb b/app/models/post.rb index 66bb866fe..df2834370 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -65,7 +65,6 @@ class Post < ActiveRecord::Base def receive(user, person) #exists locally, but you dont know about it #does not exsist locally, and you dont know about it - #exists_locally? #you know about it, and it is mutable #you know about it, and it is not mutable @@ -82,13 +81,13 @@ class Post < ActiveRecord::Base else user.add_post_to_aspects(local_post) Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle} existing_post=#{local_post.id}") - local_post + return local_post end elsif !local_post self.save user.add_post_to_aspects(self) Rails.logger.info("event=receive payload_type=#{self.class} update=false status=complete sender=#{self.diaspora_handle}") - self + return self else Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason='update not from post owner' existing_post=#{self.id}") end diff --git a/app/models/services/facebook.rb b/app/models/services/facebook.rb index f0987a16f..a8f6def73 100644 --- a/app/models/services/facebook.rb +++ b/app/models/services/facebook.rb @@ -19,7 +19,7 @@ class Services::Facebook < Service super(post, MAX_CHARACTERS, url) end - def finder + def finder(opts = {}) Rails.logger.debug("event=friend_finder type=facebook sender_id=#{self.user_id}") response = RestClient.get("https://graph.facebook.com/me/friends", {:params => {:access_token => self.access_token}}) data = JSON.parse(response.body)['data'] @@ -45,9 +45,21 @@ class Services::Facebook < Service person_ids_and_uids[s.user.person.id] = s.uid end + requests = Request.where(:recipient_id => self.user.person.id, :sender_id => person_ids_and_uids.keys).all + requests.each{|r| data_h[person_ids_and_uids[r.sender_id]][:request] = r} + + contact_objects = self.user.contacts.where(:person_id => person_ids_and_uids.keys) contact_objects.each{|c| data_h[person_ids_and_uids[c.person_id]][:contact] = c} + if opts[:local] + data_h.delete_if {|key, value| value[:person].nil? } + end + + if opts[:remote] + data_h.delete_if {|key, value| !value[:person].nil? } + end + data_h end end diff --git a/app/views/aspects/_aspect_list_item.haml b/app/views/aspects/_aspect_list_item.haml new file mode 100644 index 000000000..8ee855aa1 --- /dev/null +++ b/app/views/aspects/_aspect_list_item.haml @@ -0,0 +1,9 @@ +-# Copyright (c) 2010, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + +%li{:data=>{:guid=>aspect.id}} + %span.name + = link_to aspect.name, aspect + .right + = aspect_membership_button(aspect, contact, person) diff --git a/app/views/invitations/new.html.haml b/app/views/invitations/new.html.haml index 93d2d5642..aeca8a475 100644 --- a/app/views/invitations/new.html.haml +++ b/app/views/invitations/new.html.haml @@ -4,37 +4,37 @@ $("#user_email").focus(); }); -.span-3.append-1 - = image_tag 'icons/monotone_email_letter_round.png', :height => "128px", :width => "128px" +.span-15.last + .span-3 + = image_tag 'icons/monotone_email_letter_round.png', :height => "128px", :width => "128px" -.span-20.last - .span-20.last + .span-12.last %h2 = t('.invite_someone_to_join') .description = t('.if_they_accept_info') %br + .span-7.append-1 + #email_invitation + = form_for User.new, :url => invitation_path(User) do |invite| + %h4 + = t('email') + = invite.text_field :email, :title => t('.comma_seperated_plz') + %br - .span-13.append-1 - = form_for User.new, :url => invitation_path(User) do |invite| - %h4 - = t('email') - = invite.text_field :email, :title => t('.comma_seperated_plz') - %br + %h4 + = t('.aspect') + = invite.select(:aspects, options_from_collection_for_select(@all_aspects, 'id', 'name')) - %h4 - = t('.aspect') - = invite.select(:aspects, options_from_collection_for_select(@all_aspects, 'id', 'name')) + %br + %br - %br - %br + %h4 + = t('.personal_message') + = invite.text_area :invite_messages, :rows => 3, :value => "" - %h4 - = t('.personal_message') - = invite.text_area :invite_messages, :rows => 3, :value => "" - - %p - = invite.submit t('.send_an_invitation') + %p + = invite.submit t('.send_an_invitation') - if !@sent_invitations.empty? .span-6.last diff --git a/app/views/layouts/application.mobile.haml b/app/views/layouts/application.mobile.haml index 23f862392..a6b3ee107 100644 --- a/app/views/layouts/application.mobile.haml +++ b/app/views/layouts/application.mobile.haml @@ -30,6 +30,29 @@ = yield(:head) + -if AppConfig[:google_a_site] + :javascript + var _gaq = _gaq || []; + _gaq.push(['_setAccount', '#{AppConfig[:google_a_site]}']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + + -if AppConfig[:piwik_id] + :javascript + var pkBaseURL = (("https:" == document.location.protocol) ? "https://#{AppConfig[:piwik_url]}/" : "http://#{AppConfig[:piwik_url]}/"); + document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E")); + try { + var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", #{AppConfig[:piwik_id]}); + piwikTracker.trackPageView(); + piwikTracker.enableLinkTracking(); + } catch( err ) {} + + %body #content{:data => {:role => 'page'}} #header diff --git a/app/views/people/_aspect_list.haml b/app/views/people/_aspect_list.haml index ffbdb61b1..02784a408 100644 --- a/app/views/people/_aspect_list.haml +++ b/app/views/people/_aspect_list.haml @@ -5,23 +5,6 @@ - content_for :head do =javascript_include_tag 'contact-list' - :javascript - $(document).ready(function() { - $("#edit_contact_aspects").click(function(evt){ - evt.preventDefault(); - $(".badges").fadeOut(200, function(){ - $(".edit").fadeIn(200); - }); - }); - - $("#done_contact_aspects").click(function(evt){ - evt.preventDefault(); - $(".edit").fadeOut(200, function(){ - $(".badges").fadeIn(200); - }); - }); - }); - .aspects - if !contact %h4 @@ -37,18 +20,10 @@ .badges{:class => ("hidden" if !contact)} = aspect_badges(aspects_with_person) - .right - = link_to t('.edit_membership'), "#", :id=> "edit_contact_aspects" - - .edit.hidden - = render :partial => 'people/share_with_pane', - :locals => {:person => person, - :contact => contact, - :aspects_with_person => aspects_with_person, - :aspects_without_person => aspects_without_person} - %br - - - if contact - .right - = link_to t('aspects.aspect_contacts.done_editing'), "#", :id => "done_contact_aspects" - = link_to t('people.profile_sidebar.remove_contact'), person, :confirm => t('are_you_sure'), :method => :delete + %p + = link_to t('.edit_membership'), + {:controller => "people", + :action => "share_with", + :id => @person.id}, + :class => 'button', + :rel => 'facebox' diff --git a/app/views/people/_person.html.haml b/app/views/people/_person.html.haml index cc424791d..228ad17e0 100644 --- a/app/views/people/_person.html.haml +++ b/app/views/people/_person.html.haml @@ -9,8 +9,15 @@ = t('.thats_you') - elsif contact && !contact.pending = t('.already_connected') - - elsif (contact && contact.pending) || request + - elsif (contact && contact.pending) || (request && request.recipient == person) = t('.pending_request') + - elsif request && request.sender == person + = link_to t('people.show.incoming_request', :name => truncate(person.name, :length => 20, :separator => ' ', :omission => '')), + {:controller => "people", + :action => "share_with", + :id => person.id}, + :class => 'share_with button', + :rel => 'facebox' - else = link_to t('people.show.start_sharing'), {:controller => "people", diff --git a/app/views/people/_profile_sidebar.html.haml b/app/views/people/_profile_sidebar.html.haml index bcefdf668..d22ac25c7 100644 --- a/app/views/people/_profile_sidebar.html.haml +++ b/app/views/people/_profile_sidebar.html.haml @@ -9,7 +9,7 @@ $(this).closest('li').fadeOut(200); }); $('.delete').bind('ajax:failure', function() { - alert("#{h(t('.cannot_remove', :name => person.name))}"); + alert("#{t('status_message.destroy.failure')}"); }); }); diff --git a/app/views/people/_share_with_pane.html.haml b/app/views/people/_share_with_pane.html.haml index 74c5ced8b..a302636c7 100644 --- a/app/views/people/_share_with_pane.html.haml +++ b/app/views/people/_share_with_pane.html.haml @@ -5,16 +5,29 @@ .aspect_list#aspects_list %ul - for aspect in aspects_with_person - %li{:data=>{:guid=>aspect.id}} - %span.name - = link_to aspect.name, aspect - .right - = aspect_membership_button(aspect, contact, person) + = render :partial => 'aspects/aspect_list_item', + :locals => {:aspect => aspect, :person => person, + :contact => contact} - for aspect in aspects_without_person - %li{:data=>{:guid=>aspect.id}} - %span.name - = link_to aspect.name, aspect - .right - = aspect_membership_button(aspect, contact, person) - + = render :partial => 'aspects/aspect_list_item', + :locals => {:aspect => aspect, :person => person, + :contact => contact} +.add_aspect + = form_for(Aspect.new, :remote => true) do |aspect| + .right + = aspect.submit "add new aspect", :class => 'button' + = aspect.error_messages + = aspect.hidden_field :person_id, :value => person.id if person + = aspect.hidden_field :contact_id, :value => contact.id if contact + = aspect.hidden_field :share_with, :value => true + %p + = aspect.text_field :name, :style => "display:inline;" + %p.checkbox_select + = aspect.label :contacts_visible, t('aspects.edit.make_aspect_list_visible') + = aspect.check_box :contacts_visible, :checked => true, :default => true +.done + .right + = link_to t('aspects.aspect_contacts.done_editing'), "#", :class => "button", :onClick => '$.facebox.close();' + - if contact + = link_to t('people.profile_sidebar.remove_contact'), person, :confirm => t('are_you_sure'), :method => :delete diff --git a/app/views/services/_finder.html.haml b/app/views/services/_finder.html.haml new file mode 100644 index 000000000..f50595007 --- /dev/null +++ b/app/views/services/_finder.html.haml @@ -0,0 +1,8 @@ +-# Copyright (c) 2010, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + += search_field_tag :contact_search, "", :class => 'contact_list_search', :results => 5, :placeholder => t('shared.contact_list.all_contacts') +%ul + - for uid in friends.keys + = render :partial => 'services/remote_friend', :locals => {:friend => friends[uid], :uid => uid} diff --git a/app/views/services/_remote_friend.html.haml b/app/views/services/_remote_friend.html.haml index 800970cf3..707a2d1a8 100644 --- a/app/views/services/_remote_friend.html.haml +++ b/app/views/services/_remote_friend.html.haml @@ -2,8 +2,15 @@ .right -if friend[:contact] && !friend[:contact].pending = t('people.person.already_connected') - - elsif (friend[:contact] && friend[:contact].pending) + - elsif (friend[:contact] && friend[:contact].pending) || (friend[:request] && friend[:request].sender != friend[:person]) = t('people.person.pending_request') + - elsif (friend[:request] && friend[:request].sender == friend[:person]) + = link_to t('people.show.incoming_request', :name => truncate(friend[:person].name, :length => 20, :separator => ' ', :omission => '')), + {:controller => "people", + :action => "show", + :id => friend[:person].id, + :share_with => true}, + :class => 'button' - elsif friend[:invitation_id] = t('invitations.new.already_invited') %br @@ -17,10 +24,9 @@ :class => 'button' - elsif current_user.invites > 0 - = form_tag service_inviter_path do + = form_tag service_inviter_path(:provider => 'facebook') do = select_tag(:aspect_id, options_from_collection_for_select(@all_aspects, 'id', 'name')) = hidden_field_tag :uid, uid - = hidden_field_tag :provider, 'facebook' = submit_tag t('.invite') - if friend[:person] diff --git a/app/views/services/finder.html.haml b/app/views/services/finder.html.haml index f26e73375..f3256ab06 100644 --- a/app/views/services/finder.html.haml +++ b/app/views/services/finder.html.haml @@ -18,10 +18,7 @@ .contact_list - if @friends.keys.length > 0 - = search_field_tag :contact_search, "", :class => 'contact_list_search', :results => 5, :placeholder => t('shared.contact_list.all_contacts') - %ul - - for uid in @friends.keys - = render :partial => 'remote_friend', :locals => {:friend => @friends[uid], :uid => uid} + = render :partial => 'services/finder', :locals => {:friends => @friends} - else %br %br diff --git a/app/views/shared/_invitations.haml b/app/views/shared/_invitations.haml index 9d802e327..2b564c3cc 100644 --- a/app/views/shared/_invitations.haml +++ b/app/views/shared/_invitations.haml @@ -4,12 +4,17 @@ -if invites > 0 - if SERVICES['facebook']['app_id'] !="" %h4{:style => 'text-align:center;'} - = link_to t('.from_facebook'), friend_finder_path('facebook'), :rel => 'facebox' + - if defined? remote + = link_to t('.from_facebook'), friend_finder_path('facebook', :remote => remote), :rel => 'facebox' + -else + = link_to t('.from_facebook'), friend_finder_path('facebook'), :rel => 'facebox' + = t('or') - = link_to t('.by_email'), new_user_invitation_path, :title => t('.invite_someone') + = link_to t('.by_email'), new_user_invitation_path, :title => t('.invite_someone'), :rel => 'facebox' - else %h4 = link_to t('.by_email'), new_user_invitation_path, :title => t('.invite_someone') - = t('.invitations_left', :count => invites) + %h5{:style => 'text-align:center;'} + = t('.invitations_left', :count => invites) - else = t('.dont_have_now') diff --git a/app/views/users/getting_started.html.haml b/app/views/users/getting_started.html.haml index ec53b5db3..551c2c403 100644 --- a/app/views/users/getting_started.html.haml +++ b/app/views/users/getting_started.html.haml @@ -3,54 +3,30 @@ -# the COPYRIGHT file. -- content_for :head do - :javascript - $(document).ready(function(){ - $("#new_aspect").live("ajax:success", function(data,stat,xhr){ - window.location.reload(); - }); += content_for :head do + :css + header{ display:none; } - $(".aspects li").find(".delete").live("click", function(){ - var aspectElement = $(this).parent("li"); - if (confirm("#{t('are_you_sure')}")){ - aspectElement.fadeOut(300, function(){aspectElement.remove();}); - } - }); - }); - -.span-8.append-1.last - %h1{:style => "text-align:right;"} - = t('.welcome') - .description - =t('.signup_steps') + #getting_started_logo.start{ + -webkit-animation-name: fadeUp; + -webkit-animation-delay: 0s; + -webkit-animation-duration: 0.35s; + } - %h3{:style => "text-align:right;"} - - if @step != 1 - = link_to t('.edit_profile'), getting_started_path(:step => 1) - - else - %span.current_gs_step - = t('.edit_profile') - %br - - if @step != 2 - = link_to t('.define_aspects'), getting_started_path(:step => 2) - - else - %span.current_gs_step - = t('.define_aspects') - %br - - if @step != 3 - = link_to t('.connect_services'), getting_started_path(:step => 3) - - else - %span.current_gs_step - = t('.connect_services') - %br - - if @step != 4 - = link_to t('.finished'), getting_started_path(:step => 4) - - else - %span.current_gs_step - = t('.finished') - %br -.span-15.last - .floating{:style=>"min-height:500px;"} + @media only screen { + #getting_started_logo { -webkit-transform: translateZ(0); } + } + @-webkit-keyframes fadeUp { + 0% { opacity: 0; -webkit-transform: translate3d(0, 40px, 0); -webkit-animation-timing-function: ease-out; } + 70% { opacity: 0; -webkit-transform: translate3d(0, 35px, 0); } + 100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0); -webkit-animation-timing-function: ease-out; } + } + +.span-15.prepend-4.last{:style => 'position:relative;'} + = image_tag 'logo_caps.png', :id => 'getting_started_logo', :width => 143, :height => 21, :class => ('start' if @step == 1) + %br + %br + .floating{:style=>"min-height:300px;"} = render "users/getting_started/step_#{@step}", :current_user => current_user - if @step > 1 diff --git a/app/views/users/getting_started/_step_2.html.haml b/app/views/users/getting_started/_step_2.html.haml index b4d593674..900aa12f9 100644 --- a/app/views/users/getting_started/_step_2.html.haml +++ b/app/views/users/getting_started/_step_2.html.haml @@ -1,63 +1,19 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -- content_for :head do - = include_javascripts :aspects - -%h3 - = t('.your_aspects') - .description - = t('.description') - --if @requests.size > 0 - %h3 - = t('.your_inviter') - - %h3 - %ul.dropzone - - if @requests.size < 1 - %li=t('.no_requests') - - else - - for request in @requests - %li.person.request{:data=>{:guid=>request.id, :person_id=>request.sender.id}} - = person_image_link(request.sender) - .requests - %p= "#{t('.drag_to_add')} =>" -%ul#aspect_list - - for aspect in @all_aspects - %li.aspect{:data=>{:guid=>aspect.id}} - - .aspect_name - %span.edit_name_field - %h3{:contenteditable=>true} - = aspect.name - %span.tip click to edit - - %ul.tools - %li!= remove_link(aspect) - - %ul.dropzone{:data=>{:aspect_id=>aspect.id}} - -for contact in aspect.contacts - %li.person{:data=>{:guid=>contact.person.id, :aspect_id=>aspect.id}} - .delete - .x - X - .circle - = person_image_link(contact.person) -%h4 - = t('.aspect_name') - = form_for Aspect.new do |aspect| - = aspect.text_field :name, :id => "step-2-aspect-name", :style => "display:inline;" - %p.checkbox_select - = aspect.label :contacts_visible, t('aspects.edit.make_aspect_list_visible') - = aspect.check_box :contacts_visible, :default => true - %br - = aspect.submit t('.add') %br %br +%br +%br +%br +%h3{:style => 'text-align: center;'} + = t('.find_your_friends_on_diaspora') + %br + %br + %br + = link_to image_tag('services/facebook_sign_in.png', :id => 'getting_started_logo', :width => 154, :height => 22), '/auth/facebook' .submit_block - = link_to "#{t('users.getting_started.save_and_continue')} →", getting_started_path(:step => 3), :class => "button" - + = link_to "#{t('.skip')} →", getting_started_path(:step => @step+1), :class => 'button' diff --git a/app/views/users/getting_started/_step_3.html.haml b/app/views/users/getting_started/_step_3.html.haml index f94ff7dfd..bc3561dad 100644 --- a/app/views/users/getting_started/_step_3.html.haml +++ b/app/views/users/getting_started/_step_3.html.haml @@ -1,15 +1,26 @@ -# Copyright (c) 2010, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - +- content_for :head do + = include_javascripts :aspects %h3 - = t('.your_services') - .description - = t('.description') + = t('.people_already_on_diaspora') -= render 'shared/add_remove_services' + %br + %br + +#people_stream.stream + - for pending_req in @requests + - person = pending_req.sender + + = render :partial => 'people/person', :locals => {:request => pending_req, :person => person, :contact => nil} + - for fb_id in @friends.keys + - friend = @friends[fb_id] + = render :partial => 'people/person', :locals => {:request => friend[:request], :person => friend[:person], :contact => friend[:contact]} + +%br +%br .submit_block - = link_to "#{t('users.getting_started.save_and_continue')} →", getting_started_path(:step => 4), :class => "button" - + = link_to "#{t('.finish')} →", getting_started_completed_path, :class => 'button' diff --git a/app/views/users/getting_started/_step_4.html.haml b/app/views/users/getting_started/_step_4.html.haml deleted file mode 100644 index 3661bf972..000000000 --- a/app/views/users/getting_started/_step_4.html.haml +++ /dev/null @@ -1,33 +0,0 @@ --# Copyright (c) 2010, Diaspora Inc. This file is --# licensed under the Affero General Public License version 3 or later. See --# the COPYRIGHT file. - - -%h1 - = t('.set_up', :name => first_name_or_username(current_user)) - .description - = t('.ready_to_share') - %ul.inline_aspect_listing - - for aspect in @all_aspects - %li= aspect - -%br -%br - -%h3 - = link_to t('.continue'), root_path - -%br -%br -%br - -%p - = t('.change_profile') - = t('.user_menu') - -%p - = t('.manage_aspects') - -.submit_block - = link_to "#{t('.finish')} →", root_url, :class => "button" - diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 1c5a359a7..693ea1835 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -230,30 +230,17 @@ en: welcome: "Welcome to Diaspora!" signup_steps: "Finish your sign up by completing these three steps:" edit_profile: "Edit your profile" - define_aspects: "Define your aspects" + connect_on_diaspora: "Connect on Diaspora" connect_services: "Connect your other services" finished: "Finished!" skip: "skip getting started" save_and_continue: "Save and continue" - step_2: - your_aspects: "Your aspects" - description: "Tell Diaspora what different aspects of you are seen by different contacts. You can manage these later through your account menu at the top right. Your aspects are unique to you and not visible by others." - aspect_name: "Aspect name" - add: "Add" - your_inviter: "Here are the people who are waiting for you:" - drag_to_add: "Drag them to the aspect of yourself they know" - no_requests: "You have no requests" step_3: - your_services: "Your services" - description: 'You are able to connect your existing social networks to your Diaspora account. You will be able to post publically through your Home page when you select “make public"' - step_4: - set_up: "You're all set up, %{name}!" - ready_to_share: "You're now ready to start sharing with " - continue: "Continue on to your Home page, an overview of all of your aspects." - change_profile: "You can edit your profile and manage your connected services at any time through " - user_menu: "the user menu located at the top right." - manage_aspects: "You can also add contacts while on any aspect page." finish: "Finish" + people_already_on_diaspora: "People already on Diaspora" + step_2: + find_your_friends_on_diaspora: "Would you like to find your Facebook friends on Diaspora?" + skip: "Skip" update: password_changed: "Password Changed" password_not_changed: "Password Change Failed" @@ -348,6 +335,8 @@ en: permalink: "permalink" helper: no_message_to_display: "No message to display." + destroy: + failure: "Failed to delete post" people: person: pending_request: "pending request" diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 0c31185ca..91adf6f7a 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -21,3 +21,7 @@ en: watch: "Watch this video on {{provider}}" unknown: "Unknown video type" search_for: "Search for {{name}}" + shared: + contact_list: + cannot_remove: "Cannot remove person from last aspect. (If you want to disconnect from this person you must remove contact.)" + diff --git a/features/accepts_invitation.feature b/features/accepts_invitation.feature index 8810eea28..57df80751 100644 --- a/features/accepts_invitation.feature +++ b/features/accepts_invitation.feature @@ -9,14 +9,13 @@ Feature: invitation acceptance And I fill in "Password confirmation" with "secret" And I press "Sign up" Then I should be on the getting started page - And I should see "Welcome to Diaspora!" - And I should see "ohai" - And I fill in "profile_first_name" with "O" + And I should see "getting_started_logo" + When I fill in "profile_first_name" with "O" And I fill in "profile_last_name" with "Hai" And I fill in "profile_gender" with "guess!" And I press "Save and continue" Then I should see "Profile updated" - And I should see "Your aspects" + And I should see "Would you like to find your Facebook friends on Diaspora?" And I should not see "Here are the people who are waiting for you:" Scenario: accept invitation from user @@ -28,17 +27,24 @@ Feature: invitation acceptance And I fill in "Password confirmation" with "secret" And I press "Sign up" Then I should be on the getting started page - And I should see "Welcome to Diaspora!" - And I should see "ohai" - And I fill in "profile_first_name" with "O" + And I should see "getting_started_logo" + When I fill in "profile_first_name" with "O" And I fill in "profile_last_name" with "Hai" And I fill in "profile_gender" with "guess!" And I press "Save and continue" Then I should see "Profile updated" - And I should see "Your aspects" - And I should see "Here are the people who are waiting for you:" - And I should see 1 contact request - When I drag the contact request to the "Family" aspect - And I wait for the ajax to finish - Then I should see 1 contact in "Family" + + And I should see "Would you like to find your Facebook friends on Diaspora?" + + When I follow "Skip" + Then I should see "People already on Diaspora" + + And I press the first ".share_with.button" + And I press the first ".add.button" within "#facebox #aspects_list ul > li:first-child" + And I wait for the ajax to finish + + When I go to the home page + Then I go to the aspects manage page + Then I should see 1 contact in "Family" + diff --git a/features/connects_users.feature b/features/connects_users.feature index 6097aed19..22b9a9849 100644 --- a/features/connects_users.feature +++ b/features/connects_users.feature @@ -1,11 +1,9 @@ +@javascript Feature: sending and receiving requests Background: Given a user with email "bob@bob.bob" And a user with email "alice@alice.alice" - - @javascript - Scenario: initiating and accepting a contact request When I sign in as "bob@bob.bob" And I am on "alice@alice.alice"'s page And I press the first ".share_with.button" within "#author_info" @@ -13,7 +11,8 @@ Feature: sending and receiving requests And I wait for the ajax to finish Then I should see a ".added.button" within "#facebox #aspects_list ul > li:first-child" Then I go to the destroy user session page - + + Scenario: accepting a contact request When I sign in as "alice@alice.alice" And I am on the aspects manage page Then I should see 1 contact request @@ -30,3 +29,20 @@ Feature: sending and receiving requests And I am on the aspects manage page Then I should see 1 contact in "Besties" + + Scenario: accepting a contact request into a new aspect + When I sign in as "alice@alice.alice" + And I am on "bob@bob.bob"'s page + And I press the first ".share_with.button" within "#author_info" + And I fill in "Name" with "Super People" in the modal window + And I press "aspect_submit" in the modal window + And I wait for the ajax to finish + + When I go to the home page + Then I go to the aspects manage page + Then I should see 1 contact in "Super People" + Then I go to the destroy user session page + + When I sign in as "bob@bob.bob" + And I am on the aspects manage page + Then I should see 1 contact in "Besties" diff --git a/features/signs_up.feature b/features/signs_up.feature index 2d9018c49..c7d11b349 100644 --- a/features/signs_up.feature +++ b/features/signs_up.feature @@ -9,32 +9,20 @@ Feature: new user registration And I fill in "Password confirmation" with "secret" And I press "Sign up" Then I should be on the getting started page - And I should see "Welcome to Diaspora!" + And I should see "getting_started_logo" Scenario: new user goes through the setup wizard - When I fill in "profile_first_name" with "O" + When I fill in "profile_first_name" with "O" And I fill in "profile_last_name" with "Hai" And I fill in "profile_gender" with "guess!" And I press "Save and continue" And I wait for "step 2" to load Then I should see "Profile updated" - And I should see "Your aspects" - - When I fill in "step-2-aspect-name" with "cheez friends" - And I press "Add" - Then I should see "cheez friends" + And I should see "Would you like to find your Facebook friends on Diaspora?" + And I follow "Skip" - When I follow "Save and continue" - And I wait for "step 3" to load - Then I should see "Your services" - - When I follow "Save and continue" - And I wait for "step 4" to load - Then I should see "You're all set up, O!" - But I should not see "skip getting started" - - When I follow "Continue on to your Home page, an overview of all of your aspects." Then I should be on the aspects page + And I should not see "skip getting started" And I should see "Bring the people that matter in your life to Diaspora!" Scenario: new user skips the setup wizard and returns to the setup wizard diff --git a/public/images/icons/monotone_add_plus.png b/public/images/icons/monotone_add_plus.png new file mode 100644 index 000000000..f03378c1e Binary files /dev/null and b/public/images/icons/monotone_add_plus.png differ diff --git a/public/javascripts/contact-list.js b/public/javascripts/contact-list.js index 315c4cd31..be016c680 100644 --- a/public/javascripts/contact-list.js +++ b/public/javascripts/contact-list.js @@ -46,10 +46,11 @@ $(document).ready(function() { }); $('.added').live('ajax:failure', function(data, html, xhr) { - Diaspora.widgets.alert.alert("#{t('.cannot_remove')}"); + alert(Diaspora.widgets.i18n.t('shared.contact_list.cannot_remove')); $(this).fadeTo(200,1); }); + $('.add').live('ajax:loading', function() { $(this).fadeTo(200,0.4); }); @@ -73,5 +74,10 @@ $(document).ready(function() { $(this).children("img").attr("src","/images/icons/monotone_check_yes.png"); }); + $('.new_aspect').live('ajax:success', function(data, json, xhr){ + var json = JSON.parse(json); + $('#aspects_list ul').append(json.html); + }); + List.initialize(); }); diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index 12aa5f544..14b9f71ec 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -1341,6 +1341,7 @@ ul#settings_nav :margin 0 :padding 0 + .dull :color #aaa :font @@ -1506,10 +1507,6 @@ ul.aspects :-moz-box-shadow 0 1px 3px #333 :box-shadow 0 1px 3px #333 - :-webkit-border-radius 2px - :-moz-border-radius 2px - :border-radius 2px - :border :bottom 1px solid #ccc :top 1px solid #fff @@ -1615,7 +1612,7 @@ h3 span.current_gs_step :left 0 :width 100% :background - :color rgba(16,127,201,0.8) + :color rgba(63,143,186,0.8) :text :align center @@ -1629,7 +1626,7 @@ h3 span.current_gs_step a :color #fafafa :background - :color rgb(16,127,201) + :color $blue :padding 8px :-webkit-border-radius 10px @@ -2393,3 +2390,41 @@ ul.show_comments #logo :position relative + +#email_invitation + input + :width 100% + textarea + :width 100% + +#share_with + .add_aspect + :-webkit-border-radius 5px + :-moz-border-radius 5px + :border-radius 5px + + :margin + :top 0.5em + :background + :color #ddd + p + :padding + :left 1em + + &.checkbox_select + label + :padding + :left 15px + :top 0 + :height 2em + + .right + :z-index 5 + :top 5px + :right 1em + .done + :padding 1em + :bottom 2em + .right + :right 1em + diff --git a/spec/controllers/aspects_controller_spec.rb b/spec/controllers/aspects_controller_spec.rb index b7fd036c9..b2e29c5a7 100644 --- a/spec/controllers/aspects_controller_spec.rb +++ b/spec/controllers/aspects_controller_spec.rb @@ -156,6 +156,14 @@ describe AspectsController do response.should redirect_to(:back) end end + it "adds to aspect if the person_id is present" do + @aspect = @user.aspects.create(:name => "new aspect") + @user.aspects.stub!(:create).and_return(@aspect) + @controller.should_receive(:invite_or_add_contact_to_aspect).with( + anything(), @user2.person, @user.contact_for(@user2.person)) + + post :create, "aspect" => {"name" => "new aspect", :person_id => @user2.person.id, :share_with => true} + end end describe "#manage" do diff --git a/spec/intergration/receiving_spec.rb b/spec/intergration/receiving_spec.rb index f08e85b0c..d4fa78a7e 100644 --- a/spec/intergration/receiving_spec.rb +++ b/spec/intergration/receiving_spec.rb @@ -20,7 +20,6 @@ describe 'a user receives a post' do @user3 = eve @aspect3 = @user3.aspects.first - end it 'streams only one message to the everyone aspect when a multi-aspected contacts posts' do @@ -230,6 +229,36 @@ describe 'a user receives a post' do end end + + describe 'receiving mulitple versions of the same post from a remote pod' do + before do + @local_luke, @local_leia, @remote_raphael = set_up_friends + @post = Factory.build(:status_message, :message => 'hey', :guid => 12313123, :person => @remote_raphael, :created_at => 5.days.ago, :updated_at => 5.days.ago) + end + + it 'does not update created_at or updated_at when two people save the same post' do + @post = Factory.build(:status_message, :message => 'hey', :guid => 12313123, :person => @remote_raphael, :created_at => 5.days.ago, :updated_at => 5.days.ago) + xml = @post.to_diaspora_xml + receive_with_zord(@local_luke, @remote_raphael, xml) + sleep(2) + old_time = Time.now + receive_with_zord(@local_leia, @remote_raphael, xml) + (Post.find_by_guid @post.guid).updated_at.should be < old_time + (Post.find_by_guid @post.guid).created_at.should be < old_time + end + + it 'does not update the post if a new one is sent with a new created_at' do + @post = Factory.build(:status_message, :message => 'hey', :guid => 12313123, :person => @remote_raphael, :created_at => 5.days.ago) + old_time = @post.created_at + xml = @post.to_diaspora_xml + receive_with_zord(@local_luke, @remote_raphael, xml) + @post = Factory.build(:status_message, :message => 'hey', :guid => 12313123, :person => @remote_raphael, :created_at => 2.days.ago) + receive_with_zord(@local_luke, @remote_raphael, xml) + (Post.find_by_guid @post.guid).created_at.day.should == old_time.day + end + end + + describe 'salmon' do let(:post){@user1.post :status_message, :message => "hello", :to => @aspect.id} let(:salmon){@user1.salmon( post )} diff --git a/spec/lib/postzord/dispatch_spec.rb b/spec/lib/postzord/dispatch_spec.rb index a85f9f134..fab082890 100644 --- a/spec/lib/postzord/dispatch_spec.rb +++ b/spec/lib/postzord/dispatch_spec.rb @@ -76,13 +76,9 @@ describe Postzord::Dispatch do context "comments" do before do - @local_luke = Factory(:user_with_aspect, :username => "luke") - @local_leia = Factory(:user_with_aspect, :username => "leia") - @remote_raphael = Factory(:person, :diaspora_handle => "raphael@remote.net") - connect_users_with_aspects(@local_luke, @local_leia) - @local_leia.activate_contact(@remote_raphael, @local_leia.aspects.first) - @local_luke.activate_contact(@remote_raphael, @local_luke.aspects.first) + @local_luke, @local_leia, @remote_raphael = set_up_friends end + context "local luke's post is commented on by" do before do @post = @local_luke.post(:status_message, :message => "hello", :to => @local_luke.aspects.first) diff --git a/spec/models/aspect_spec.rb b/spec/models/aspect_spec.rb index ff4f668f4..87f6397d0 100644 --- a/spec/models/aspect_spec.rb +++ b/spec/models/aspect_spec.rb @@ -28,6 +28,12 @@ describe Aspect do }.should_not change(Aspect, :count) end + it 'validates case insensitiveness on names' do + lambda { + invalid_aspect = user.aspects.create(:name => "Losers ") + }.should_not change(Aspect, :count) + end + it 'has a 20 character limit on names' do aspect = Aspect.new(:name => "this name is really too too too too too long") aspect.valid?.should == false diff --git a/spec/models/services/facebook_spec.rb b/spec/models/services/facebook_spec.rb index e67076a13..39a67a4ea 100644 --- a/spec/models/services/facebook_spec.rb +++ b/spec/models/services/facebook_spec.rb @@ -40,6 +40,10 @@ describe Services::Facebook do { "name": "#{@user2_fb_name}", "id": "#{@user2_fb_id}" + }, + { + "name": "Person to Invite", + "id": "abc123" } ] } @@ -54,12 +58,14 @@ JSON @service.finder end + + context 'returns a hash' do it 'returns a hash' do @service.finder.class.should == Hash end it 'contains a name' do - @service.finder.values.first[:name].should == @user2_fb_name + @service.finder["#{@user2_fb_id}"][:name].should == @user2_fb_name end it 'contains a photo url' do pending @@ -68,21 +74,57 @@ JSON @service.finder.include?(@user2_fb_id).should be_true end it 'contains a diaspora person object' do - @service.finder.values.first[:person].should == @user2.person + @service.finder["#{@user2_fb_id}"][:person].should == @user2.person end it 'caches the profile' do - @service.finder.values.first[:person].profile.loaded?.should be_true + @service.finder["#{@user2_fb_id}"][:person].profile.loaded?.should be_true end it 'does not include the person if the search is disabled' do p = @user2.person.profile p.searchable = false p.save - @service.finder.values.first[:person].should be_nil + @service.finder["#{@user2_fb_id}"][:person].should be_nil end + + context "request" do + before do + @request = Request.diaspora_initialize(:from => @user2.person, :to => @user.person, :into => @user2.aspects.first) + Postzord::Receiver.new(@user, :object => @request, :person => @user2.person).receive_object + Request.count.should == 1 + end + it 'contains a request object if one has been sent' do + @service.finder["#{@user2_fb_id}"][:request].should == @request + end + + it 'caches the profile' do + @service.finder["#{@user2_fb_id}"][:request].sender.profile.loaded?.should be_true + end + + it 'caches the sender' do + @service.finder["#{@user2_fb_id}"][:request].sender.loaded?.should be_true + end + + end + it 'contains a contact object if connected' do connect_users(@user, @user.aspects.first, @user2, @user2.aspects.first) - @service.finder.values.first[:contact].should == @user.reload.contact_for(@user2.person) + @service.finder["#{@user2_fb_id}"][:contact].should == @user.reload.contact_for(@user2.person) end + + context 'only local' do + it 'does not return people who are remote' do + @service.finder(:local => true)['abc123'].should be nil + @service.finder(:local => true)["#{@user2_fb_id}"].should_not be_nil + end + end + + context 'only remote' do + it 'does not return people who are remote' do + @service.finder(:remote => true)['abc123'].should_not be nil + @service.finder(:remote => true)["#{@user2_fb_id}"].should be_nil + end + end + context 'already invited' do before do @user2.invitation_service = 'facebook' @@ -91,14 +133,14 @@ JSON end it 'contains an invitation if invited' do @inv = Invitation.create(:sender => @user, :recipient => @user2, :aspect => @user.aspects.first) - @service.finder.values.first[:invitation_id].should == @inv.id + @service.finder["#{@user2_fb_id}"][:invitation_id].should == @inv.id end it 'does not find the user with a wrong identifier' do @user2.invitation_identifier = 'dsaofhnadsoifnsdanf' @user2.save @inv = Invitation.create(:sender => @user, :recipient => @user2, :aspect => @user.aspects.first) - @service.finder.values.first[:invitation_id].should be_nil + @service.finder["#{@user2_fb_id}"][:invitation_id].should be_nil end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2eb3c978b..f2a30b80e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -34,6 +34,18 @@ RSpec.configure do |config| end end +def set_up_friends + local_luke = Factory(:user_with_aspect, :username => "luke") + local_leia = Factory(:user_with_aspect, :username => "leia") + remote_raphael = Factory(:person, :diaspora_handle => "raphael@remote.net") + connect_users_with_aspects(local_luke, local_leia) + local_leia.activate_contact(remote_raphael, local_leia.aspects.first) + local_luke.activate_contact(remote_raphael, local_luke.aspects.first) + + [local_luke, local_leia, remote_raphael] +end + + def alice #users(:alice) User.where(:username => 'alice').first