diff --git a/.travis.yml b/.travis.yml index d43ddbb42..0b826c315 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ branches: only: - 'master' - rvm: - 1.8.7 - ree diff --git a/Gemfile b/Gemfile index 66326040a..08482ea84 100644 --- a/Gemfile +++ b/Gemfile @@ -40,7 +40,7 @@ gem 'sqlite3' if ENV['DB'] == 'all' || ENV['DB'] == 'sqlite' # file uploading gem 'aws', '2.3.32' # upgrade to 2.4 breaks 1.8 >.< -gem 'carrierwave', '0.5.2' +gem 'carrierwave', '0.5.3' gem 'excon', '0.2.4' gem 'fastercsv', '1.5.4', :require => false gem 'fog', '0.3.25' @@ -97,6 +97,7 @@ gem 'haml', '3.1.2' gem 'mobile-fu' gem 'sass', '3.1.7' gem 'will_paginate', '3.0.pre2' +gem 'client_side_validations' # web @@ -117,6 +118,7 @@ end group :test do gem 'capybara', '~> 0.3.9' gem 'cucumber-rails', '0.3.2' + gem 'cucumber-api-steps', :require => false gem 'database_cleaner', '0.6.0' gem 'diaspora-client', :git => 'git://github.com/diaspora/diaspora-client.git' #"0.1.0", #:path => '~/workspace/diaspora-client' diff --git a/Gemfile.lock b/Gemfile.lock index c1982af08..e34e0787b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -104,7 +104,7 @@ GEM xml-simple bcrypt-ruby (2.1.4) builder (2.1.2) - bunny (0.7.6) + bunny (0.7.8) capistrano (2.5.19) highline net-scp (>= 1.0.0) @@ -120,7 +120,7 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) selenium-webdriver (>= 0.0.3) - carrierwave (0.5.2) + carrierwave (0.5.3) activesupport (~> 3.0) cgi_multipart_eof_fix (2.5.0) chef (0.9.12) @@ -128,17 +128,18 @@ GEM erubis extlib highline - json (<= 1.4.6, >= 1.4.4) + json (>= 1.4.4, <= 1.4.6) mixlib-authentication (>= 1.1.0) mixlib-cli (>= 1.1.0) mixlib-config (>= 1.1.2) mixlib-log (>= 1.2.0) moneta ohai (>= 0.5.7) - rest-client (< 1.7.0, >= 1.0.4) + rest-client (>= 1.0.4, < 1.7.0) uuidtools childprocess (0.2.2) ffi (~> 1.0.6) + client_side_validations (3.1.0) closure-compiler (1.1.4) cloudfiles (1.4.10) mime-types (>= 1.16) @@ -150,6 +151,9 @@ GEM gherkin (~> 2.5.0) json (>= 1.4.6) term-ansicolor (>= 1.0.6) + cucumber-api-steps (0.6) + cucumber (>= 0.8.3) + jsonpath (>= 0.1.2) cucumber-rails (0.3.2) cucumber (>= 0.8.0) culerity (0.2.15) @@ -161,7 +165,7 @@ GEM warden (~> 1.0.3) devise_invitable (0.5.0) devise (~> 1.3.1) - rails (<= 3.2, >= 3.0.0) + rails (>= 3.0.0, <= 3.2) diff-lcs (1.1.3) em-synchrony (0.2.0) eventmachine (>= 0.12.9) @@ -178,7 +182,7 @@ GEM faraday (0.6.1) addressable (~> 2.2.4) multipart-post (~> 1.1.0) - rack (< 2, >= 1.1.0) + rack (>= 1.1.0, < 2) faraday-stack (0.1.3) faraday (~> 0.6) faraday_middleware (0.6.5) @@ -208,7 +212,7 @@ GEM rspec-instafail (~> 0.1.8) ruby-progressbar (~> 0.0.10) gem_plugin (0.2.3) - gherkin (2.5.1) + gherkin (2.5.2) json (>= 1.4.6) haml (3.1.2) hashie (1.0.0) @@ -235,6 +239,8 @@ GEM jasmine-core (1.2.0.rc1) json (1.4.6) json_pure (1.6.1) + jsonpath (0.4.2) + multi_json jwt (0.1.3) json (>= 1.2.4) linecache (0.43) @@ -276,7 +282,7 @@ GEM net-ssh (2.0.24) net-ssh-gateway (1.1.0) net-ssh (>= 1.99.1) - newrelic_rpm (3.1.2) + newrelic_rpm (3.2.0) nokogiri (1.4.3.1) oa-basic (0.2.6) oa-core (= 0.2.6) @@ -313,7 +319,7 @@ GEM addressable (~> 2.2) ohai (0.5.8) extlib - json (<= 1.4.6, >= 1.4.4) + json (>= 1.4.4, <= 1.4.6) mixlib-cli mixlib-config mixlib-log @@ -350,7 +356,7 @@ GEM activesupport (= 3.0.10) bundler (~> 1.0) railties (= 3.0.10) - rails-i18n (0.1.9) + rails-i18n (0.1.10) i18n (~> 0.5) railties (3.0.10) actionpack (= 3.0.10) @@ -361,7 +367,8 @@ GEM rake (0.9.2) rash (0.3.0) hashie (~> 1.0.0) - rdoc (3.9.4) + rdoc (3.10) + json (~> 1.4) redcarpet (2.0.0b5) redis (2.2.2) redis-namespace (0.8.0) @@ -429,7 +436,7 @@ GEM sqlite3 (1.3.4) subexec (0.0.4) systemu (2.4.0) - term-ansicolor (1.0.6) + term-ansicolor (1.0.7) thin (1.2.11) daemons (>= 1.0.9) eventmachine (>= 0.12.6) @@ -454,13 +461,13 @@ GEM uuidtools (2.1.2) vegas (0.1.8) rack (>= 1.0.0) - warden (1.0.5) + warden (1.0.6) rack (>= 1.0) webmock (1.6.2) addressable (>= 2.2.2) crack (>= 0.1.7) will_paginate (3.0.pre2) - xml-simple (1.1.0) + xml-simple (1.1.1) yard (0.7.2) yui-compressor (0.9.6) POpen4 (>= 0.1.4) @@ -478,9 +485,11 @@ DEPENDENCIES capistrano (= 2.5.19) capistrano-ext (= 1.2.1) capybara (~> 0.3.9) - carrierwave (= 0.5.2) + carrierwave (= 0.5.3) chef (= 0.9.12) + client_side_validations cloudfiles (= 1.4.10) + cucumber-api-steps cucumber-rails (= 0.3.2) database_cleaner (= 0.6.0) devise (~> 1.3.1) diff --git a/app/controllers/activity_streams/photos_controller.rb b/app/controllers/activity_streams/photos_controller.rb index 58e3808c7..d0ff89ced 100644 --- a/app/controllers/activity_streams/photos_controller.rb +++ b/app/controllers/activity_streams/photos_controller.rb @@ -48,7 +48,7 @@ class ActivityStreams::PhotosController < ApplicationController end def show - @photo = current_user.find_visible_post_by_id(params[:id]) + @photo = current_user.find_visible_shareable_by_id(Photo, params[:id]) respond_with @photo end diff --git a/app/controllers/api/v0/tags_controller.rb b/app/controllers/api/v0/tags_controller.rb new file mode 100644 index 000000000..1ce401b1c --- /dev/null +++ b/app/controllers/api/v0/tags_controller.rb @@ -0,0 +1,9 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class Api::V0::TagsController < ApplicationController + def show + render :json => Api::V0::Serializers::Tag.new(params[:name]) + end +end diff --git a/app/controllers/api/v0/users_controller.rb b/app/controllers/api/v0/users_controller.rb new file mode 100644 index 000000000..5328a63c3 --- /dev/null +++ b/app/controllers/api/v0/users_controller.rb @@ -0,0 +1,13 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class Api::V0::UsersController < ApplicationController + def show + if user = User.find_by_username(params[:username]) + render :json => Api::V0::Serializers::User.new(user) + else + head :not_found + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8fe708d97..35b2c4f2d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -22,7 +22,8 @@ class ApplicationController < ActionController::Base :my_contacts_count, :only_sharing_count, :tag_followings, - :tags + :tags, + :open_publisher def ensure_http_referer_is_set request.env['HTTP_REFERER'] ||= '/aspects' @@ -121,7 +122,7 @@ class ApplicationController < ActionController::Base end def after_sign_in_path_for(resource) - stored_location_for(:user) || (current_user.getting_started? ? getting_started_path : aspects_path) + stored_location_for(:user) || (current_user.getting_started? ? getting_started_path : multi_path) end def tag_followings @@ -150,7 +151,7 @@ class ApplicationController < ActionController::Base def default_stream_action(stream_klass) authenticate_user! save_sort_order - @stream = stream_klass.new(current_user, :max_time => params[:max_time], :order => sort_order) + @stream = stream_klass.new(current_user, :max_time => max_time, :order => sort_order) if params[:only_posts] render :partial => 'shared/stream', :locals => {:posts => @stream.posts} diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index c2a4738ac..7ded695c1 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -14,7 +14,7 @@ class CommentsController < ApplicationController end def create - target = current_user.find_visible_post_by_id params[:post_id] + target = current_user.find_visible_shareable_by_id Post, params[:post_id] text = params[:text] if target @@ -56,7 +56,7 @@ class CommentsController < ApplicationController def index if user_signed_in? - @post = current_user.find_visible_post_by_id(params[:post_id]) + @post = current_user.find_visible_shareable_by_id(Post, params[:post_id]) else @post = Post.where(:id => params[:post_id], :public => true).includes(:author, :comments => :author).first end diff --git a/app/controllers/community_spotlight_controller.rb b/app/controllers/community_spotlight_controller.rb new file mode 100644 index 000000000..837d77bdb --- /dev/null +++ b/app/controllers/community_spotlight_controller.rb @@ -0,0 +1,7 @@ +require File.join(Rails.root, 'lib', 'stream', 'community_spotlight') + +class CommunitySpotlightController < ApplicationController + def index + default_stream_action(Stream::CommunitySpotlight) + end +end diff --git a/app/controllers/contacts_controller.rb b/app/controllers/contacts_controller.rb index 450b00b1a..a35902b81 100644 --- a/app/controllers/contacts_controller.rb +++ b/app/controllers/contacts_controller.rb @@ -38,9 +38,9 @@ class ContactsController < ApplicationController render :layout => false end - def featured - @featured = true - @people = Person.featured_users + def spotlight + @spotlight = true + @people = Person.community_spotlight end private diff --git a/app/controllers/conversations_controller.rb b/app/controllers/conversations_controller.rb index bc1586290..3915be1d6 100644 --- a/app/controllers/conversations_controller.rb +++ b/app/controllers/conversations_controller.rb @@ -67,7 +67,7 @@ class ConversationsController < ApplicationController @contact_ids = "" - @contacts_json = all_contacts_and_ids.to_json.gsub!(/(")/, '\\"') + @contacts_json = all_contacts_and_ids.to_json if params[:contact_id] @contact_ids = current_user.contacts.find(params[:contact_id]).id elsif params[:aspect_id] diff --git a/app/controllers/featured_users_controller.rb b/app/controllers/featured_users_controller.rb deleted file mode 100644 index e5cc606d6..000000000 --- a/app/controllers/featured_users_controller.rb +++ /dev/null @@ -1,7 +0,0 @@ -require File.join(Rails.root, 'lib', 'stream', 'featured_users') - -class FeaturedUsersController < ApplicationController - def index - default_stream_action(Stream::FeaturedUsers) - end -end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index c7d7d21c0..2b677fdac 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -6,7 +6,7 @@ class HomeController < ApplicationController def show if current_user - redirect_to :controller => 'aspects', :action => 'index' + redirect_to multi_path elsif is_mobile_device? redirect_to user_session_path else diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb index 12ad5562a..d8a49fad4 100644 --- a/app/controllers/likes_controller.rb +++ b/app/controllers/likes_controller.rb @@ -59,10 +59,10 @@ class LikesController < ApplicationController def target @target ||= if params[:post_id] - current_user.find_visible_post_by_id(params[:post_id]) + current_user.find_visible_shareable_by_id(Post, params[:post_id]) else comment = Comment.find(params[:comment_id]) - comment = nil unless current_user.find_visible_post_by_id(comment.post_id) + comment = nil unless current_user.find_visible_shareable_by_id(Post, comment.commentable_id) comment end end diff --git a/app/controllers/multis_controller.rb b/app/controllers/multis_controller.rb new file mode 100644 index 000000000..42f73f606 --- /dev/null +++ b/app/controllers/multis_controller.rb @@ -0,0 +1,11 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +require File.join(Rails.root, 'lib', 'stream', 'multi') + +class MultisController < ApplicationController + def index + default_stream_action(Stream::Multi) + end +end diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 99340eaa7..c27df96c7 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -50,7 +50,7 @@ class NotificationsController < VannaController post_process :html do def post_read_all(json) - Response.new(:status => 302, :location => aspects_path) + Response.new(:status => 302, :location => multi_path) end end diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index 28daa5bba..36990b730 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -2,6 +2,8 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. +require File.join(Rails.root, "lib", 'stream', "person") + class PeopleController < ApplicationController before_filter :authenticate_user!, :except => [:show] @@ -86,7 +88,9 @@ class PeopleController < ApplicationController @aspect = :profile @share_with = (params[:share_with] == 'true') - max_time = params[:max_time] ? Time.at(params[:max_time].to_i) : Time.now + @stream = Stream::Person.new(current_user, @person, + :max_time => max_time) + @profile = @person.profile unless params[:format] == "json" # hovercard @@ -104,22 +108,11 @@ class PeopleController < ApplicationController @contacts_of_contact_count = 0 @contacts_of_contact = [] end - - if (@person != current_user.person) && !@contact.persisted? - @commenting_disabled = true - else - @commenting_disabled = false - end - @posts = current_user.posts_from(@person).where(:type => ["StatusMessage", "Reshare", "ActivityStreams::Photo"]).includes(:comments).limit(15).where(StatusMessage.arel_table[:created_at].lt(max_time)) - else - @commenting_disabled = true - @posts = @person.posts.where(:type => ["StatusMessage", "Reshare", "ActivityStreams::Photo"], :public => true).includes(:comments).limit(15).where(StatusMessage.arel_table[:created_at].lt(max_time)).order('posts.created_at DESC') end - @posts.includes(:author => :profile) end if params[:only_posts] - render :partial => 'shared/stream', :locals => {:posts => @posts} + render :partial => 'shared/stream', :locals => {:posts => @stream.posts} else respond_to do |format| format.all { respond_with @person, :locals => {:post_type => :all} } diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 1afafd9b9..b29f39fd8 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -29,7 +29,7 @@ class PhotosController < ApplicationController @contacts_of_contact_count = 0 end - @posts = current_user.posts_from(@person).where(:type => 'Photo').paginate(:page => params[:page]) + @posts = current_user.photos_from(@person).paginate(:page => params[:page]) render 'people/show' @@ -118,7 +118,7 @@ class PhotosController < ApplicationController end def destroy - photo = current_user.posts.where(:id => params[:id]).first + photo = current_user.photos.where(:id => params[:id]).first if photo current_user.retract(photo) @@ -148,7 +148,7 @@ class PhotosController < ApplicationController end def edit - if @photo = current_user.posts.where(:id => params[:id]).first + if @photo = current_user.photos.where(:id => params[:id]).first respond_with @photo else redirect_to person_photos_path(current_user.person) @@ -156,7 +156,7 @@ class PhotosController < ApplicationController end def update - photo = current_user.posts.where(:id => params[:id]).first + photo = current_user.photos.where(:id => params[:id]).first if photo if current_user.update_post( photo, params[:photo] ) flash.now[:notice] = I18n.t 'photos.update.notice' @@ -187,7 +187,7 @@ class PhotosController < ApplicationController end def photo - @photo ||= current_user.find_visible_post_by_id(params[:id], :type => 'Photo') + @photo ||= current_user.find_visible_shareable_by_id(Photo, params[:id]) end def additional_photos diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 5b97ed27e..39b502e2e 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -18,7 +18,7 @@ class PostsController < ApplicationController key = params[:id].to_s.length <= 8 ? :id : :guid if user_signed_in? - @post = current_user.find_visible_post_by_id(params[:id], :key => key) + @post = current_user.find_visible_shareable_by_id(Post, params[:id], :key => key) else @post = Post.where(key => params[:id], :public => true).includes(:author, :comments => :author).first end @@ -30,10 +30,6 @@ class PostsController < ApplicationController notification.save end - if is_mobile_device? - @comments = @post.comments - end - respond_to do |format| format.xml{ render :xml => @post.to_diaspora_xml } format.mobile{render 'posts/show.mobile.haml'} diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 85d2eb3f4..171ede5b0 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -4,6 +4,9 @@ class ProfilesController < ApplicationController before_filter :authenticate_user! + + respond_to :html + respond_to :js, :only => :update def edit @person = current_user.person @aspect = :person_edit @@ -35,18 +38,30 @@ class ProfilesController < ApplicationController :id => params[:photo_id]).first if params[:photo_id] if current_user.update_profile params[:profile] - flash[:notice] = I18n.t 'profiles.update.updated' - if current_user.getting_started? - redirect_to getting_started_path - else - redirect_to edit_profile_path + respond_to do |format| + format.js { render :nothing => true, :status => 200 } + format.html { + flash[:notice] = I18n.t 'profiles.update.updated' + if current_user.getting_started? + + redirect_to getting_started_path + else + redirect_to edit_profile_path + end + } end + else - flash[:error] = I18n.t 'profiles.update.failed' - if params[:getting_started] - redirect_to getting_started_path(:step => params[:getting_started]) - else - redirect_to edit_profile_path + respond_to do |format| + format.js { render :nothing => true, :status => 200 } + format.html { + flash[:error] = I18n.t 'profiles.update.failed' + if params[:getting_started] + redirect_to getting_started_path(:step => params[:getting_started]) + else + redirect_to edit_profile_path + end + } end end diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 09d6cbe7d..1d4ad964c 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -26,9 +26,26 @@ class ServicesController < ApplicationController :uid => auth['uid']) current_user.services << service - flash[:notice] = I18n.t 'services.create.success' + if service.persisted? + fetch_photo = current_user.person.profile[:image_url].blank? + + current_user.update_profile(current_user.person.profile.from_omniauth_hash(user)) + Resque.enqueue(Jobs::FetchProfilePhoto, current_user.id, service.id, user["image"]) if fetch_photo + + flash[:notice] = I18n.t 'services.create.success' + else + flash[:error] = I18n.t 'services.create.failure' + + if existing_service = Service.where(:type => service.type.to_s, :uid => service.uid).first + flash[:error] << I18n.t('services.create.already_authorized', + :diaspora_id => existing_service.user.person.profile.diaspora_handle, + :service_name => provider.camelize ) +:A + end + end + if current_user.getting_started - redirect_to getting_started_path(:step => 3) + redirect_to getting_started_path else redirect_to services_url end diff --git a/app/controllers/post_visibilities_controller.rb b/app/controllers/share_visibilities_controller.rb similarity index 67% rename from app/controllers/post_visibilities_controller.rb rename to app/controllers/share_visibilities_controller.rb index eb0c46855..b7fca1386 100644 --- a/app/controllers/post_visibilities_controller.rb +++ b/app/controllers/share_visibilities_controller.rb @@ -3,18 +3,21 @@ # the COPYRIGHT file. # -class PostVisibilitiesController < ApplicationController +class ShareVisibilitiesController < ApplicationController before_filter :authenticate_user! def update #note :id references a postvisibility + params[:shareable_id] ||= params[:post_id] + params[:shareable_type] ||= 'Post' @post = accessible_post @contact = current_user.contact_for(@post.author) - if @contact && @vis = PostVisibility.where(:contact_id => @contact.id, - :post_id => params[:post_id]).first - @vis.hidden = !@vis.hidden + if @contact && @vis = ShareVisibility.where(:contact_id => @contact.id, + :shareable_id => params[:shareable_id], + :shareable_type => params[:shareable_type]).first + @vis.hidden = !@vis.hidden if @vis.save update_cache(@vis) render 'update' diff --git a/app/controllers/soups_controller.rb b/app/controllers/soups_controller.rb deleted file mode 100644 index c44b7f3be..000000000 --- a/app/controllers/soups_controller.rb +++ /dev/null @@ -1,9 +0,0 @@ -require File.join(Rails.root, 'lib', 'stream', 'soup') - -class SoupsController < ApplicationController - #before_filter :redirect_unless_admin - - def index - default_stream_action(Stream::Soup) - end -end diff --git a/app/controllers/status_messages_controller.rb b/app/controllers/status_messages_controller.rb index 0f3c39e5c..b15a447c2 100644 --- a/app/controllers/status_messages_controller.rb +++ b/app/controllers/status_messages_controller.rb @@ -4,6 +4,8 @@ class StatusMessagesController < ApplicationController before_filter :authenticate_user! + + before_filter :remove_getting_started, :only => [:create] respond_to :html respond_to :mobile @@ -96,4 +98,11 @@ class StatusMessagesController < ApplicationController def comments_expanded true end + + def remove_getting_started + if current_user.getting_started == true + current_user.update_attributes(:getting_started => false) + end + true + end end diff --git a/app/controllers/tag_followings_controller.rb b/app/controllers/tag_followings_controller.rb index 9262c9c87..589b68079 100644 --- a/app/controllers/tag_followings_controller.rb +++ b/app/controllers/tag_followings_controller.rb @@ -51,4 +51,16 @@ class TagFollowingsController < ApplicationController redirect_to tag_path(:name => params[:name]) end end + + def create_multiple + tags = params[:tags].split(",") + tags.each do |tag| + tag_name = tag.gsub(/^#/,"") + + @tag = ActsAsTaggableOn::Tag.find_or_create_by_name(tag_name) + @tag_following = current_user.tag_followings.create(:tag_id => @tag.id) + end + + redirect_to multi_path + end end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index d05e1bab3..d5757bedf 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -2,6 +2,7 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. require File.join(Rails.root, 'app', 'models', 'acts_as_taggable_on_tag') +require File.join(Rails.root, 'lib', 'stream', 'tag') class TagsController < ApplicationController skip_before_filter :which_action_and_user @@ -34,34 +35,17 @@ class TagsController < ApplicationController end def show - params[:name].downcase! - @aspect = :tag - @tag = ActsAsTaggableOn::Tag.find_by_name(params[:name]) - @tag_follow_count = @tag.try(:followed_count).to_i - - if current_user - @posts = StatusMessage.owned_or_visible_by_user(current_user) - else - @posts = StatusMessage.all_public - end - - @posts = @posts.tagged_with(params[:name]).for_a_stream(max_time, 'created_at') - - @commenting_disabled = true - params[:prefill] = "##{params[:name]} " + @stream = Stream::Tag.new(current_user, params[:name], :max_time => max_time, :page => params[:page]) if params[:only_posts] - render :partial => 'shared/stream', :locals => {:posts => @posts} - else - profiles = Profile.tagged_with(params[:name]).where(:searchable => true).select('profiles.id, profiles.person_id') - @people = Person.where(:id => profiles.map{|p| p.person_id}).paginate(:page => params[:page], :per_page => 15) - @people_count = Person.where(:id => profiles.map{|p| p.person_id}).count + render :partial => 'shared/stream', :locals => {:posts => @stream.posts} + return end end def tag_followed? if @tag_followed.nil? - @tag_followed = TagFollowing.joins(:tag).where(:tags => {:name => params[:name]}, :user_id => current_user.id).exists? #, + @tag_followed = TagFollowing.joins(:tag).where(:tags => {:name => params[:name]}, :user_id => current_user.id).exists? end @tag_followed end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4188a98b0..0628ce12f 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -41,12 +41,20 @@ class UsersController < ApplicationController else flash[:error] = I18n.t 'users.update.password_not_changed' end - elsif u[:language] - if @user.update_attributes(:language => u[:language]) - I18n.locale = @user.language - flash[:notice] = I18n.t 'users.update.language_changed' + elsif u[:show_community_spotlight_in_stream] || u[:getting_started] + if @user.update_attributes(u) + flash[:notice] = I18n.t 'users.update.settings_updated' + redirect_to multi_path + return else - flash[:error] = I18n.t 'users.update.language_not_changed' + flash[:notice] = I18n.t 'users.update.settings_not_updated' + end + elsif u[:language] + if @user.update_attributes(u) + I18n.locale = @user.language + flash[:notice] = I18n.t 'users.update.language_updated' + else + flash[:error] = I18n.t 'users.update.language_not_updated' end elsif u[:email] @user.unconfirmed_email = u[:email] @@ -97,13 +105,12 @@ class UsersController < ApplicationController @user = current_user @person = @user.person @profile = @user.profile - @services = @user.services - @step = 0 render "users/getting_started" end def logged_out + @page = :logged_out if user_signed_in? redirect_to root_path end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index fd7bef727..87c9cd862 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -64,7 +64,7 @@ module ApplicationHelper if current_user.contacts.size > 0 contacts_path else - featured_users_path + community_spotlight_path end end diff --git a/app/helpers/aspect_global_helper.rb b/app/helpers/aspect_global_helper.rb index 276f3591b..d10338bf5 100644 --- a/app/helpers/aspect_global_helper.rb +++ b/app/helpers/aspect_global_helper.rb @@ -5,7 +5,7 @@ module AspectGlobalHelper def aspects_with_post(aspects, post) aspects.select do |aspect| - AspectVisibility.exists?(:aspect_id => aspect.id, :post_id => post.id) + AspectVisibility.exists?(:aspect_id => aspect.id, :shareable_id => post.id, :shareable_type => 'Post') end end @@ -21,7 +21,7 @@ module AspectGlobalHelper str = "" link = opts.delete(:link) if !link - str << link_to(aspect.name, "#", 'data-guid' => aspect.id, :class => 'hard_aspect_link').html_safe + str << link_to(aspect.name, "#", 'data-guid' => aspect.id).html_safe else str << link_for_aspect(aspect).html_safe end @@ -32,7 +32,7 @@ module AspectGlobalHelper str = "" aspects.each do |aspect| str << '
  • ' - str << link_for_aspect(aspect, :params => opts, 'data-guid' => aspect.id, :class => 'hard_aspect_link').html_safe + str << link_for_aspect(aspect, :params => opts, 'data-guid' => aspect.id).html_safe str << '
  • ' end str.html_safe @@ -42,8 +42,6 @@ module AspectGlobalHelper opts[:params] ||= {} params ||= {} opts[:params] = opts[:params].merge("a_ids[]" => aspect.id, :created_at => params[:created_at]) - opts[:class] ||= "" - opts[:class] << " hard_aspect_link" opts['data-guid'] = aspect.id link_to aspect.name, aspects_path( opts[:params] ), opts @@ -71,7 +69,7 @@ module AspectGlobalHelper klass = checked ? "selected" : "" str = < +
  • #{aspect.name}
  • LISTITEM diff --git a/app/helpers/getting_started_helper.rb b/app/helpers/getting_started_helper.rb index 5bd271be4..3d8bbc7df 100644 --- a/app/helpers/getting_started_helper.rb +++ b/app/helpers/getting_started_helper.rb @@ -3,18 +3,6 @@ # the COPYRIGHT file. module GettingStartedHelper - # @return [Boolean] The user has filled out all profile fields - def has_completed_profile? - profile = current_user.person.profile - [:full_name, :image_url, - :birthday, :gender, - :bio, :location, - :tag_string].map! do |attr| - return false if profile.send(attr).blank? - end - true - end - # @return [Boolean] The user has connected at least one service def has_connected_services? AppConfig[:configured_services].blank? || current_user.services.size > 0 @@ -29,7 +17,7 @@ module GettingStartedHelper def has_few_followed_tags? current_user.followed_tags.size > 2 end - + # @return [Boolean] The user has connected to cubbi.es def has_connected_cubbies? current_user.authorizations.size > 0 @@ -40,15 +28,6 @@ module GettingStartedHelper current_user.getting_started == false end - # @return [String] Welcome text with or without the current_user's first_name - def welcome_text - if current_user.person.profile.first_name.present? - t('users.getting_started.welcome_with_name', :name => current_user.first_name) - else - t('users.getting_started.welcome') - end - end - def tag_link(tag_name) if tag_followed?(tag_name) link_to "##{tag_name}", tag_followings_path(tag_name), :method => :delete, :class => "featured_tag followed" diff --git a/app/helpers/interim_stream_hackiness_helper.rb b/app/helpers/interim_stream_hackiness_helper.rb new file mode 100644 index 000000000..9b57ddb7a --- /dev/null +++ b/app/helpers/interim_stream_hackiness_helper.rb @@ -0,0 +1,63 @@ +module InterimStreamHackinessHelper + def commenting_disabled?(post) + return true unless user_signed_in? + if defined?(@commenting_disabled) + @commenting_disabled + elsif defined?(@stream) + !@stream.can_comment?(post) + else + false + end + end + + ##### These methods need to go away once we pass publisher object into the partial ###### + def publisher_prefill_text + if params[:prefill].present? + params[:prefill] + elsif defined?(@stream) + @stream.publisher.prefill + else + nil + end + end + + def from_group(post) + if defined?(@stream) && params[:controller] == 'multis' + @stream.post_from_group(post) + else + [] + end + end + + def what_stream_sentence(post) + from_group(post).map{|x| I18n.t("streams.#{x.to_s}")}.to_sentence + end + + def stream_settings_link(post) + link_to "", "#{edit_user_path}#stream-preferences" + end + + def publisher_open + if defined?(@stream) + @stream.publisher.open? + else + false + end + end + + def publisher_public + if defined?(@stream) + @stream.publisher.public? + else + false + end + end + + def publisher_explain + if defined?(@stream) + @stream.publisher.public? + else + false + end + end +end diff --git a/app/helpers/people_helper.rb b/app/helpers/people_helper.rb index 86ca83d69..49e656ba8 100644 --- a/app/helpers/people_helper.rb +++ b/app/helpers/people_helper.rb @@ -37,7 +37,7 @@ module PeopleHelper def person_image_tag(person, size=nil) size ||= :thumb_small - "\"#{h(person.name)}\"".html_safe + "\"#{h(person.name)}\"".html_safe end def person_image_link(person, opts={}) diff --git a/app/helpers/publisher_helper.rb b/app/helpers/publisher_helper.rb index 235fafbdb..d38f8a365 100644 --- a/app/helpers/publisher_helper.rb +++ b/app/helpers/publisher_helper.rb @@ -14,4 +14,8 @@ module PublisherHelper def public_helper_text (public_value)? t('javascripts.publisher.public'): t('javascripts.publisher.limited') end + + def all_aspects_selected?(selected_aspects) + @all_aspects_selected ||= all_aspects.size == selected_aspects.size + end end diff --git a/app/helpers/reshares_helper.rb b/app/helpers/reshares_helper.rb index 5b97adc39..f5131814f 100644 --- a/app/helpers/reshares_helper.rb +++ b/app/helpers/reshares_helper.rb @@ -7,6 +7,15 @@ module ResharesHelper end end + def resharable?(post) + if reshare?(post) + # Reshare post is resharable if you're not the original author nor the resharer + post.root.present? && post.root.author_id != current_user.person.id && post.author_id != current_user.person.id + else + post.author_id != current_user.person.id && post.public? + end + end + def reshare_link(post) if reshare?(post) return unless post.root diff --git a/app/helpers/stream_helper.rb b/app/helpers/stream_helper.rb index 06bdf29ce..6144989bb 100644 --- a/app/helpers/stream_helper.rb +++ b/app/helpers/stream_helper.rb @@ -5,19 +5,19 @@ module StreamHelper def next_page_path(opts ={}) if controller.instance_of?(TagsController) - tag_path(:name => @tag.name, :max_time => @posts.last.created_at.to_i) + tag_path(:name => @stream.tag_name, :max_time => time_for_scroll(opts[:ajax_stream], @stream)) elsif controller.instance_of?(AppsController) "/apps/1?#{{:max_time => @posts.last.created_at.to_i}.to_param}" elsif controller.instance_of?(PeopleController) - person_path(@person, :max_time => @posts.last.created_at.to_i) + person_path(@person, :max_time => time_for_scroll(opts[:ajax_stream], @stream)) elsif controller.instance_of?(TagFollowingsController) tag_followings_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order]) - elsif controller.instance_of?(FeaturedUsersController) - featured_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order]) + elsif controller.instance_of?(CommunitySpotlightController) + spotlight_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order]) elsif controller.instance_of?(MentionsController) mentions_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order]) - elsif controller.instance_of?(SoupsController) - soup_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order]) + elsif controller.instance_of?(MultisController) + multi_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order]) elsif controller.instance_of?(PostsController) public_stream_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :sort_order => session[:sort_order]) elsif controller.instance_of?(AspectsController) diff --git a/app/models/api/v0/serializers/tag.rb b/app/models/api/v0/serializers/tag.rb new file mode 100644 index 000000000..bd378607d --- /dev/null +++ b/app/models/api/v0/serializers/tag.rb @@ -0,0 +1,19 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class Api::V0::Serializers::Tag + + def initialize(tag) + @stream = Stream::Tag.new(nil, tag) + end + + def as_json(opts={}) + { + "name" => @stream.tag_name, + "person_count" => @stream.tagged_people_count, + "followed_count" => @stream.tag_follow_count, + "posts" => [] + } + end +end diff --git a/app/models/api/v0/serializers/user.rb b/app/models/api/v0/serializers/user.rb new file mode 100644 index 000000000..2dc94fc07 --- /dev/null +++ b/app/models/api/v0/serializers/user.rb @@ -0,0 +1,20 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class Api::V0::Serializers::User + def initialize(user) + @person = user.person + @profile = @person.profile + end + + def as_json(opts={}) + { + "diaspora_id" => @person.diaspora_handle, + "first_name" => @profile.first_name, + "last_name" => @profile.last_name, + "image_url" => @profile.image_url, + "searchable" => @profile.searchable + } + end +end diff --git a/app/models/aspect.rb b/app/models/aspect.rb index 55dd2dccb..c87d60c93 100644 --- a/app/models/aspect.rb +++ b/app/models/aspect.rb @@ -9,7 +9,8 @@ class Aspect < ActiveRecord::Base has_many :contacts, :through => :aspect_memberships has_many :aspect_visibilities - has_many :posts, :through => :aspect_visibilities + has_many :posts, :through => :aspect_visibilities, :source => :shareable, :source_type => 'Post' + has_many :photos, :through => :aspect_visibilities, :source => :shareable, :source_type => 'Photo' validates :name, :presence => true, :length => { :maximum => 20 } @@ -24,5 +25,17 @@ class Aspect < ActiveRecord::Base def to_s name end + + def << (shareable) + case shareable + when Post + self.posts << shareable + when Photo + self.photos << shareable + else + raise "Unknown shareable type '#{shareable.class.base_class.to_s}'" + end + end + end diff --git a/app/models/aspect_visibility.rb b/app/models/aspect_visibility.rb index 42f560ead..a5593b834 100644 --- a/app/models/aspect_visibility.rb +++ b/app/models/aspect_visibility.rb @@ -7,7 +7,7 @@ class AspectVisibility < ActiveRecord::Base belongs_to :aspect validates :aspect, :presence => true - belongs_to :post - validates :post, :presence => true + belongs_to :shareable, :polymorphic => true + validates :shareable, :presence => true end diff --git a/app/models/comment.rb b/app/models/comment.rb index 77eade82c..71cfae25f 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -23,7 +23,8 @@ class Comment < ActiveRecord::Base xml_attr :text xml_attr :diaspora_handle - belongs_to :post + belongs_to :commentable, :touch => true, :polymorphic => true + alias_attribute :post, :commentable belongs_to :author, :class_name => 'Person' validates :text, :presence => true, :length => { :maximum => 2500 } diff --git a/app/models/contact.rb b/app/models/contact.rb index fa3094b3e..ba7358911 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -12,8 +12,8 @@ class Contact < ActiveRecord::Base has_many :aspect_memberships has_many :aspects, :through => :aspect_memberships - has_many :post_visibilities - has_many :posts, :through => :post_visibilities + has_many :share_visibilities, :source => :shareable, :source_type => 'Post' + has_many :posts, :through => :share_visibilities, :source => :shareable, :source_type => 'Post' validate :not_contact_for_self @@ -54,9 +54,9 @@ class Contact < ActiveRecord::Base :into => aspects.first) end - def receive_post(post) - PostVisibility.create!(:post_id => post.id, :contact_id => self.id) - post.socket_to_user(self.user, :aspect_ids => self.aspect_ids) if post.respond_to? :socket_to_user + def receive_shareable(shareable) + ShareVisibility.create!(:shareable_id => shareable.id, :shareable_type => shareable.class.base_class.to_s, :contact_id => self.id) + shareable.socket_to_user(self.user, :aspect_ids => self.aspect_ids) if shareable.respond_to? :socket_to_user end def contacts diff --git a/app/models/jobs/fetch_profile_photo.rb b/app/models/jobs/fetch_profile_photo.rb new file mode 100644 index 000000000..d750ee3ba --- /dev/null +++ b/app/models/jobs/fetch_profile_photo.rb @@ -0,0 +1,28 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + + +module Jobs + class FetchProfilePhoto < Base + @queue = :photos + def self.perform(user_id, service_id, fallback_image_url = nil) + service = Service.find(service_id) + + image_url = service.profile_photo_url + image_url ||= fallback_image_url + + return unless image_url + + user = User.find(user_id) + + @photo = Photo.diaspora_initialize(:author => user.person, :image_url => image_url, :pending => true) + @photo.save! + + profile_params = {:image_url => @photo.url(:thumb_large), + :image_url_medium => @photo.url(:thumb_medium), + :image_url_small => @photo.url(:thumb_small)} + user.update_profile(profile_params) + end + end +end diff --git a/app/models/notification.rb b/app/models/notification.rb index 1a1bbb6c1..40711786a 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -47,7 +47,7 @@ class Notification < ActiveRecord::Base private def self.concatenate_or_create(recipient, target, actor, notification_type) - return nil if post_visiblity_is_hidden?(recipient, target) + return nil if share_visiblity_is_hidden?(recipient, target) if n = notification_type.where(:target_id => target.id, :target_type => target.class.base_class, :recipient_id => recipient.id, @@ -68,7 +68,7 @@ private def self.make_notification(recipient, target, actor, notification_type) - return nil if post_visiblity_is_hidden?(recipient, target) + return nil if share_visiblity_is_hidden?(recipient, target) n = notification_type.new(:target => target, :recipient_id => recipient.id) n.actors = n.actors | [actor] @@ -78,12 +78,12 @@ private end #horrible hack that should not be here! - def self.post_visiblity_is_hidden?(recipient, post) + def self.share_visiblity_is_hidden?(recipient, post) return false unless post.is_a?(Post) contact = recipient.contact_for(post.author) return false unless contact && recipient && post - pv = PostVisibility.where(:contact_id => contact.id, :post_id => post.id).first + pv = ShareVisibility.where(:contact_id => contact.id, :shareable_id => post.id, :shareable_type => post.class.base_class.to_s).first pv.present? ? pv.hidden? : false end end diff --git a/app/models/person.rb b/app/models/person.rb index b93e015ce..0d6d40829 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -28,6 +28,7 @@ class Person < ActiveRecord::Base has_many :contacts, :dependent => :destroy # Other people's contacts for this person has_many :posts, :foreign_key => :author_id, :dependent => :destroy # This person's own posts + has_many :photos, :foreign_key => :author_id, :dependent => :destroy # This person's own photos has_many :comments, :foreign_key => :author_id, :dependent => :destroy # This person's own comments belongs_to :owner, :class_name => 'User' @@ -58,8 +59,10 @@ class Person < ActiveRecord::Base select("DISTINCT people.*") } - def self.featured_users - AppConfig[:featured_users].present? ? Person.where(:diaspora_handle => AppConfig[:featured_users]) : [] + scope :profile_tagged_with, lambda{|tag_name| joins(:profile => :tags).where(:profile => {:tags => {:name => tag_name}}).where('profiles.searchable IS TRUE') } + + def self.community_spotlight + AppConfig[:community_spotlight].present? ? Person.where(:diaspora_handle => AppConfig[:community_spotlight]) : [] end # Set a default of an empty profile when a new Person record is instantiated. @@ -76,7 +79,6 @@ class Person < ActiveRecord::Base self.profile ||= Profile.new unless profile_set end - def self.find_from_id_or_username(params) p = if params[:id].present? Person.where(:id => params[:id]).first @@ -136,8 +138,6 @@ class Person < ActiveRecord::Base Person.searchable.where(sql, *tokens) end - - def name(opts = {}) if self.profile.nil? fix_profile @@ -146,14 +146,17 @@ class Person < ActiveRecord::Base end def self.name_from_attrs(first_name, last_name, diaspora_handle) - first_name.blank? ? diaspora_handle : "#{first_name.to_s.strip} #{last_name.to_s.strip}" + first_name.blank? && last_name.blank? ? diaspora_handle : "#{first_name.to_s.strip} #{last_name.to_s.strip}".strip end def first_name @first_name ||= if profile.nil? || profile.first_name.nil? || profile.first_name.blank? self.diaspora_handle.split('@').first else - profile.first_name.to_s + names = profile.first_name.to_s.split(/\s/) + str = names[0...-1].join(' ') + str = names[0] if str.blank? + str end end @@ -248,7 +251,7 @@ class Person < ActiveRecord::Base end def has_photos? - self.posts.where(:type => "Photo").exists? + self.photos.exists? end def as_json( opts = {} ) @@ -272,6 +275,8 @@ class Person < ActiveRecord::Base person.update_url(url) end end + + # @param person [Person] # @param url [String] diff --git a/app/models/photo.rb b/app/models/photo.rb index 75b644276..c45784c83 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -2,8 +2,12 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. -class Photo < Post +class Photo < ActiveRecord::Base require 'carrierwave/orm/activerecord' + + include Diaspora::Commentable + include Diaspora::Shareable + mount_uploader :processed_image, ProcessedImage mount_uploader :unprocessed_image, UnprocessedImage @@ -40,11 +44,25 @@ class Photo < Post end def self.diaspora_initialize(params = {}) - photo = super(params) - image_file = params.delete(:user_file) + photo = self.new params.to_hash + photo.author = params[:author] + photo.public = params[:public] if params[:public] + photo.pending = params[:pending] if params[:pending] + photo.diaspora_handle = photo.author.diaspora_handle + photo.random_string = ActiveSupport::SecureRandom.hex(10) - photo.unprocessed_image.store! image_file + + if params[:user_file] + image_file = params.delete(:user_file) + photo.unprocessed_image.store! image_file + + elsif params[:image_url] + photo.remote_unprocessed_image_url = params[:image_url] + photo.unprocessed_image.store! + end + photo.update_remote_path + photo end diff --git a/app/models/post.rb b/app/models/post.rb index 048990f7c..559564e69 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -3,26 +3,14 @@ # the COPYRIGHT file. class Post < ActiveRecord::Base - require File.join(Rails.root, 'lib/diaspora/web_socket') include ApplicationHelper - include ROXML - include Diaspora::Webhooks - include Diaspora::Guid include Diaspora::Likeable + include Diaspora::Commentable + include Diaspora::Shareable - xml_attr :diaspora_handle xml_attr :provider_display_name - xml_attr :public - xml_attr :created_at - has_many :comments, :order => 'created_at', :dependent => :destroy - - has_many :aspect_visibilities - has_many :aspects, :through => :aspect_visibilities - - has_many :post_visibilities - has_many :contacts, :through => :post_visibilities has_many :mentions, :dependent => :destroy has_many :reshares, :class_name => "Reshare", :foreign_key => :root_guid, :primary_key => :guid @@ -30,49 +18,18 @@ class Post < ActiveRecord::Base belongs_to :o_embed_cache - belongs_to :author, :class_name => 'Person' - - validates :guid, :uniqueness => true - after_create :cache_for_author #scopes - scope :all_public, where(:public => true, :pending => false) scope :includes_for_a_stream, includes(:o_embed_cache, {:author => :profile}, :mentions => {:person => :profile}) #note should include root and photos, but i think those are both on status_message def self.for_a_stream(max_time, order) - by_max_time(max_time, order). - includes_for_a_stream. - where(:type => Stream::Base::TYPES_OF_POST_IN_STREAM). - limit(15) + self.for_visible_shareable_sql(max_time, order). + includes_for_a_stream end - def self.by_max_time(max_time, order='created_at') - where("posts.#{order} < ?", max_time).order("posts.#{order} desc") - end ############# - def diaspora_handle - read_attribute(:diaspora_handle) || self.author.diaspora_handle - end - - def user_refs - if AspectVisibility.exists?(:post_id => self.id) - self.post_visibilities.count + 1 - else - self.post_visibilities.count - end - end - - def reshare_count - @reshare_count ||= Post.where(:root_guid => self.guid).count - end - - def diaspora_handle= nd - self.author = Person.where(:diaspora_handle => nd).first - write_attribute(:diaspora_handle, nd) - end - def self.diaspora_initialize params new_post = self.new params.to_hash new_post.author = params[:author] @@ -82,23 +39,15 @@ class Post < ActiveRecord::Base new_post end + def reshare_count + @reshare_count ||= Post.where(:root_guid => self.guid).count + end + # @return Returns true if this Post will accept updates (i.e. updates to the caption of a photo). def mutable? false end - # The list of people that should receive this Post. - # - # @param [User] user The context, or dispatching user. - # @return [Array] The list of subscribers to this post - def subscribers(user) - if self.public? - user.contact_people - else - user.people_in_aspects(user.aspects_with_post(self.id)) - end - end - def activity_streams? false end @@ -111,12 +60,6 @@ class Post < ActiveRecord::Base I18n.t('notifier.a_post_you_shared') end - # @return [Integer] - def update_comments_counter - self.class.where(:id => self.id). - update_all(:comments_count => self.comments.count) - end - # @return [Boolean] def cache_for_author if self.should_cache_for_author? @@ -131,72 +74,4 @@ class Post < ActiveRecord::Base self.triggers_caching? && RedisCache.configured? && RedisCache.acceptable_types.include?(self.type) && user = self.author.owner end - - - # @param [User] user The user that is receiving this post. - # @param [Person] person The person who dispatched this post to the - # @return [void] - 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 - self.class.transaction do - local_post = persisted_post - - if local_post && verify_persisted_post(local_post) - self.receive_persisted(user, person, local_post) - - elsif !local_post - self.receive_non_persisted(user, person) - - 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}") - false - end - end - end - - protected - - # @return [Post,void] - def persisted_post - self.class.where(:guid => self.guid).first - end - - # @return [Boolean] - def verify_persisted_post(persisted_post) - persisted_post.author_id == self.author_id - end - - def receive_persisted(user, person, local_post) - known_post = user.find_visible_post_by_id(self.guid, :key => :guid) - if known_post - if known_post.mutable? - known_post.update_attributes(self.attributes) - true - else - Rails.logger.info("event=receive payload_type=#{self.class} update=true status=abort sender=#{self.diaspora_handle} reason=immutable") #existing_post=#{known_post.id}") - false - end - else - user.contact_for(person).receive_post(local_post) - user.notify_if_mentioned(local_post) - Rails.logger.info("event=receive payload_type=#{self.class} update=true status=complete sender=#{self.diaspora_handle}") #existing_post=#{local_post.id}") - true - end - end - - def receive_non_persisted(user, person) - if self.save - user.contact_for(person).receive_post(self) - user.notify_if_mentioned(self) - Rails.logger.info("event=receive payload_type=#{self.class} update=false status=complete sender=#{self.diaspora_handle}") - true - else - Rails.logger.info("event=receive payload_type=#{self.class} update=false status=abort sender=#{self.diaspora_handle} reason=#{self.errors.full_messages}") - false - end - end end diff --git a/app/models/post_visibility.rb b/app/models/post_visibility.rb deleted file mode 100644 index 6b41c8d3b..000000000 --- a/app/models/post_visibility.rb +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. - -class PostVisibility < ActiveRecord::Base - - belongs_to :contact - belongs_to :post - - # Perform a batch import, given a set of contacts and a post - # @note performs a bulk insert in mySQL; performs linear insertions in postgres - # @param contacts [Array] Recipients - # @param post [Post] - # @return [void] - def self.batch_import(contact_ids, post) - if postgres? - contact_ids.each do |contact_id| - PostVisibility.find_or_create_by_contact_id_and_post_id(contact_id, post.id) - end - else - new_post_visibilities_data = contact_ids.map do |contact_id| - [contact_id, post.id] - end - PostVisibility.import([:contact_id, :post_id], new_post_visibilities_data) - end - end -end diff --git a/app/models/profile.rb b/app/models/profile.rb index 579dd2208..7764a4f28 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -45,6 +45,7 @@ class Profile < ActiveRecord::Base before_validation do self.tag_string = self.tag_string.split[0..4].join(' ') end + before_save do self.build_tags self.construct_full_name @@ -77,6 +78,18 @@ class Profile < ActiveRecord::Base result || '/images/user/default.png' end + def from_omniauth_hash(omniauth_user_hash) + mappings = {"description" => "bio", + 'image' => 'image_url', + 'name' => 'first_name', + 'location' => 'location', + } + + update_hash = Hash[omniauth_user_hash.map {|k, v| [mappings[k], v] }] + + self.attributes.merge(update_hash){|key, old, new| old.blank? ? new : old} + end + def image_url= url return image_url if url == '' if url.nil? || url.match(/^https?:\/\//) diff --git a/app/models/retraction.rb b/app/models/retraction.rb index 348a4e521..e3868d033 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -15,7 +15,7 @@ class Retraction def subscribers(user) unless self.type == 'Person' @subscribers ||= self.object.subscribers(user) - @subscribers -= self.object.resharers + @subscribers -= self.object.resharers unless self.object.is_a?(Photo) @subscribers else raise 'HAX: you must set the subscribers manaully before unfriending' if @subscribers.nil? diff --git a/app/models/service.rb b/app/models/service.rb index ef3b1f483..c6b2f35f9 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -16,6 +16,11 @@ class Service < ActiveRecord::Base truncated = "#{truncated} #{url}" unless url.blank? return truncated end + + def profile_photo_url + nil + end + end require File.join(Rails.root, 'app/models/services/facebook') require File.join(Rails.root, 'app/models/services/twitter') diff --git a/app/models/services/facebook.rb b/app/models/services/facebook.rb index c4384a189..ed31888e1 100644 --- a/app/models/services/facebook.rb +++ b/app/models/services/facebook.rb @@ -71,7 +71,11 @@ class Services::Facebook < Service ServiceUser.import(data, :on_duplicate_key_update => OVERRIDE_FIELDS_ON_FB_UPDATE + [:updated_at]) end end - + + def profile_photo_url + "https://graph.facebook.com/#{self.uid}/picture?type=large&access_token=#{URI.escape(self.access_token)}" + end + private OVERRIDE_FIELDS_ON_FB_UPDATE = [:contact_id, :person_id, :request_id, :invitation_id, :photo_url, :name, :username] diff --git a/app/models/services/twitter.rb b/app/models/services/twitter.rb index 12c7d9585..7d35f6899 100644 --- a/app/models/services/twitter.rb +++ b/app/models/services/twitter.rb @@ -9,6 +9,27 @@ class Services::Twitter < Service Rails.logger.debug("event=post_to_service type=twitter sender_id=#{self.user_id}") message = public_message(post, url) + configure_twitter + + begin + Twitter.update(message) + rescue Exception => e + Rails.logger.info e.message + end + end + + def public_message(post, url) + super(post, MAX_CHARACTERS, url) + end + + def profile_photo_url + configure_twitter + + Twitter.profile_image(nickname, :size => "original") + end + + private + def configure_twitter twitter_key = SERVICES['twitter']['consumer_key'] twitter_consumer_secret = SERVICES['twitter']['consumer_secret'] @@ -22,15 +43,5 @@ class Services::Twitter < Service config.oauth_token = self.access_token config.oauth_token_secret = self.access_secret end - - begin - Twitter.update(message) - rescue Exception => e - Rails.logger.info e.message - end - end - - def public_message(post, url) - super(post, MAX_CHARACTERS, url) end end diff --git a/app/models/share_visibility.rb b/app/models/share_visibility.rb new file mode 100644 index 000000000..6fd3c0712 --- /dev/null +++ b/app/models/share_visibility.rb @@ -0,0 +1,26 @@ +# Copyright (c) 2010-2011, Diaspora Inc. This file is +# licensed under the Affero General Public License version 3 or later. See +# the COPYRIGHT file. + +class ShareVisibility < ActiveRecord::Base + belongs_to :contact + belongs_to :shareable, :polymorphic => :true + + # Perform a batch import, given a set of contacts and a shareable + # @note performs a bulk insert in mySQL; performs linear insertions in postgres + # @param contacts [Array] Recipients + # @param share [Shareable] + # @return [void] + def self.batch_import(contact_ids, share) + if postgres? + contact_ids.each do |contact_id| + ShareVisibility.find_or_create_by_contact_id_and_shareable_id_and_shareable_type(contact_id, share.id, share.class.base_class.to_s) + end + else + new_share_visibilities_data = contact_ids.map do |contact_id| + [contact_id, share.id, share.class.base_class.to_s] + end + ShareVisibility.import([:contact_id, :shareable_id, :shareable_type], new_share_visibilities_data) + end + end +end diff --git a/app/models/status_message.rb b/app/models/status_message.rb index 9cc74a711..2860afab9 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -19,7 +19,10 @@ class StatusMessage < Post xml_attr :raw_message has_many :photos, :dependent => :destroy, :foreign_key => :status_message_guid, :primary_key => :guid - validate :presence_of_content + + # TODO: disabling presence_of_content() (and its specs in status_message_controller_spec.rb:125) is a quick and dirty fix for federation + # a StatusMessage is federated before its photos are so presence_of_content() fails erroneously if no text is present + #validate :presence_of_content attr_accessible :text, :provider_display_name attr_accessor :oembed_url @@ -32,16 +35,6 @@ class StatusMessage < Post #scopes scope :where_person_is_mentioned, lambda{|person| joins(:mentions).where(:mentions => {:person_id => person.id})} - def self.owned_or_visible_by_user(user) - joins("LEFT OUTER JOIN post_visibilities ON post_visibilities.post_id = posts.id"). - joins("LEFT OUTER JOIN contacts ON contacts.id = post_visibilities.contact_id"). - where(Contact.arel_table[:user_id].eq(user.id).or( - StatusMessage.arel_table[:public].eq(true).or( - StatusMessage.arel_table[:author_id].eq(user.person.id) - ) - )).select('DISTINCT posts.*') - end - def self.tag_stream(user, tag_array, max_time, order) owned_or_visible_by_user(user). joins(:tags).where(:tags => {:name => tag_array}). diff --git a/app/models/user.rb b/app/models/user.rb index 60349daaf..96cd712fb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -28,9 +28,10 @@ class User < ActiveRecord::Base validates_presence_of :person, :unless => proc {|user| user.invitation_token.present?} validates_associated :person + validate :no_person_with_same_username has_one :person, :foreign_key => :owner_id - delegate :public_key, :posts, :owns?, :diaspora_handle, :name, :public_url, :profile, :first_name, :last_name, :to => :person + delegate :public_key, :posts, :photos, :owns?, :diaspora_handle, :name, :public_url, :profile, :first_name, :last_name, :to => :person 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 @@ -57,7 +58,8 @@ class User < ActiveRecord::Base :language, :disable_mail, :invitation_service, - :invitation_identifier + :invitation_identifier, + :show_community_spotlight_in_stream def self.all_sharing_with_person(person) @@ -207,7 +209,7 @@ class User < ActiveRecord::Base def add_to_streams(post, aspects_to_insert) post.socket_to_user(self, :aspect_ids => aspects_to_insert.map{|x| x.id}) if post.respond_to? :socket_to_user aspects_to_insert.each do |aspect| - aspect.posts << post + aspect << post end end @@ -309,6 +311,7 @@ class User < ActiveRecord::Base params[:image_url_medium] = photo.url(:thumb_medium) params[:image_url_small] = photo.url(:thumb_small) end + if self.person.profile.update_attributes(params) Postzord::Dispatcher.build(self, profile).post true @@ -470,4 +473,11 @@ class User < ActiveRecord::Base self.email = self.invitation_identifier if self.invitation_service == 'email' self end + + def no_person_with_same_username + diaspora_id = "#{self.username}@#{AppConfig[:pod_uri].host}" + if self.username_changed? && Person.exists?(:diaspora_handle => diaspora_id) + errors[:base] << 'That username has already been taken' + end + end end diff --git a/app/views/aspects/_aspect_listings.haml b/app/views/aspects/_aspect_listings.haml index 8d875333f..9752b1623 100644 --- a/app/views/aspects/_aspect_listings.haml +++ b/app/views/aspects/_aspect_listings.haml @@ -3,7 +3,7 @@ -# the COPYRIGHT file. %ul#aspect_nav.left_nav - %li.all_aspects{:class => ("active" if params["set"] != "all" && params["set"] != "only_sharing" && !@featured && !@finder)} + %li.all_aspects .root_element= link_to t('aspects.index.your_aspects'), aspects_path %ul.sub_nav @@ -14,8 +14,7 @@ %li{:data => {:aspect_id => aspect.id}, :class => ("active" if defined?(stream) && stream.aspect_ids.include?(aspect.id))} .edit = link_to image_tag("icons/pencil.svg", :height => 12, :title => t('.edit_aspect', :name => aspect.name)), edit_aspect_path(aspect), :rel => "facebox" - - %a.aspect_selector{:href => aspects_path("a_ids[]" => aspect.id), :class => "aspect_selector name hard_aspect_link", 'data-guid' => aspect.id} + %a.aspect_selector{:href => aspects_path("a_ids[]" => aspect.id), :class => "name", 'data-guid' => aspect.id} = aspect %li diff --git a/app/views/aspects/_aspect_stream.haml b/app/views/aspects/_aspect_stream.haml index c86ae06dc..5ef3067a7 100644 --- a/app/views/aspects/_aspect_stream.haml +++ b/app/views/aspects/_aspect_stream.haml @@ -4,11 +4,11 @@ #aspect_stream_header #sort_by - = t('.recently') + = t('streams.recently') %span.controls - = link_to_if(session[:sort_order] == 'created_at', t('.commented_on'), stream.link(:sort_order => 'updated_at')) + = link_to_if(session[:sort_order] == 'created_at', t('streams.commented_on'), stream.link(:sort_order => 'updated_at')) · - = link_to_if(session[:sort_order] == 'updated_at', t('.posted'), stream.link(:sort_order => 'created_at' )) + = link_to_if(session[:sort_order] == 'updated_at', t('streams.posted'), stream.link(:sort_order => 'created_at' )) %h3 = stream.title @@ -16,11 +16,14 @@ = render 'shared/publisher', :selected_aspects => stream.aspects, :aspect_ids => stream.aspect_ids, :for_all_aspects => stream.for_all_aspects?, :aspect => stream.aspect = render 'aspects/no_posts_message' -- if current_user.contacts.size < 2 - = render 'aspects/no_contacts_message' +#gs-shim{:title => "3. #{t('.stay_updated')}", 'data-content' => t('.stay_updated_explanation')} #main_stream.stream{:data => {:guids => stream.aspect_ids.join(','), :time_for_scroll => time_for_scroll(stream.ajax_stream?, stream)}} - if !stream.ajax_stream? && stream.posts.length > 0 = render 'shared/stream', :posts => stream.posts #pagination =link_to(t('more'), next_page_path(:ajax_stream => stream.ajax_stream?), :class => 'paginate') + +- if current_user.contacts.size < 2 + = render 'aspects/no_contacts_message' + diff --git a/app/views/aspects/_no_contacts_message.haml b/app/views/aspects/_no_contacts_message.haml index a4a0e052b..30aa0d3bd 100644 --- a/app/views/aspects/_no_contacts_message.haml +++ b/app/views/aspects/_no_contacts_message.haml @@ -7,5 +7,5 @@ %br %br = t('.try_adding_some_more_contacts') - != t('.or_featured', :link => link_to(t(".featured_users") , featured_users_path)) + != t('.or_spotlight', :link => link_to(t(".community_spotlight") , community_spotlight_path)) diff --git a/app/views/aspects/index.html.haml b/app/views/aspects/index.html.haml index a7e42d6aa..948273dd8 100644 --- a/app/views/aspects/index.html.haml +++ b/app/views/aspects/index.html.haml @@ -6,25 +6,42 @@ - content_for :head do = include_javascripts :home +- if current_user.getting_started? + #welcome-to-diaspora + .container{:style => "position: relative;"} + .right + = link_to image_tag('deletelabel.png'), getting_started_completed_path, :id => "gs-skip-x" + .span-23 + %h1 + = t('.welcome_to_diaspora', :name => current_user.first_name) + %h3 + = t('.introduce_yourself') + %br + %br + %br + %br + %br + .span-5.leftNavBar #home_user_badge = owner_image_link - %h3 - = current_user.first_name + %h4 + = link_to current_user.first_name, "/u/#{current_user.username}" - - unless has_completed_getting_started? - .section - %ul.left_nav - %li - = link_to "Welcome", getting_started_path, :class => "home_selector" + .section + %ul.left_nav + %li + %b + = link_to t("streams.multi.title"), multi_path, :class => 'home_selector' .section = render 'aspects/aspect_listings', :stream => @stream .section %ul.left_nav - .li - %b= link_to t('.mentions'), mentions_path, :class => 'home_selector' + %li + %b + = link_to t('streams.mentions.title'), mentions_path, :class => 'home_selector' .section#followed_tags_listing = render 'tags/followed_tags_listings' diff --git a/app/views/comments/_comment.html.haml b/app/views/comments/_comment.html.haml index e0955bde3..342a6bce0 100644 --- a/app/views/comments/_comment.html.haml +++ b/app/views/comments/_comment.html.haml @@ -5,7 +5,7 @@ %li.comment.posted{:id => comment.guid, :class => ("hidden" if(defined? hidden))} - if current_user && (current_user.owns?(comment) || current_user.owns?(post)) .right.controls - = link_to image_tag('deletelabel.png'), post_comment_path(comment.post_id, comment), :class => "delete comment_delete", :title => t('delete') + = link_to image_tag('deletelabel.png'), post_comment_path(comment.commentable_id, comment), :class => "delete comment_delete", :title => t('delete') = person_image_link(comment.author, :size => :thumb_small) .content %span.from diff --git a/app/views/featured_users/_user.html.haml b/app/views/community_spotlight/_user.html.haml similarity index 100% rename from app/views/featured_users/_user.html.haml rename to app/views/community_spotlight/_user.html.haml diff --git a/app/views/contacts/_aspect_listings.haml b/app/views/contacts/_aspect_listings.haml index 3367d4e37..2cc8dd481 100644 --- a/app/views/contacts/_aspect_listings.haml +++ b/app/views/contacts/_aspect_listings.haml @@ -3,33 +3,33 @@ -# the COPYRIGHT file. %ul#aspect_nav.left_nav - %li.all_aspects{:class => ("active" if params["set"] != "all" && params["set"] != "only_sharing" && !@featured && !@finder)} + %li.all_aspects{:class => ("active" if params["set"] != "all" && params["set"] != "only_sharing" && !@spotlight && !@finder)} %a.home_selector{:href => contacts_path, :class => ("sub_selected" if params["a_id"])} + = t('contacts.index.my_contacts') .contact_count = my_contacts_count - = t('contacts.index.my_contacts') %ul.sub_nav - for aspect in all_aspects %li{:data => {:aspect_id => aspect.id}, :class => ("active" if params["a_id"].to_i == aspect.id)} %a.aspect_selector{:href => contacts_path(:a_id => aspect.id)} + = aspect .contact_count = aspect.contacts.size - = aspect %li = link_to t('aspects.aspect_listings.add_an_aspect'), new_aspect_path, :class => "new_aspect", :rel => "facebox" %li.all_contacts{:class => ("active" if params["set"] == "all" || params["set"] == "only_sharing")} %a.home_selector{:href => contacts_path(:set => "all"), :class => ("sub_selected" if params["set"] == "only_sharing")} + = t('contacts.index.all_contacts') .contact_count = all_contacts_count - = t('contacts.index.all_contacts') %ul.sub_nav %li{:class => ("active" if params["set"] == "only_sharing")} %a.aspect_selector{:href => contacts_path(:set => "only_sharing")} + = t('contacts.index.only_sharing_with_me') .contact_count = only_sharing_count - = t('contacts.index.only_sharing_with_me') diff --git a/app/views/contacts/index.html.haml b/app/views/contacts/index.html.haml index fd10ce84d..0d6732b67 100644 --- a/app/views/contacts/index.html.haml +++ b/app/views/contacts/index.html.haml @@ -23,9 +23,8 @@ - conv_opts[:title] = t('.many_people_are_you_sure', :suggested_limit => suggested_limit) if @contacts.size > suggested_limit = link_to t('.start_a_conversation'), new_conversation_path(:aspect_id => @aspect.id, :name => @aspect.name), conv_opts - - if @contacts.size > suggested_limit - = javascript_tag "$('.conversation_button').tipsy({trigger: 'hover', gravity: 'n'});" - = link_to t('.add_to_aspect', :name => @aspect.name), edit_aspect_path(@aspect), :rel => "facebox" + - if @contacts.size + = link_to t('.add_to_aspect', :name => @aspect.name), edit_aspect_path(@aspect), :rel => "facebox" - if @contacts.size > 0 - for contact in @contacts @@ -60,9 +59,9 @@ %br %br = t('.check_out') - = link_to t('contacts.spotlight.community_spotlight'), featured_users_path + = link_to t('contacts.spotlight.community_spotlight'), community_spotlight_path - if @aspect or - = link_to t('.add_to_aspect', :name => @aspect.name).downcase, edit_aspect_path(@aspect), :rel => "facebox" + = link_to t('.add_to_aspect', :name => @aspect.name), edit_aspect_path(@aspect), :rel => "facebox" diff --git a/app/views/contacts/featured.haml b/app/views/contacts/spotlight.haml similarity index 50% rename from app/views/contacts/featured.haml rename to app/views/contacts/spotlight.haml index 1a897e2af..9347ebb48 100644 --- a/app/views/contacts/featured.haml +++ b/app/views/contacts/spotlight.haml @@ -3,7 +3,7 @@ -# the COPYRIGHT file. - content_for :page_title do - = t('.community_spotlight') + = t('contacts.spotlight.community_spotlight') - content_for :head do = include_javascripts :people @@ -14,12 +14,17 @@ = render 'shared/contact_sidebar' -.span-18.last +.span-18.last{:style => "position:relative;"} + + - if AppConfig[:spotlight_suggest_email].present? + .right + = link_to "Suggest a member", "mailto:#{AppConfig[:spotlight_suggest_email]}", :class => "button" + %h3 - = t('.community_spotlight') + = t('contacts.spotlight.community_spotlight') %br - #featured_users + #community_spotlight - unless @people.blank? - @people.each do |person| - = render 'featured_users/user', :person => person + = render 'community_spotlight/user', :person => person diff --git a/app/views/conversations/new.haml b/app/views/conversations/new.haml index 6026f09a9..dc8f8c239 100644 --- a/app/views/conversations/new.haml +++ b/app/views/conversations/new.haml @@ -4,7 +4,7 @@ :javascript $(document).ready(function () { - var data = $.parseJSON( "#{@contacts_json}" ), + var data = $.parseJSON( "#{escape_javascript(@contacts_json)}" ), autocompleteInput = $("#contact_autocomplete"); autocompleteInput.autoSuggest(data, { diff --git a/app/views/invitations/edit.html.haml b/app/views/invitations/edit.html.haml index 0bbe3f159..ca4047ff3 100644 --- a/app/views/invitations/edit.html.haml +++ b/app/views/invitations/edit.html.haml @@ -1,43 +1,47 @@ = javascript_include_tag "validation" = javascript_tag "Diaspora.Page = 'InvitationsEdit';" -:javascript - $(function() { - $("#user_username").focus(); - }); - .span-7.append-1.prepend-3 %br %br %br %br - %h2 - = t('.your_account_awaits') + %h1 + = t('welcome') %h3.accept_invitation_text = t('.accept_your_invitation') - flash.each do |name, msg| %p{:class => "login_#{name}"}= msg + = image_tag 'diaspora_collage.png', :style => "margin-left:-50px;" + .span-10 %br %br %br %br - = form_for(resource, :as => resource_name, :url => invitation_path(resource_name), :html => {:method => :put, :class => 'accept_invitation_form'}) do |f| - %p - = f.label :username , t('username') - = f.text_field :username, :title => t('registrations.new.enter_username') - %p - = f.label :email , t('email') - = f.email_field :email, :title => t('registrations.new.enter_email') - %p - = f.label :password , t('password') - = f.password_field :password, :title => t('registrations.new.enter_password') - %p - = f.label :password_confirmation , t('password_confirmation') - = f.password_field :password_confirmation, :title => t('registrations.new.enter_password_again') - = f.hidden_field :invitation_token + = form_for(resource, :as => resource_name, :url => invitation_path(resource_name), :html => {:method => :put, :class => 'accept_invitation_form'}, :validate => true) do |f| + %fieldset + .clearfix + %b + = t('username') + = f.text_field :username, :title => t('registrations.new.enter_username') + %span.host_uri + = "@#{AppConfig[:pod_uri].host}" + .clearfix + %b + = t('email') + = f.email_field :email, :title => t('registrations.new.enter_email') + .clearfix + %b + = t('password') + = f.password_field :password, :title => t('registrations.new.enter_password') + .clearfix + %b + = t('password_confirmation') + = f.password_field :password_confirmation, :title => t('registrations.new.enter_password_again') + = f.hidden_field :invitation_token - .submit_field - = f.submit t('registrations.new.create_my_account') + .submit_field + = f.submit t('registrations.new.create_my_account'), :class => 'in_aspects' diff --git a/app/views/invitations/new.html.haml b/app/views/invitations/new.html.haml index e1dc190c8..82abcf855 100644 --- a/app/views/invitations/new.html.haml +++ b/app/views/invitations/new.html.haml @@ -1,9 +1,3 @@ -:javascript - $(function() { - $('#new_user [title]').tipsy({trigger: 'focus', gravity: ($('html').attr('dir') == 'rtl') ? 'e' : 'w'}); - $("#user_email").focus(); - }); - .span-15.last .span-3 = image_tag 'icons/monotone_email_letter_round.png', :height => "128px", :width => "128px" diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index ddaf669be..923013d72 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -23,7 +23,7 @@ #nav_badges #home_badge.badge - = link_to aspects_path, :title => t('_home') do + = link_to multi_path, :title => t('_home') do = image_tag 'icons/home_grey.svg', :height => 16, :alt => t('_home') #notification_badge.badge @@ -40,7 +40,10 @@ #notification_dropdown .header - = link_to t('.view_all'), notifications_path, :id => "view_all_notifications" + .right + = link_to t('notifications.index.mark_all_as_read'), read_all_notifications_path + \| + = link_to t('.view_all'), notifications_path, :id => "view_all_notifications" %h4 = t('.recent_notifications') .notifications diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 17a72f3cc..0beb4d220 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -19,8 +19,12 @@ / Social Media Icons are by Paul Robert Lloyd @ http://paulrobertlloyd.com/2009/06/social_media_icons - = stylesheet_link_tag "blueprint/screen", :media => 'screen' - = stylesheet_link_tag "blueprint/print", :media => 'print' + / bootstrap/blueprint switch + - if @aspect == :getting_started || @page == :logged_out + = stylesheet_link_tag "bootstrap.min.css" + - else + = stylesheet_link_tag "blueprint/screen", :media => 'screen' + = stylesheet_link_tag "blueprint/print", :media => 'print' = stylesheet_link_tag "login", :media => 'screen' @@ -48,7 +52,6 @@ = javascript_include_tag 'web-socket-receiver' = render 'js/websocket_js' - = yield(:head) -unless Rails.env == "production" @@ -80,7 +83,6 @@ piwikTracker.enableLinkTracking(); } catch( err ) {} - - if @person %link{:rel => "alternate", :href => "#{@person.public_url}.atom", :type => "application/atom+xml", :title => "#{t('.public_feed', :name => @person.name)}"} @@ -91,15 +93,21 @@ #notifications - - flash.each do |name, msg| - %div{:id => "flash_#{name}"}= msg + - unless @page == :logged_out + - flash.each do |name, msg| + %div{:id => "flash_#{name}"} + .message + = msg %header{:class=>('landing' unless current_user)} = render 'layouts/header' .container{:style=> "#{yield(:break_the_mold)}"} - .span-24.last{:style=> "#{yield(:break_the_mold)}"} + - if @aspsect == :getting_started || @page == :logged_out = yield + - else + .span-24.last{:style=> "#{yield(:break_the_mold)}"} + = yield %footer .container diff --git a/app/views/layouts/application.mobile.haml b/app/views/layouts/application.mobile.haml index 95cd15336..c4d0ef66b 100644 --- a/app/views/layouts/application.mobile.haml +++ b/app/views/layouts/application.mobile.haml @@ -50,7 +50,7 @@ = yield %header - = link_to(image_tag('white@2x.png', :height => 20, :width => 127, :id => 'header_title'), aspects_path) + = link_to(image_tag('white@2x.png', :height => 20, :width => 127, :id => 'header_title'), multi_path) - if user_signed_in? - if yield(:header_action).present? = yield(:header_action) diff --git a/app/views/people/show.html.haml b/app/views/people/show.html.haml index 10ccd9937..7ccb346a7 100644 --- a/app/views/people/show.html.haml +++ b/app/views/people/show.html.haml @@ -26,12 +26,13 @@ .stream_container = render 'people/sub_header', :person => @person, :contact => @contact - - if @posts.length > 0 + / hackity hack until we get a photo stream + - if (@posts && @posts.length > 0) || @stream.posts.length > 0 -if @post_type == :photos = render 'photos/index', :photos => @posts - else #main_stream.stream - = render 'shared/stream', :posts => @posts + = render 'shared/stream', :posts => @stream.posts #pagination =link_to(t('more'), next_page_path, :class => 'paginate') diff --git a/app/views/people/show.mobile.haml b/app/views/people/show.mobile.haml index 69e902b63..414b9a875 100644 --- a/app/views/people/show.mobile.haml +++ b/app/views/people/show.mobile.haml @@ -20,12 +20,12 @@ = link_to t('.return_to_aspects'), aspects_manage_path = t('.to_accept_or_ignore') -- if @posts.length > 0 +- if @stream.posts.length > 0 -if @post_type == :photos - = render 'photos/index', :photos => @posts + = render 'photos/index', :photos => @stream.posts - else #main_stream.stream - = render 'shared/stream', :posts => @posts + = render 'shared/stream', :posts => @stream.posts #pagination =link_to(t('more'), next_page_path, :class => 'paginate') - else diff --git a/app/views/photos/_new_profile_photo.haml b/app/views/photos/_new_profile_photo.haml index 1cf4af32d..fa3638ea7 100644 --- a/app/views/photos/_new_profile_photo.haml +++ b/app/views/photos/_new_profile_photo.haml @@ -38,7 +38,6 @@ var id = responseJSON.data.photo.id; var url = responseJSON.data.photo.unprocessed_image.url; var oldPhoto = $('#photo_id'); - console.log(responseJSON); if(oldPhoto.length == 0) { $('#update_profile_form').prepend(""); }else{ @@ -47,6 +46,7 @@ $("#profile_photo_upload").find(".avatar").removeClass('loading'); $("#profile_photo_upload").find(".avatar").attr("src",url); + $(".avatar[data-person_id=#{current_user.person.id}]").attr("src",url); } }); } @@ -55,6 +55,10 @@ #profile_photo_upload = owner_image_tag(:thumb_medium) + -if !aspect.nil? && aspect == :getting_started + %br + %br + #file-upload.button =t('.upload') diff --git a/app/views/posts/show.mobile.haml b/app/views/posts/show.mobile.haml index 84d886908..63bf09376 100644 --- a/app/views/posts/show.mobile.haml +++ b/app/views/posts/show.mobile.haml @@ -5,3 +5,4 @@ .stream = render :partial => 'shared/stream_element', :locals => {:post => @post, :commenting_disabled => commenting_disabled?(@post), :expanded_info => true} + diff --git a/app/views/profiles/_edit_public.haml b/app/views/profiles/_edit_public.haml index b6e859e43..fda938d61 100644 --- a/app/views/profiles/_edit_public.haml +++ b/app/views/profiles/_edit_public.haml @@ -5,34 +5,33 @@ - content_for :head do = include_javascripts :profile -:javascript - $(document).ready(function () { - var data = $.parseJSON( '#{@tags_array.to_json.gsub("'", "\\\\'")}' ), - autocompleteInput = $("#profile_tag_string"); + :javascript + $(document).ready(function () { + var data = $.parseJSON( '#{@tags_array.to_json.gsub("'", "\\\\'")}' ), + autocompleteInput = $("#profile_tag_string"); - autocompleteInput.autoSuggest("#{tags_path}", { - selectedItemProp: "name", - searchObjProps: "name", - asHtmlID: "tags", - neverSubmit: true, - retriveLimit: 10, - selectionLimit: 5, - minChars: 2, - keyDelay: 200, - startText: "", - emptyText: "#{t('no_results')}", - preFill: data - }); + autocompleteInput.autoSuggest("#{tags_path}", { + selectedItemProp: "name", + searchObjProps: "name", + asHtmlID: "tags", + neverSubmit: true, + retriveLimit: 10, + minChars: 2, + keyDelay: 200, + startText: "", + emptyText: "#{t('no_results')}", + preFill: data + }); - autocompleteInput.bind('keydown', function(evt){ - if(evt.keyCode == 13 || evt.keyCode == 9 || evt.keyCode == 32){ - evt.preventDefault(); - if( $('li.as-result-item.active').length == 0 ){ - $('li.as-result-item').first().click(); + autocompleteInput.bind('keydown', function(evt){ + if(evt.keyCode == 13 || evt.keyCode == 9 || evt.keyCode == 32){ + evt.preventDefault(); + if( $('li.as-result-item.active').length == 0 ){ + $('li.as-result-item').first().click(); + } } - } + }); }); - }); %h3 = t('profiles.edit.your_public_profile') diff --git a/app/views/registrations/new.html.haml b/app/views/registrations/new.html.haml index 567e5318d..012aa79be 100644 --- a/app/views/registrations/new.html.haml +++ b/app/views/registrations/new.html.haml @@ -1,39 +1,48 @@ = javascript_include_tag "validation" +-# = javascript_include_tag 'vendor/jquery.ghostInput' -:javascript - $(function() { - $("#user_username").focus(); - }); - += javascript_tag "Diaspora.Page = 'InvitationsEdit';" .span-7.append-1.prepend-3 %br %br %br %br - %h2 - = t('.join_the_movement') + %h1 + = t('welcome') %h3.accept_invitation_text - = t('.sign_up_today') + = t('.sign_up_message') + - flash.each do |name, msg| + %p{:class => "login_#{name}"}= msg + + = image_tag 'diaspora_collage.png', :style => "margin-left:-50px;" .span-10 %br %br %br %br - = form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'sign_up_form'}) do |f| - %p - = f.label :username , t('username') - = f.text_field :username, :title => t('.enter_username') - %p - = f.label :email , t('email') - = f.text_field :email, :title => t('.enter_email') - - %p - = f.label :password , t('password') - = f.password_field :password, :title => t('.enter_password') - %p - = f.label :password_confirmation , t('password_confirmation') - = f.password_field :password_confirmation, :title => t('.enter_password_again') + = form_for(resource, :as => resource_name, :html => {:class => 'new_user_form'}, :url => registration_path(resource_name), :validate => true) do |f| + %fieldset + .clearfix + %b + = t('username') + = f.text_field :username, :title => t('registrations.new.enter_username') + %span.host_uri + = "@#{AppConfig[:pod_uri].host}" + .clearfix + %b + = t('email') + = f.email_field :email, :title => t('registrations.new.enter_email') + .clearfix + %b + = t('password') + = f.password_field :password, :title => t('registrations.new.enter_password') + .clearfix + %b + = t('password_confirmation') + = f.password_field :password_confirmation, :title => t('registrations.new.enter_password_again') + + .submit_field + = f.submit t('registrations.new.create_my_account'), :class => 'in_aspects' - = f.submit t('.create_my_account') diff --git a/app/views/registrations/new.mobile.haml b/app/views/registrations/new.mobile.haml new file mode 100644 index 000000000..17f0d5f5a --- /dev/null +++ b/app/views/registrations/new.mobile.haml @@ -0,0 +1,40 @@ +-# Copyright (c) 2010-2011, Diaspora Inc. This file is +-# licensed under the Affero General Public License version 3 or later. See +-# the COPYRIGHT file. + += javascript_include_tag "validation" + +.stream + #login_form + .login-container + %h2 + = t('users.getting_started.welcome') + = form_for(resource, :as => resource_name, :html => {:class => 'new_user_form'}, :url => registration_path(resource_name), :validate => true) do |f| + .row + .row + = f.label :username, t('username') + .centered + = f.text_field :username + %span.host_uri + = "@#{AppConfig[:pod_uri].host}" + .row + .row + = f.label :email, t('email') + .centered + = f.email_field :email + .row + .row + = f.label :password, t('password') + .centered + = f.password_field :password + .row + .row + = f.label :password_confirmation, t('password_confirmation') + .centered + = f.password_field :password_confirmation + .row + = f.submit t('registrations.new.create_my_account'), :class => 'login-submit' + = link_to t('.sign_up'), new_user_session_path() + +%footer + diff --git a/app/views/post_visibilities/update.js.erb b/app/views/share_visibilities/update.js.erb similarity index 100% rename from app/views/post_visibilities/update.js.erb rename to app/views/share_visibilities/update.js.erb diff --git a/app/views/shared/_contact_sidebar.html.haml b/app/views/shared/_contact_sidebar.html.haml index 5e560ea6b..bfe2696a2 100644 --- a/app/views/shared/_contact_sidebar.html.haml +++ b/app/views/shared/_contact_sidebar.html.haml @@ -8,9 +8,9 @@ %hr %ul.left_nav - - if AppConfig[:featured_users] - %li{:class => ("active" if @featured)} - = link_to t('contacts.featured.featured_users'), featured_users_path, :class => "element_selector" + - if AppConfig[:community_spotlight] + %li{:class => ("active" if @spotlight)} + = link_to t('contacts.spotlight.community_spotlight'), community_spotlight_path, :class => "element_selector" %li{:class => ("active" if @finder)} = link_to "Facebook Friends", friend_finder_path('facebook'), :class => "element_selector" diff --git a/app/views/shared/_donate.html.haml b/app/views/shared/_donate.html.haml index 38a04b6a6..a87d6c2ec 100644 --- a/app/views/shared/_donate.html.haml +++ b/app/views/shared/_donate.html.haml @@ -1,11 +1,12 @@ -%form{:action => "https://www.paypal.com/cgi-bin/webscr", :method => "post"} - %input{:name => "cmd", :type => "hidden", :value => "_s-xclick"} - %input{:name => "hosted_button_id", :type => "hidden", :value => AppConfig[:paypal_hosted_button_id]} - %input{:name => "on0", :type => "hidden", :value => "Type"} - %input{:name => "modify", :type => "hidden", :value => "2"} - %select{:name => "os0"} - %option{:value => "Mocha"} Mocha : $3.00USD - %option{:value => "Americano"} Americano : $5.00USD - %option{:value => "Box o' Joe"} Box o' Joe : $20.00USD - %input{:name => "currency_code", :type => "hidden", :value => "USD"} +-# %form{:action => "https://www.paypal.com/cgi-bin/webscr", :method => "post"} +%form{:action => "https://www.diasporafoundation.org/donate", :method => "get"} + -# %input{:name => "cmd", :type => "hidden", :value => "_s-xclick"} + -# %input{:name => "hosted_button_id", :type => "hidden", :value => AppConfig[:paypal_hosted_button_id]} + -# %input{:name => "on0", :type => "hidden", :value => "Type"} + -# %input{:name => "modify", :type => "hidden", :value => "2"} + %select{:name => "monthly_amount"} + %option{:value => "1"} Supporter : $5.00USD + %option{:value => "2"} Member : $10.00USD + %option{:value => "3"} Freedom Fighter : $20.00USD + -# %input{:name => "currency_code", :type => "hidden", :value => "USD"} %input{:name => "submit", :type => "submit", :value => t('aspects.index.donate')} diff --git a/app/views/shared/_publisher.html.haml b/app/views/shared/_publisher.html.haml index f5b8742b5..087a2a345 100644 --- a/app/views/shared/_publisher.html.haml +++ b/app/views/shared/_publisher.html.haml @@ -4,11 +4,49 @@ :javascript $(function() { - $(".question_mark").tipsy({trigger: 'hover', gravity: 'n'}); - $(".service_icon").tipsy({trigger: 'hover', gravity: 'n'}); - $(".public_icon").tipsy({trigger: 'hover', gravity: 'n'}); + $(".question_mark").twipsy({trigger: 'hover', placement: 'bottom'}); + $(".service_icon").twipsy({trigger: 'hover', placement: 'bottom'}); + $(".public_icon").twipsy({trigger: 'hover', placement: 'bottom'}); }); +- if publisher_open + :javascript + $(document).ready(function() { + Publisher.open(); + }); + +-if publisher_explain + :javascript + $(document).ready(function() + { + $("#publisher .dropdown").popover({trigger: 'manual', offset: 10, placement:'below'}); + $("#publisher .dropdown").bind("click", function(){$(this).popover("hide")}); + + $("#publisher #status_message_fake_text").popover({trigger: 'manual', placement: 'right', offset: 30, id: "first_message_explain"}); + $("#publisher #status_message_fake_text").bind("click", function(){$(this).popover("hide")}); + + $("#gs-shim").popover({trigger: 'manual', placement: 'left', offset: -5}); + $("#gs-shim").bind("click", function(){$(this).popover("hide")}); + + setTimeout(function(){ + $("#publisher #status_message_fake_text").popover("show"); + }, 600); + + setTimeout(function(){ + $("#publisher .dropdown").popover("show"); + }, 1000); + + setTimeout(function(){ + $("#gs-shim").popover("show"); + }, 1400); + + $("#publisher .button.creation").bind("click", function(){ + $("#publisher .dropdown").popover("hide"); + $("#publisher #status_message_fake_text").popover("hide"); + $("#gs-shim").popover("hide"); + }); + }); + #publisher.closed{:class => ((aspect == :profile)? 'mention_popup' : nil )} .content_creation = form_for(StatusMessage.new, :remote => remote?, :html => {"data-type" => "json"}) do |status| @@ -18,28 +56,53 @@ #publisher_textarea_wrapper = link_to( image_tag('deletelabel.png'), "#", :id => "hide_publisher", :title => t('.discard_post')) %ul#photodropzone - = status.text_area :fake_text, :rows => 2, :value => h(params[:prefill]), :tabindex => 1, :placeholder => t('.whats_on_your_mind') + = status.text_area :fake_text, :rows => 2, :value => h(publisher_prefill_text), :tabindex => 1, :placeholder => t('.whats_on_your_mind'), + :title => "1. #{t('shared.public_explain.share')}", 'data-content' => t('shared.public_explain.new_user_welcome_message') = status.hidden_field :text, :value => '', :class => 'clear_on_submit' #file-upload{:title => t('.upload_photos')} = image_tag 'icons/camera.svg', :height => 14 - - - for aspect_id in aspect_ids - = hidden_field_tag 'aspect_ids[]', aspect_id.to_s + - if publisher_public + = hidden_field_tag 'aspect_ids[]', "public" + - elsif all_aspects_selected?(selected_aspects) + = hidden_field_tag 'aspect_ids[]', "all_aspects" + - else + - for aspect_id in aspect_ids + = hidden_field_tag 'aspect_ids[]', aspect_id.to_s .options_and_submit .public_toggle %span#publisher_service_icons - = t("shared.publisher.click_to_share_with") - - if((defined?(for_all_aspects) && for_all_aspects) || aspect == :profile) - = status.hidden_field(:public, :value => public_value ) - = image_tag "icons/globe.png", :title => public_helper_text, :class => "public_icon #{'dim' if !public_value}", :width => 16, :height => 16 - if current_user.services - for service in current_user.services = image_tag "social_media_logos/#{service.provider}-16x16.png", :title => service.provider.titleize, :class => "service_icon dim", :id =>"#{service.provider}", :maxchar => "#{service.class::MAX_CHARACTERS}" = link_to (image_tag "icons/monotone_wrench_settings.png"), "#question_mark_pane", :class => 'question_mark', :rel => 'facebox', :title => t('shared.public_explain.manage') - = render "shared/aspect_dropdown", :selected_aspects => selected_aspects, :hang => 'left' + + // NOTE(dropdown special casing to DRY up -- taken from the aspect_dropdown partial) + .dropdown{:class => "hang_right", :title => "2. #{t('shared.public_explain.control_your_audience')}", 'data-content'=> t('shared.public_explain.visibility_dropdown')} + .button.toggle.publisher + - if publisher_public + = t('public') + - elsif all_aspects_selected?(selected_aspects) + = t('all_aspects') + - elsif selected_aspects.size == 1 + = selected_aspects.first.name + - else + = t('.toggle', :count => selected_aspects.size) + ▼ + + .wrapper + %ul.dropdown_list{:unSelectable => 'on', 'data-person_id' => (person.id if defined?(person) && person), 'data-service_uid' => (service_uid if defined?(service_uid))} + %li.public.radio{"data-aspect_id" => "public", :class => ("selected" if publisher_public)} + Public + + %li.divider.all_aspects.radio{:style => "border-bottom: 1px solid #ddd;", "data-aspect_id" => "all_aspects", :class => ("selected" if (!publisher_public && all_aspects_selected?(selected_aspects)))} + = t('all_aspects') + + - for aspect in all_aspects + = aspect_dropdown_list_item(aspect, !all_aspects_selected?(selected_aspects) && selected_aspects.include?(aspect) ) + = status.submit t('.share'), :disable_with => t('.posting'), :class => 'button creation', :tabindex => 2 .facebox_content diff --git a/app/views/shared/_right_sections.html.haml b/app/views/shared/_right_sections.html.haml index 736667f19..6906e7ca0 100644 --- a/app/views/shared/_right_sections.html.haml +++ b/app/views/shared/_right_sections.html.haml @@ -69,23 +69,13 @@ .content != t('bookmarklet.explanation', :link => link_to(t('bookmarklet.explanation_link_text'), bookmarklet)) -- if @stream.has_featured_users? - .section - .title.no_icon - %h5 - =t('aspects.index.community_spotlight') - .content#featured_users - = link_to t('aspects.index.see_more_from_us'), featured_path, :id => 'view_all_contacts_link' - -- unless AppConfig[:paypal_hosted_button_id].blank? - .section - .title - = image_tag('/images/icons/coffee.png') - %h5 - = t('aspects.index.donate') - .content - = t('aspects.index.keep_us_running', :pod => URI.parse(AppConfig[:pod_url]).host) - %br - = render 'shared/donate' - +.section + .title + = image_tag('/images/icons/coffee.png') + %h5 + = t('aspects.index.donate') + .content + = t('aspects.index.keep_us_running', :pod => URI.parse(AppConfig[:pod_url]).host) + %br + = render 'shared/donate' diff --git a/app/views/shared/_stream_element.html.haml b/app/views/shared/_stream_element.html.haml index e2f3dcb1c..970793f3a 100644 --- a/app/views/shared/_stream_element.html.haml +++ b/app/views/shared/_stream_element.html.haml @@ -3,24 +3,26 @@ -# the COPYRIGHT file. -.stream_element{:id => post.guid} +.stream_element{:id => post.guid, :class => from_group(post)} .right.controls - if current_user && post.author.owner_id == current_user.id = link_to image_tag('deletelabel.png'), post_path(post), :confirm => t('are_you_sure'), :method => :delete, :remote => true, :class => "delete stream_element_delete", :title => t('delete') - else - = link_to image_tag('deletelabel.png'), post_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true, :class => "delete stream_element_delete vis_hide", :title => t('.hide_and_mute') + = link_to image_tag('deletelabel.png'), share_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true, :class => "delete stream_element_delete vis_hide", :title => t('.hide_and_mute') = image_tag 'ajax-loader.gif', :class => "hide_loader hidden" .undo_text.hidden %p - = t('post_visibilites.update.post_hidden_and_muted', :name => person_link(post.author)).html_safe + = t('share_visibilites.update.post_hidden_and_muted', :name => person_link(post.author)).html_safe %p - = t('post_visibilites.update.see_it_on_their_profile', :name => person_link(post.author)).html_safe - = link_to t('undo'), post_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true + = t('share_visibilites.update.see_it_on_their_profile', :name => person_link(post.author)).html_safe + = link_to t('undo'), share_visibility_path(:id => "42", :post_id => post.id), :method => :put, :remote => true + + .indicator{:title => "#{what_stream_sentence(post)}"} + = stream_settings_link(post) .sm_body = person_image_link(post.author, :size => :thumb_small) - .content %div.post_initial_info %span.from @@ -72,7 +74,7 @@ %span.like_action = like_action(post, current_user) - - if (post.author_id != current_user.person.id) && (post.public?) + - if resharable?(post) · %span.reshare_action = reshare_link(post) diff --git a/app/views/shared/_stream_element.mobile.haml b/app/views/shared/_stream_element.mobile.haml index 666591b90..cbe35079b 100644 --- a/app/views/shared/_stream_element.mobile.haml +++ b/app/views/shared/_stream_element.mobile.haml @@ -26,19 +26,19 @@ - if defined?(expanded_info) && expanded_info .comment_container .post_stats - - if @post.public? + - if post.public? %span.comment_count - = @post.reshares.size + = post.reshares.size %span.comment_count - = @post.comments.size + = post.comments.size %span.like_count - = @post.likes.size + = post.likes.size %ul.comments - = render :partial => 'comments/comment', :collection => @comments, :locals => {:post => @post} + = render :partial => 'comments/comment', :collection => post.comments, :locals => {:post => post} %li.comment.add_comment_bottom_link_container - = link_to "Add a comment", new_post_comment_path(@post), :class => 'add_comment_bottom_link btn comment_action inactive' + = link_to "Add a comment", new_post_comment_path(post), :class => 'add_comment_bottom_link btn comment_action inactive' diff --git a/app/views/tags/_followed_tags_listings.haml b/app/views/tags/_followed_tags_listings.haml index 7bd2e56e9..380cb25d8 100644 --- a/app/views/tags/_followed_tags_listings.haml +++ b/app/views/tags/_followed_tags_listings.haml @@ -5,7 +5,7 @@ - if user_signed_in? %ul.left_nav %li - %b=link_to t('aspects.index.tags_following'), tag_followings_path, :class => 'home_selector' + %b=link_to t('streams.followed_tag.title'), tag_followings_path, :class => 'home_selector' %ul.sub_nav - if tags.size > 0 diff --git a/app/views/tags/show.haml b/app/views/tags/show.haml index 3db8e4c54..99f2dae38 100644 --- a/app/views/tags/show.haml +++ b/app/views/tags/show.haml @@ -4,8 +4,8 @@ - content_for :page_title do - - if params[:name] - = "##{params[:name]}" + - if @stream.tag_name + = @stream.display_tag_name - else = t('.whatup', :pod => @pod_url) @@ -17,12 +17,12 @@ $(".button.tag_following").hover(function(){ $this = $(this); $this.removeClass("in_aspects"); - $this.val("#{t('.stop_following', :tag => params[:name])}"); + $this.val("#{t('.stop_following', :tag => @stream.tag_name)}"); }, function(){ $this = $(this); $this.addClass("in_aspects"); - $this.val("#{t('.following', :tag => params[:name])}"); + $this.val("#{t('.following', :tag => @stream.tag_name)}"); }); }); $(".people_stream .pagination a").live("click", function() { @@ -36,10 +36,10 @@ .span-6.tags_people %h3 - = t('people', :count => @people_count) + = t('people', :count => @stream.tagged_people_count) .side_stream.stream - = render :partial => 'people/index', :locals => {:people => @people} + = render :partial => 'people/index', :locals => {:people => @stream.tagged_people} %br @@ -49,28 +49,28 @@ .span-15.last .stream_container #author_info - - if user_signed_in? && current_user.person != @person + - if user_signed_in? .right - unless tag_followed? - = button_to t('.follow', :tag => params[:name]), tag_tag_followings_path(:name => params[:name]), :method => :post, :class => 'button take_action' + = button_to t('.follow', :tag => @stream.tag_name), tag_tag_followings_path(:name => @stream.tag_name), :method => :post, :class => 'button take_action' - else - = button_to t('.following', :tag => params[:name]), tag_tag_followings_path(:name => params[:name]), :method => :delete, :class => 'button red_on_hover tag_following in_aspects take_action' + = button_to t('.following', :tag => @stream.tag_name), tag_tag_followings_path(:name => @stream.tag_name), :method => :delete, :class => 'button red_on_hover tag_following in_aspects take_action' %h2 - = "##{params[:name]}" + = @stream.display_tag_name %small = t('.followed_by') - = t('people', :count => @tag_follow_count) + = t('people', :count => @stream.tag_follow_count) - if current_user - = render 'shared/publisher', :selected_aspects => all_aspects.map{|a| a.id}, :aspect_ids => all_aspects.map{|a| a.id}, :for_all_aspects => true, :aspect => all_aspects.first + = render 'shared/publisher', :selected_aspects => @stream.aspect_ids, :aspect_ids => @stream.aspect_ids, :for_all_aspects => true, :aspect => @stream.aspect %hr #main_stream.stream - - if @posts.length > 0 - = render 'shared/stream', :posts => @posts + - if @stream.posts.length > 0 + = render 'shared/stream', :posts => @stream.posts #pagination =link_to(t('more'), next_page_path, :class => 'paginate') - else - = t('.nobody_talking', :tag => "##{params[:name]}") + = t('.nobody_talking', :tag => @stream.display_tag_name) diff --git a/app/views/tags/show.mobile.haml b/app/views/tags/show.mobile.haml index 2e2ced94c..d87643c3d 100644 --- a/app/views/tags/show.mobile.haml +++ b/app/views/tags/show.mobile.haml @@ -3,11 +3,11 @@ -# the COPYRIGHT file. %h1 - = "##{params[:name]}" + = @stream.display_tag_name #main_stream.stream - = render 'shared/stream', :posts => @posts - -if @posts.length > 0 + = render 'shared/stream', :posts => @stream.posts + -if @stream.posts.length > 0 #pagination %a.more-link.paginate{:href => next_page_path} %h1 diff --git a/app/views/users/edit.html.haml b/app/views/users/edit.html.haml index f9f585dc3..f6f043053 100644 --- a/app/views/users/edit.html.haml +++ b/app/views/users/edit.html.haml @@ -71,8 +71,42 @@ %br %br %hr + %br + %h3#stream-preferences + = t('.stream_preferences') + = form_for current_user, :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + %p.checkbox_select + = f.label :show_community_spotlight_in_stream, t('.show_community_spotlight') + = f.check_box :show_community_spotlight_in_stream + + %br + = f.submit t('.change'), :class => 'button' + + %br + %br + %hr + %br + + %h3#getting-started-preferences + = t('.show_getting_started') + = form_for current_user, :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + %p.checkbox_select + = f.label :getting_started, t('.show_getting_started') + = f.check_box :getting_started + + %br + = f.submit t('.change'), :class => 'button' + + %br + %br + %hr + %br %h3 = t('.receive_email_notifications') = form_for 'user', :url => user_path, :html => { :method => :put } do |f| @@ -81,38 +115,38 @@ = f.fields_for :email_preferences do |type| #email_prefs %p.checkbox_select - = type.label t('.also_commented') - = type.check_box :also_commented, {:checked => @email_prefs['also_commented']}, false, true + = type.label :also_commented, t('.also_commented') + = type.check_box :also_commented, {:checked => @email_prefs['also_commented']}, false, true %br %p.checkbox_select - = type.label t('.mentioned') - = type.check_box :mentioned, {:checked => @email_prefs['mentioned']}, false, true + = type.label :mentioned, t('.mentioned') + = type.check_box :mentioned, {:checked => @email_prefs['mentioned']}, false, true %br %p.checkbox_select - = type.label t('.comment_on_post') - = type.check_box :comment_on_post, {:checked => @email_prefs['comment_on_post']}, false, true - - %br - %p.checkbox_select - = type.label t('.private_message') - = type.check_box :private_message, {:checked => @email_prefs['private_message']}, false, true - - %br - %p.checkbox_select - = type.label t('.started_sharing') - = type.check_box :started_sharing, {:checked => @email_prefs['started_sharing']}, false, true + = type.label :comment_on_post, t('.comment_on_post') + = type.check_box :comment_on_post, {:checked => @email_prefs['comment_on_post']}, false, true %br %p.checkbox_select - = type.label t('.liked') - = type.check_box :liked, {:checked => @email_prefs['liked']}, false, true + = type.label :private_message, t('.private_message') + = type.check_box :private_message, {:checked => @email_prefs['private_message']}, false, true %br %p.checkbox_select - = type.label t('.reshared') - = type.check_box :reshared, {:checked => @email_prefs['reshared']}, false, true + = type.label :started_sharing, t('.started_sharing') + = type.check_box :started_sharing, {:checked => @email_prefs['started_sharing']}, false, true + + %br + %p.checkbox_select + = type.label :liked, t('.liked') + = type.check_box :liked, {:checked => @email_prefs['liked']}, false, true + + %br + %p.checkbox_select + = type.label :reshared, t('.reshared') + = type.check_box :reshared, {:checked => @email_prefs['reshared']}, false, true %br = f.submit t('.change') diff --git a/app/views/users/getting_started.haml b/app/views/users/getting_started.haml index 1f5cbd217..6638c83d9 100644 --- a/app/views/users/getting_started.haml +++ b/app/views/users/getting_started.haml @@ -2,189 +2,80 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -.span-5.leftNavBar - #home_user_badge - = owner_image_link - %h3 - = current_user.first_name +- content_for :head do + = include_javascripts :profile - - unless has_completed_getting_started? - .section - %ul.left_nav - %li - = link_to t(".welcome"), getting_started_path, :class => "home_selector active" +%br - .section - = render 'aspects/aspect_listings' - - .section - = render 'tags/followed_tags_listings' - -.span-13.append-1 - .stream_container - %h2 - = welcome_text - %h4 +%section#hello-there + .hero-unit + %h1.center + = t('.well_hello_there') + %p.center = t(".community_welcome") - %p - = t(".not_mandatory") - %ul#getting_started - %li.profile{:class => ("completed" if has_completed_profile?)} - .getting_started_number - %h3 - = @step += 1 - .content - %h3 - = t(".fill_out_your_profile") - #getting_started_profile_photo - = person_image_link(current_user.person, :size => :thumb_medium) - %p - = t(".profile_description") - .span-8.fields - - [:full_name, :image_url, :birthday, :gender, :bio, :location, :tag_string].each do |attr| - .span-4.last - = profile_field_tag(current_user.person.profile, attr) + .clearfix + %br + %br - #edit_profile_button_div - = link_to t(".edit_profile"), edit_profile_path, :class => "button", :target => "_blank" + .clearfix + .row + %h2 + = t(".who_are_you") - - unless AppConfig[:configured_services].blank? - %li.services{:class => ("completed" if has_connected_services?)} - .getting_started_number - %h3 - = @step += 1 - .content - %h3 - = t('.connect_to_your_other_social_networks') - - %p - = t('.connect_to_your_other_social_networks_explanation_p1') - - if AppConfig[:configured_services].detect{|s| s == "facebook"} - = t('.connect_to_your_other_social_networks_explanation_p2') - - #getting_started_service_icons - - AppConfig.configured_services.each do |service| - - unless current_user.services.any?{|x| x.provider == service} - %span.service - %span.service_image - = link_to(image_tag("social_media_logos/#{service.to_s.downcase}-48x48.png", :title => service.to_s.titleize), "/auth/#{service}") - - else - %span.service - %span.service_image - = image_tag( "social_media_logos/#{service.to_s.downcase}-48x48.png", :title => service.to_s.titleize, :class => "dim") - %span.checkmark - = image_tag( "icons/check_yes_ok.png") - - %li.connect_with_people{:class => ("completed" if has_few_contacts?)} - .getting_started_number - %h3 - = @step += 1 - .content - %h3 - = t('.connect_with_people') - - %p - - = t('.connect_with_people_explanation_pt1', :bold => content_tag(:b, t('.bold'))).html_safe - = t('.connect_with_people_explanation_pt2') - - -unless AppConfig[:no_follow_diasporahq] - #diaspora_hq_pane - - if diasporahq = Person.find_by_diaspora_handle("diasporahq@joindiaspora.com") - = person_image_link(diasporahq, :size => :thumb_medium) - - .name - = person_link(diasporahq) - - .info - = t('.get_updates_from_core') - - .add_to_aspect - = render :partial => 'people/relationship_action', - :locals => { :person => diasporahq, - :contact => current_user.contact_for(diasporahq), - :current_user => current_user } - - #featured_users_pane - %h4 - = t('.featured_users') - - %div - - Person.featured_users[0..5].each do |person| - .featured_user_card_small - .right - .add_to_aspect - = render :partial => 'people/relationship_action', - :locals => { :person => person, - :contact => current_user.contact_for(person), - :current_user => current_user } - = person_image_link(person, :target => "_blank") - = person_link(person, :class => "hovercardable", :target => "_blank") - .tags - - person.profile.tags[0..2].each do |tg| - = link_to "##{tg}", tag_path(tg.name), :target => "_blank" - - = link_to "#{t('.see_all_featured_users')} ->", featured_users_path, :target => "_blank" - - %br - #find_friends_pane - %h4 - = t('.find_friends') - .span-5.append-1 - = form_tag(people_path, :method => 'get', :class => "people search_form") do - = text_field_tag 'q', nil, :placeholder => t(".search_for_people"), :type => 'search', :results => 5 - .span-5.last{:style => "height:30px;"} - %h4{:style => "margin-top:7px;"} - or - = link_to t('.find_friends_from_facebook'), friend_finder_path('facebook'), :target => "_blank" - .clearfix - %br - - %li.follow_interests{:class => ("completed" if has_few_followed_tags?)} - .getting_started_number - %h3 - = @step += 1 - .content - %h3 - = t('.follow_your_interests') - - %p - = t('.hashtag_explanation') - - .span-5.append-1 - = form_tag(tags_path, :method => 'get', :class => "tag_input search_form") do - = text_field_tag 'q', nil, :placeholder => t(".search_for_hashtags"), :type => 'search', :results => 5 - .span-5.last - %h4{:style => "margin-top:7px;"} - = t('.featured_tags') - %p - - ["diaspora", "art", "gif", "french"].each do |tag_name| - = tag_link(tag_name) - %br - .clearfix - %br - %br - - %li.cubbies{:class => ("completed" if has_connected_cubbies?)} - .getting_started_number - %h3 - = @step += 1 - .content - %h3 - = t(".connect_to") - = link_to "Cubbi.es", "http://cubbi.es/", :target => "_blank" - %p - = t('tokens.show.what_is_cubbies') - - .cubbies_images - = image_tag '/images/cubbies_collage.png', :width => 422, :height => 159, :class => "cubbies_collage_small" - = image_tag '/images/cubbies_screenshot2.png', :height => 151, :width => 200, :class => "cubbies_user_page_small" - - %li{:style => 'text-align:center;'} + .row %p - = link_to t('.finished'), getting_started_completed_path, :class => "button" + = t('.we_can_speed_things_up') + = link_to t('.hooking_up_fb'), "auth/facebook?callback_url=#{getting_started_url}" + = t('.what_facebook_does') + + .row + .span6 + = form_tag profile_path, :method => :put, :remote => true, :id => 'edit_profile' do + %fieldset + .clearfix + = label_tag 'profile[first_name]', "Your name", :class => "bootstrapped" + .input + = text_field_tag 'profile[first_name]', current_user.person.profile.first_name + = image_tag 'ajax-loader.gif', :id => "form_spinner", :class => "hidden" + + %span.saved{:class => "hidden"} + = image_tag 'icons/check_yes_ok.png' + = t(".saved") + + .clearfix + = label_tag :your_photo, "Your photo", :class => "bootstrapped" + .input{:style => "position:relative;"} + = render 'photos/new_profile_photo', :aspect => :getting_started, :person => current_user.person + %br + %br + + .clearfix + .row + %h2 + = t('.what_are_you_in_to') + + .row + %p + = t('.hashtag_explanation') + %i + = t('.hashtag_suggestions') + + .row + .span13 + = form_tag(multiple_tag_followings_path, :method => 'post', :class => "tag_input search_form") do + %fieldset + .clearfix + = label_tag 'follow_tags', "Follow tags", :class => "bootstrapped" + .input + = text_field_tag 'follow_tags', nil, :class => "nostrap" + + .clearfix + %br + %br + %br + .input + = link_to "#{t('.awesome_take_me_to_diaspora')} »", "#", :id => "awesome_button", :class => "btn primary" + + = image_tag 'ajax-loader.gif', :id => "awesome_spinner", :class => "hidden" -/.span-5.rightBar.last -/ = render 'selected_contacts', :people => @selected_people.sample(20), :count => @contact_count -/ = render 'shared/right_sections' diff --git a/app/views/users/logged_out.haml b/app/views/users/logged_out.haml index 4595bf96e..2ae90f64a 100644 --- a/app/views/users/logged_out.haml +++ b/app/views/users/logged_out.haml @@ -2,36 +2,31 @@ -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. +- content_for :head do + :css + body { + margin-top: 220px; + } + + #grey_header - .container{:style => 'text-align:center;'} - %h2 + .row + %h3 = t('.signed_out') %h1 = t('.go_mobile') .container{:style => 'text-align:center;'} - %br - %br - %br - %br - %br - %br - %br - %br - %br + .row.mobile_row + = image_tag 'diaspora_mobile_screens.png', :width => 480, :height => 300 - = image_tag 'mobile.jpg', :width => 150, :height => 294 + .row + %h4 + = t('.simply_visit') + %strong + = link_to AppConfig[:pod_url], root_url + = t('.on_your_mobile_device') - %br - %br - %br - - %h4 - = t('.simply_visit') - %strong - = link_to AppConfig[:pod_url], root_url - = t('.on_your_mobile_device') - - %p.dull - = t('.works_on_modern') + %p.dull + = t('.works_on_modern') diff --git a/config/application.yml.example b/config/application.yml.example index 222ef90da..c2817d5ce 100644 --- a/config/application.yml.example +++ b/config/application.yml.example @@ -60,10 +60,12 @@ defaults: &defaults # to contact joindiaspora.com, set this to true: no_follow_diasporahq: false - # Featured users + # Community Spotlight # (expressed as an array of Diaspora IDs) - featured_users: + community_spotlight: - 'diasporahq@joindiaspora.com' + # Email to send spotlight suggestions to + spotlight_suggest_email: '' # List of users who have admin privileges # (expressed as an array of local usernames) diff --git a/config/assets.yml b/config/assets.yml index 2bd5b17e9..7c3a66341 100644 --- a/config/assets.yml +++ b/config/assets.yml @@ -10,8 +10,8 @@ javascripts: jquery: - public/javascripts/vendor/jquery162.min.js main: + - public/javascripts/rails.validations.js - public/javascripts/rails.js - - public/javascripts/vendor/jquery.tipsy.js - public/javascripts/vendor/jquery.hotkeys.js - public/javascripts/vendor/jquery.autoresize.min.js - public/javascripts/vendor/jquery-ui-1.8.9.custom.min.js @@ -39,6 +39,10 @@ javascripts: - public/javascripts/contact-edit.js - public/javascripts/contact-list.js - public/javascripts/aspect-sorting.js + + - public/javascripts/vendor/bootstrap/bootstrap-twipsy.js + - public/javascripts/vendor/bootstrap/bootstrap-popover.js + login: - public/javascripts/login.js mobile: @@ -78,8 +82,8 @@ stylesheets: - public/stylesheets/hovercard.css - public/stylesheets/vendor/facebox.css - public/stylesheets/vendor/fileuploader.css - - public/stylesheets/vendor/tipsy.css - public/stylesheets/vendor/autoSuggest.css + - public/stylesheets/interim-bootstrap.css rtl: - public/stylesheets/rtl.css diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb index dd8b6e4f2..5afaacf8d 100644 --- a/config/initializers/carrierwave.rb +++ b/config/initializers/carrierwave.rb @@ -2,6 +2,9 @@ # licensed under the Affero General Public License version 3 or later. See # the COPYRIGHT file. +#Excon needs to see the CA Cert Bundle file +ENV["SSL_CERT_FILE"] = AppConfig[:ca_file] + CarrierWave.configure do |config| if AppConfig[:s3_key] && AppConfig[:s3_secret] && AppConfig[:s3_bucket] && AppConfig[:s3_region] config.storage = :s3 diff --git a/config/initializers/client_side_validations.rb b/config/initializers/client_side_validations.rb new file mode 100644 index 000000000..b598bd991 --- /dev/null +++ b/config/initializers/client_side_validations.rb @@ -0,0 +1,14 @@ +# ClientSideValidations Initializer + +#require 'client_side_validations/simple_form' if defined?(::SimpleForm) +#require 'client_side_validations/formtastic' if defined?(::Formtastic) + +# Uncomment the following block if you want each input field to have the validation messages attached. +ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| + unless html_tag =~ /^