Commit 685662c3 authored by Jordi Mallach's avatar Jordi Mallach

Merge branch 'master' of git://github.com/diaspora/diaspora

parents a6f68fa6 0b6c5421
......@@ -38,9 +38,10 @@ end
group :heroku do
gem 'pg'
gem 'mysql'
end
gem 'settingslogic', '2.0.6'
gem 'settingslogic', :git => 'git://github.com/binarylogic/settingslogic.git'
# database
gem 'activerecord-import'
......
......@@ -15,6 +15,12 @@ GIT
json
rails (>= 3.0.0)
GIT
remote: git://github.com/binarylogic/settingslogic.git
revision: 4884d455bf18d92723cb8190cfd2dbf87f3aafd5
specs:
settingslogic (2.0.8)
GIT
remote: git://github.com/diaspora/acts-as-taggable-on.git
revision: c3592fe1a906f6ff1cd12766c5cf1152c51eec40
......@@ -237,6 +243,7 @@ GEM
gem_plugin (>= 0.2.3)
multi_json (1.0.4)
multipart-post (1.1.4)
mysql (2.8.1)
mysql2 (0.2.17)
net-scp (1.0.4)
net-ssh (>= 1.99.1)
......@@ -360,7 +367,6 @@ GEM
ffi (~> 1.0.9)
multi_json (~> 1.0.4)
rubyzip
settingslogic (2.0.6)
simple_oauth (0.1.5)
sinatra (1.2.8)
rack (~> 1.1)
......@@ -450,6 +456,7 @@ DEPENDENCIES
mobile-fu
mock_redis
mongrel
mysql
mysql2 (= 0.2.17)
newrelic_rpm
nokogiri (~> 1.5.0)
......@@ -479,7 +486,7 @@ DEPENDENCIES
ruby-oembed
sass
selenium-webdriver (~> 2.16.0)
settingslogic (= 2.0.6)
settingslogic!
sqlite3
thin (~> 1.3.1)
timecop
......
web: bundle exec rails s -p $PORT
web: bundle exec rails s thin -p $PORT
redis: redis-server
worker: QUEUE=* bundle exec rake resque:work
......@@ -54,29 +54,7 @@ class AspectMembershipsController < ApplicationController
end
end
def update
@person = Person.find(params[:person_id])
@from_aspect = current_user.aspects.where(:id => params[:aspect_id]).first
@to_aspect = current_user.aspects.where(:id => params[:to]).first
response_hash = { }
unless current_user.move_contact( @person, @to_aspect, @from_aspect)
flash[:error] = I18n.t 'aspects.move_contact.error',:inspect => params.inspect
end
if aspect = current_user.aspects.where(:id => params[:to]).first
response_hash[:notice] = I18n.t 'aspects.move_contact.success'
response_hash[:success] = true
else
response_hash[:notice] = I18n.t 'aspects.move_contact.failure'
response_hash[:success] = false
end
render :text => response_hash.to_json
end
rescue_from ActiveRecord::StatementInvalid do
render :text => "Duplicate record rejected.", :status => 400
end
end
require File.join(Rails.root, 'lib', 'stream', 'community_spotlight')
class CommunitySpotlightController < ApplicationController
def index
default_stream_action(Stream::CommunitySpotlight)
end
end
......@@ -42,7 +42,7 @@ class PeopleController < ApplicationController
#only do it if it is an email address
if diaspora_id?(params[:q])
people = Person.where(:diaspora_handle => params[:q].downcase)
webfinger(params[:q]) if people.empty?
Webfinger.in_background(params[:q]) if people.empty?
else
people = Person.search(params[:q], current_user)
end
......@@ -53,7 +53,7 @@ class PeopleController < ApplicationController
#only do it if it is an email address
if diaspora_id?(params[:q])
people = Person.where(:diaspora_handle => params[:q])
webfinger(params[:q]) if people.empty?
Webfinger.in_background(params[:q]) if people.empty?
else
people = Person.search(params[:q], current_user)
end
......@@ -131,7 +131,7 @@ class PeopleController < ApplicationController
def retrieve_remote
if params[:diaspora_handle]
webfinger(params[:diaspora_handle], :single_aspect_form => true)
Webfinger.in_background(params[:diaspora_handle], :single_aspect_form => true)
render :nothing => true
else
render :nothing => true, :status => 422
......@@ -161,7 +161,6 @@ class PeopleController < ApplicationController
@contact = current_user.contact_for(@person) || Contact.new
render :partial => 'aspect_membership_dropdown', :locals => {:contact => @contact, :person => @person, :hang => 'left'}
end
Webfinger.new(account, opts)
end
def diaspora_id?(query)
......@@ -169,9 +168,6 @@ class PeopleController < ApplicationController
end
private
def webfinger(account, opts = {})
Webfinger.new(account, opts)
end
def remote_profile_with_no_user_session?
@person && @person.remote? && !user_signed_in?
......
......@@ -21,7 +21,7 @@ module ApplicationHelper
if language != DEFAULT_LANGUAGE
translations = I18n.t('javascripts', :locale => language)
defaults.update(translations)
defaults.deep_merge!(translations)
end
defaults
......
# Copyright (c) 2012, Diaspora Inc. This file is
# licensed under the Affero General Public License version 3 or later. See
# the COPYRIGHT file.
module PostsHelper
def post_page_title(post)
if post.is_a?(Photo)
I18n.t "posts.show.photos_by", :count => 1, :author => post.status_message.author.name
elsif post.is_a?(Reshare)
I18n.t "posts.show.reshare_by", :author => post.author.name
else
if post.text.present?
truncate(post.text(:plain_text => true), :length => 20)
elsif post.respond_to?(:photos) && post.photos.present?
I18n.t "posts.show.photos_by", :count => post.photos.size, :author => post.author.name
end
end
end
end
......@@ -5,34 +5,32 @@
module StreamHelper
def next_page_path(opts ={})
if controller.instance_of?(TagsController)
tag_path(:name => @stream.tag_name, :max_time => time_for_scroll(opts[:ajax_stream], @stream))
tag_path(:name => @stream.tag_name, :max_time => time_for_scroll(@stream))
elsif controller.instance_of?(AppsController)
"/apps/1?#{{:max_time => @posts.last.created_at.to_i}.to_param}"
elsif controller.instance_of?(PeopleController)
local_or_remote_person_path(@person, :max_time => time_for_scroll(opts[:ajax_stream], @stream))
local_or_remote_person_path(@person, :max_time => time_for_scroll(@stream))
elsif controller.instance_of?(TagFollowingsController)
tag_followings_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream))
elsif controller.instance_of?(CommunitySpotlightController)
spotlight_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream))
tag_followings_path(:max_time => time_for_scroll(@stream))
elsif controller.instance_of?(MentionsController)
mentions_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream))
mentions_path(:max_time => time_for_scroll(@stream))
elsif controller.instance_of?(MultisController)
multi_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream))
multi_path(:max_time => time_for_scroll(@stream))
elsif controller.instance_of?(PostsController)
public_stream_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream))
public_stream_path(:max_time => time_for_scroll(@stream))
elsif controller.instance_of?(AspectsController)
aspects_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream), :a_ids => @stream.aspect_ids)
aspects_path(:max_time => time_for_scroll(@stream), :a_ids => @stream.aspect_ids)
elsif controller.instance_of?(LikeStreamController)
like_stream_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream))
like_stream_path(:max_time => time_for_scroll(@stream))
elsif controller.instance_of?(CommentStreamController)
comment_stream_path(:max_time => time_for_scroll(opts[:ajax_stream], @stream))
comment_stream_path(:max_time => time_for_scroll(@stream))
else
raise 'in order to use pagination for this new controller, update next_page_path in stream helper'
end
end
def time_for_scroll(ajax_stream, stream)
if ajax_stream || stream.stream_posts.empty?
def time_for_scroll(stream)
if stream.stream_posts.empty?
(Time.now() + 1).to_i
else
stream.stream_posts.last.send(stream.order.to_sym).to_i
......
......@@ -6,9 +6,11 @@ require 'uri'
require File.join(Rails.root, 'lib', 'enviroment_configuration')
class AppConfig < Settingslogic
ARRAY_VARS = [:community_spotlight, :admins]
def self.source_file_name
if ENV['application_yml'].present?
puts "using remote application.yml"
return ENV['application_yml']
end
config_file = File.join(Rails.root, "config", "application.yml")
if !File.exists?(config_file) && (Rails.env == 'test' || Rails.env.include?("integration") || EnviromentConfiguration.heroku?)
config_file = File.join(Rails.root, "config", "application.yml.example")
......@@ -121,18 +123,9 @@ HELP
def self.[] (key)
return self.pod_uri if key == :pod_uri
return fetch_from_env(key.to_s) if EnviromentConfiguration.heroku?
super
end
def fetch_from_env(key)
if ARRAY_VARS.include?(key.to_sym)
ENV[key].split(EnviromentConfiguration::ARRAY_SEPERATOR)
else
ENV[key] if ENV[key]
end
end
def self.[]= (key, value)
super
if key.to_sym == :pod_url
......
......@@ -84,5 +84,4 @@ class Comment < ActiveRecord::Base
def parent= parent
self.post = parent
end
end
# 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 FetchWebfinger < Base
@queue = :socket_webfinger
def self.perform(account)
Webfinger.new(account).fetch
end
end
end
......@@ -36,7 +36,7 @@ class Post < ActiveRecord::Base
t.add :user_like
t.add :mentioned_people
t.add lambda { |post|
if post.photos_count > 0
if post.respond_to?(:photos) && post.photos_count > 0
post.photos
else
[]
......
......@@ -40,10 +40,6 @@ class StatusMessage < Post
joins(:likes).where(:likes => {:author_id => person.id})
}
def photos_count
self.photos.size
end
def self.guids_for_author(person)
Post.connection.select_values(Post.where(:author_id => person.id).select('posts.guid').to_sql)
end
......@@ -177,7 +173,7 @@ class StatusMessage < Post
end
def update_photos_counter
StatusMessage.where(:id => self.id).
self.class.where(:id => self.id).
update_all(:photos_count => self.photos.count)
end
......@@ -192,6 +188,5 @@ class StatusMessage < Post
def self.tag_stream(tag_ids)
joins(:tags).where(:tags => {:id => tag_ids})
end
end
......@@ -172,17 +172,6 @@ class User < ActiveRecord::Base
end
######### Aspects ######################
def move_contact(person, to_aspect, from_aspect)
return true if to_aspect == from_aspect
contact = contact_for(person)
add_contact_to_aspect(contact, to_aspect)
membership = contact ? AspectMembership.where(:contact_id => contact.id, :aspect_id => from_aspect.id).first : nil
return(membership && membership.destroy)
end
def add_contact_to_aspect(contact, aspect)
return true if AspectMembership.exists?(:contact_id => contact.id, :aspect_id => aspect.id)
contact.aspect_memberships.create!(:aspect => aspect)
......
......@@ -65,6 +65,17 @@
- if rtl?
= include_stylesheets :rtl, :media => 'all'
:javascript
// Support for older browsers
if(Array.isArray === undefined) {
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) == '[object Array]';
};
}
if ((window.history) && (window.history.pushState === undefined)) {
window.history.pushState = function() { };
}
= csrf_meta_tag
<!--[if IE]>
= javascript_include_tag "/javascripts/ie.js"
......
......@@ -2,6 +2,9 @@
-# licensed under the Affero General Public License version 3 or later. See
-# the COPYRIGHT file.
- content_for :page_title do
= post_page_title @post
.span-20.append-2.prepend-2.last
#main_stream.stream.status_message_show
......
......@@ -614,6 +614,14 @@ en:
destroy: "Delete"
permalink: "permalink"
not_found: "Sorry, we couldn't find that post."
photos_by:
zero: "No photos by %{author}"
one: "One photo by %{author}"
two: "Two photos by %{author}"
few: "%{count} photos by %{author}"
many: "%{count} photos by %{author}"
other: "%{count} photos by %{author}"
reshare_by: "Reshare by %{author}"
share_visibilites:
update:
......
......@@ -114,12 +114,10 @@ Diaspora::Application.routes.draw do
resources :contacts, :except => [:update, :create] do
get :sharing, :on => :collection
end
resources :aspect_memberships, :only => [:destroy, :create, :update]
resources :aspect_memberships, :only => [:destroy, :create]
resources :share_visibilities, :only => [:update]
resources :blocks, :only => [:create, :destroy]
get 'spotlight' => 'community_spotlight#index', :as => 'spotlight'
get 'community_spotlight' => "contacts#spotlight", :as => 'community_spotlight'
get 'stream' => "multis#index", :as => 'multi'
......
......@@ -99,6 +99,7 @@ Feature: posting from the main page
Then I should see an uploaded image within the photo drop zone
And the publisher should be expanded
@wip
Scenario: hide a contact's post
Given I expand the publisher
When I fill in "status_message_fake_text" with "Here is a post for you to hide"
......@@ -114,8 +115,10 @@ Feature: posting from the main page
And I click to delete the first post
And I wait for the ajax to finish
And I go to "bob@bob.bob"'s page
And I wait for the ajax to finish
Then I should not see "Here is a post for you to hide"
When I am on the aspects page
And I wait for the ajax to finish
Then I should not see "Here is a post for you to hide"
Scenario: delete one of my posts
......
......@@ -65,16 +65,6 @@ class Stream::Aspect < Stream::Base
end
end
# Only ajax in the stream if all aspects are present.
# In this case, we know we're on the first page of the stream,
# as the default view for aspects/index is showing posts from
# all a user's aspects.
#
# @return [Boolean] see #for_all_aspects?
def ajax_stream?
!AppConfig[:redis_cache] && for_all_aspects?
end
# The title that will display at the top of the stream's
# publisher box.
#
......
......@@ -75,12 +75,6 @@ class Stream::Base
Rails.application.routes.url_helpers.contacts_path
end
#helpers
# @return [Boolean]
def ajax_stream?
false
end
# @return [Boolean]
def for_all_aspects?
true
......
class Stream::CommunitySpotlight < Stream::Base
def title
"Community Spotlight doing cool stuff!"
end
def link(opts={})
Rails.application.routes.url_helpers.spotlight_path(opts)
end
def contacts_title
"This week's community spotlight"
end
def contacts_link
Rails.application.routes.url_helpers.community_spotlight_path
end
def contacts_link_title
I18n.translate('aspects.selected_contacts.view_all_community_spotlight')
end
def posts
Post.all_public.where(:author_id => people.map{|x| x.id})
end
def people
Person.community_spotlight
end
end
......@@ -23,11 +23,6 @@ class Stream::Multi < Stream::Base
end.call
end
# @return [Boolean]
def ajax_stream?
false
end
#emits an enum of the groups which the post appeared
# :spotlight, :aspects, :tags, :mentioned
def post_from_group(post)
......
......@@ -16,7 +16,6 @@ class Stream::Public < Stream::Base
@posts ||= Post.all_public
end
def contacts_title
I18n.translate("streams.public.contacts_title")
end
......
......@@ -12,15 +12,15 @@ namespace :heroku do
application_config = YAML.load_file('config/application.yml')['production'] rescue {}
application_config.delete_if { |k, v| v.nil? or v.to_s.empty? }
heroku_env = application_config.map do|key, value|
value =value.join(EnviromentConfiguration::ARRAY_SEPERATOR) if value.respond_to?(:join)
#heroku_env = application_config.map do|key, value|
#value =value.join(EnviromentConfiguration::ARRAY_SEPERATOR) if value.respond_to?(:join)
"#{key}=\"#{value}\""
end.join(' ')
#"#{key}=\"#{value}\""
#end.join(' ')
puts "Generating and setting a new secret token"
token = ActiveSupport::SecureRandom.hex(40)#reloads secret token every time you reload vars.... this expires cookies, and kinda sucks
system "#{HEROKU_CONFIG_ADD_COMMAND} #{heroku_env} SECRET_TOKEN=#{token}"
system "#{HEROKU_CONFIG_ADD_COMMAND} HEROKU=true SECRET_TOKEN=#{token}"
end
task :install_requirements do
......
......@@ -9,6 +9,10 @@ class Webfinger
Rails.logger.info("event=webfinger status=initialized target=#{account}")
end
def self.in_background(account, opts={})
Resque.enqueue(Jobs::FetchWebfinger, account)
end
def fetch
begin
person = Person.by_account_identifier(@account)
......
document.createElement('header');
document.createElement('footer');
// IE 9 work-around for vendor/backbone.js
if ((window.history) && (document.documentMode == 9)) {
window.history.pushState = function() { };
}
......@@ -1194,6 +1194,7 @@ header #global_search
&:focus
@include box-shadow(0,0,5px,#fff)
:outline none
:background-color white
input[type='search']
:width 220px
......
......@@ -124,15 +124,4 @@ describe AspectMembershipsController do
end
end
end
describe "#update" do
it 'calls the move_contact method' do
@controller.stub!(:current_user).and_return(alice)
alice.should_receive(:move_contact)
put :update, :id => 123,
:person_id => alice.person.id,
:aspect_id => @aspect0.id,
:to => @aspect1.id
end
end
end
require 'spec_helper'
describe CommunitySpotlightController do
describe "GET 'index'" do
it "should be successful" do
sign_in alice
get 'index'
response.should be_success
end
end
end
......@@ -385,11 +385,4 @@ describe PeopleController do
@controller.diaspora_id?("ilya_2%3@joindiaspora.com").should be_false
end
end
describe '#webfinger' do
it 'calls Webfinger.new' do
Webfinger.should_receive(:new).with(@user.diaspora_handle, anything).once
get :retrieve_remote, :diaspora_handle => @user.diaspora_handle
end
end
end
......@@ -5,15 +5,4 @@
require 'spec_helper'
describe StreamHelper do
before do
@post = Factory(:status_message)
end
describe '#next_page_path' do
it 'works for apps page' do
stub!(:controller).and_return(AppsController.new)
@posts = [Factory(:activity_streams_photo)]
next_page_path.should include '/apps/1'
end
end
end
......@@ -62,7 +62,7 @@ describe Stream::Aspect do
stream.posts
end
it 'respects ordering' do
it 'respects ordering' do
stream = Stream::Aspect.new(@alice, [1,2], :order => 'created_at')
@alice.should_receive(:visible_shareables).with(Post, hash_including(:order => 'created_at DESC')).and_return(stub.as_null_object)
stream.posts
......@@ -132,40 +132,6 @@ describe Stream::Aspect do
end
end
describe '.ajax_stream?' do
before do
@original_value = AppConfig[:redis_cache]
@stream = Stream::Aspect.new(stub, stub)
end
after do
AppConfig[:redis_cache] = @original_value
end
context 'if we are not caching with redis' do
before do
AppConfig[:redis_cache] = false
end
it 'is true if stream is for all aspects?' do
@stream.stub(:for_all_aspects?).and_return(true)
@stream.ajax_stream?.should be_true
end
it 'is false if it is not for all aspects' do
@stream.stub(:for_all_aspects?).and_return(false)
@stream.ajax_stream?.should be_false
end
end
context 'if we are caching with redis' do
it 'returns false' do
AppConfig[:redis_cache] = true
@stream.ajax_stream?.should be_false
end
end
end
describe 'shared behaviors' do
before do
@stream = Stream::Aspect.new(alice, alice.aspects.map(&:id))
......
require 'spec_helper'
require File.join(Rails.root, 'spec', 'shared_behaviors', 'stream')
describe Stream::CommunitySpotlight do
before do
@stream = Stream::CommunitySpotlight.new(Factory(:user), :max_time => Time.now, :order => 'updated_at')
end
describe 'shared behaviors' do
it_should_behave_like 'it is a stream'
end
end
......@@ -144,28 +144,6 @@ describe AppConfig do
end
end
context 'configurations which are arrays' do
it 'should be set to be admins or community_spotlight' do
AppConfig::ARRAY_VARS.should =~ [:community_spotlight, :admins]
end
context 'on heroku' do
before do
ENV['admins'] = "maxwell#{EnviromentConfiguration::ARRAY_SEPERATOR}daniel"
EnviromentConfiguration.stub(:heroku?).and_return(true)
end
after do
EnviromentConfiguration.stub(:heroku?).and_return(false)
end
it 'converts a string with ARRAY_SEPERATOR to an array' do
AppConfig[:admins].should be_a Array
end
end
end
describe ".pod_uri" do
it "properly parses the pod_url" do
AppConfig.pod_uri = nil
......
......@@ -244,4 +244,22 @@ describe Photo do
}.should_not change(StatusMessage, :count)
end
end
describe 'photo cache counter' do
it "works" do
@s = @user.build_post(:status_message, :text => "sup?", :to => @aspect.id)
@s.save!
@s.reload.photos_count.should == 0
@s.photos << @photo
@s.save!
@s.reload.photos_count.should == 1
@s.photos << @photo2
@s.save!
@s.reload.photos_count.should == 2
@s.photos.last.destroy
@s.reload.photos_count.should == 1
@s.photos.first.destroy
@s.reload.photos_count.should == 0
end
end
end