social_stream-base 0.19.2 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/javascripts/social_stream.follow.js +23 -0
- data/app/assets/javascripts/social_stream.wall.js.erb +3 -3
- data/app/controllers/search_controller.rb +30 -16
- data/app/helpers/location_helper.rb +1 -44
- data/app/helpers/search_helper.rb +7 -7
- data/app/models/activity.rb +0 -21
- data/app/models/activity_action.rb +8 -0
- data/app/models/activity_object.rb +55 -25
- data/app/models/activity_object_audience.rb +8 -0
- data/app/models/actor.rb +9 -0
- data/app/models/comment.rb +1 -3
- data/app/models/group.rb +3 -0
- data/app/models/post.rb +1 -3
- data/app/models/relation.rb +5 -0
- data/app/models/relation/follow.rb +6 -7
- data/app/models/relation/public.rb +5 -0
- data/app/models/relation/single.rb +11 -1
- data/app/views/activities/_new.html.erb +1 -1
- data/app/views/contacts/_link_follow.html.erb +8 -4
- data/app/views/followers/update.js.erb +2 -0
- data/app/views/layouts/_search.html.erb +2 -2
- data/app/views/search/_extended_search.html.erb +17 -17
- data/app/views/search/_form.html.erb +4 -4
- data/app/views/search/_header_search.html.erb +2 -2
- data/app/views/search/index.html.erb +1 -1
- data/app/views/search/index.js.erb +4 -4
- data/db/migrate/20120403175913_create_activity_object_audiences.rb +34 -0
- data/db/migrate/20120411132550_add_visit_count_to_activity_object.rb +9 -0
- data/db/migrate/20120411151413_relation_public_permissions.rb +8 -0
- data/lib/generators/social_stream/base/templates/initializer.rb +3 -0
- data/lib/social_stream-base.rb +2 -1
- data/lib/social_stream/ability/base.rb +14 -8
- data/lib/social_stream/base/dependencies.rb +1 -0
- data/lib/social_stream/base/thinking-sphinx.rb +18 -0
- data/lib/social_stream/base/version.rb +1 -1
- data/lib/social_stream/controllers/objects.rb +6 -0
- data/lib/social_stream/test_helpers/controllers.rb +1 -1
- data/lib/social_stream/views/location.rb +48 -0
- data/lib/tasks/db/populate.rake +1 -1
- data/lib/thinking-sphinx/social_stream.rb +3 -0
- data/spec/controllers/groups_controller_spec.rb +6 -6
- data/spec/controllers/posts_controller_spec.rb +6 -6
- data/spec/controllers/users_controller_spec.rb +4 -4
- data/spec/dummy/config/initializers/social_stream.rb +3 -0
- data/spec/factories/activity.rb +24 -1
- data/spec/factories/post.rb +1 -1
- data/spec/models/activity_authorization_spec.rb +1 -1
- data/spec/models/post_spec.rb +0 -4
- data/spec/models/relation_follow_spec.rb +8 -0
- metadata +73 -64
data/app/models/group.rb
CHANGED
@@ -34,6 +34,8 @@ class Group < ActiveRecord::Base
|
|
34
34
|
|
35
35
|
# Creates the ties from the founder to the group
|
36
36
|
def create_ties_from_founder
|
37
|
+
=begin
|
38
|
+
# FIXME: need to define a proper relation for this case. Maybe a system defined relation
|
37
39
|
author.sent_contacts.create! :receiver_id => actor_id,
|
38
40
|
:relation_ids => _relation_ids
|
39
41
|
|
@@ -41,6 +43,7 @@ class Group < ActiveRecord::Base
|
|
41
43
|
user_author.sent_contacts.create! :receiver_id => actor_id,
|
42
44
|
:relation_ids => _relation_ids
|
43
45
|
end
|
46
|
+
=end
|
44
47
|
end
|
45
48
|
|
46
49
|
# Creates the ties from the group to the participants
|
data/app/models/post.rb
CHANGED
data/app/models/relation.rb
CHANGED
@@ -67,6 +67,11 @@ class Relation < ActiveRecord::Base
|
|
67
67
|
where(:type => positive_names)
|
68
68
|
}
|
69
69
|
|
70
|
+
scope :allowing, lambda { |action, object|
|
71
|
+
joins(:permissions).
|
72
|
+
merge(Permission.where(:action => action).where(:object => object))
|
73
|
+
}
|
74
|
+
|
70
75
|
before_create :initialize_sender_type
|
71
76
|
|
72
77
|
class << self
|
@@ -4,11 +4,10 @@
|
|
4
4
|
# Use this model setting <tt>config.relation_model = :follow</tt> in your
|
5
5
|
# <tt>config/initializers/social_stream.rb</tt>
|
6
6
|
class Relation::Follow < Relation::Single
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
PERMISSIONS =
|
8
|
+
[
|
9
|
+
[ 'create', 'activity' ],
|
10
|
+
[ 'read', 'activity' ],
|
11
|
+
[ 'follow', nil ]
|
12
|
+
]
|
13
13
|
end
|
14
|
-
|
@@ -4,11 +4,21 @@
|
|
4
4
|
# these {Relation relations}.
|
5
5
|
#
|
6
6
|
class Relation::Single < Relation
|
7
|
+
PERMISSIONS = []
|
8
|
+
|
7
9
|
class << self
|
8
10
|
def instance
|
9
11
|
@instance ||=
|
10
|
-
first ||
|
12
|
+
first ||
|
13
|
+
create!(:permissions => permissions)
|
14
|
+
end
|
15
|
+
|
16
|
+
def permissions
|
17
|
+
self::PERMISSIONS.map{ |p|
|
18
|
+
Permission.find_or_create_by_action_and_object p.first, p.last
|
19
|
+
}
|
11
20
|
end
|
21
|
+
|
12
22
|
end
|
13
23
|
|
14
24
|
# The name of public relation
|
@@ -32,7 +32,7 @@
|
|
32
32
|
}
|
33
33
|
//For security with check "var default_security_width = '100px';" in activities.js.erb
|
34
34
|
<% end %>
|
35
|
-
<%= select_tag :
|
35
|
+
<%= select_tag :relation_ids, options_for_select(current_subject.activity_relations(receiver).sort.map{ |r| [ r.name, r.id ] }), :id => 'security', :multiple => true, :title => t("activity.privacy.myself.contacts.#{ receiver.class.to_s.underscore }") %>
|
36
36
|
<% else %>
|
37
37
|
<div id="security_chzn" class="chzn-container chzn-container-multi">
|
38
38
|
<ul class="chzn-choices">
|
@@ -1,9 +1,13 @@
|
|
1
1
|
<div class="<%= follow_link_class contact %>">
|
2
2
|
<% if contact.sent? %>
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
<div class="following-button">
|
4
|
+
<%= t 'contact.following' %>
|
5
|
+
</div>
|
6
|
+
<div class="unfollow-button">
|
7
|
+
<%= form_tag follower_path(contact), :method => :delete, :remote => true do |f| %>
|
8
|
+
<%= submit_tag t('contact.unfollow') %>
|
9
|
+
<% end %>
|
10
|
+
</div>
|
7
11
|
<% else %>
|
8
12
|
<%= form_tag follower_path(contact), :method => :put, :remote => true do |f| %>
|
9
13
|
<%= submit_tag t('contact.follow') %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div id="header_search">
|
2
2
|
<form action="<%=search_path%>" method="get" id="header_search_form">
|
3
|
-
<%= text_field_tag :
|
3
|
+
<%= text_field_tag :q, nil,:autocomplete => :off, :id => :header_search_input %>
|
4
4
|
</form>
|
5
5
|
<div id="header_search_display">
|
6
6
|
<ul><li class="loading"><%= image_tag('loading.gif', :class => :loading) %></li></ul>
|
@@ -44,7 +44,7 @@ $(document).ready(function() {
|
|
44
44
|
$("#header_search_display").html("<ul><li class=\"loading\"><%= escape_javascript(image_tag('loading.gif', :class => :loading)) %></li></ul>").show();
|
45
45
|
$.ajax({
|
46
46
|
type : "GET",
|
47
|
-
url : "<%= search_url %>?
|
47
|
+
url : "<%= search_url %>?q=" + searchstring + "&mode=header_search",
|
48
48
|
success : function(html) {
|
49
49
|
if ($("#header_search_input").val()==searchstring){ //Only show if input value is still the same
|
50
50
|
$("#header_search_display").html(html);
|
@@ -1,19 +1,19 @@
|
|
1
1
|
<% if @search_result.empty? %>
|
2
|
-
<div class="model_with_details">
|
3
|
-
|
4
|
-
</div>
|
2
|
+
<div class="model_with_details">
|
3
|
+
<%= I18n.t('search.nothing') %>
|
4
|
+
</div>
|
5
5
|
<% else %>
|
6
|
-
<% @search_result.each do |model|%>
|
7
|
-
<% if @search_class_sym.nil? %>
|
8
|
-
<div class="subject_search_results block left">
|
9
|
-
|
10
|
-
</div>
|
11
|
-
<% else %>
|
12
|
-
<div class="subject_search_results block left <%= model.class.name.downcase %>">
|
13
|
-
|
14
|
-
</div>
|
15
|
-
<% end %>
|
16
|
-
<% end %>
|
17
|
-
<br class="clearfloat">
|
18
|
-
<%= paginate @search_result %>
|
19
|
-
<% end %>
|
6
|
+
<% @search_result.each do |model|%>
|
7
|
+
<% if @search_class_sym.nil? %>
|
8
|
+
<div class="subject_search_results block left">
|
9
|
+
<%= render_global_search_for model %>
|
10
|
+
</div>
|
11
|
+
<% else %>
|
12
|
+
<div class="subject_search_results block left <%= model.class.name.downcase %>">
|
13
|
+
<%= render_focus_search_for model %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
<br class="clearfloat">
|
18
|
+
<%= paginate @search_result %>
|
19
|
+
<% end %>
|
@@ -1,20 +1,20 @@
|
|
1
1
|
<%= form_tag search_path, :method => :get,
|
2
2
|
:remote => true,
|
3
3
|
:id => "search_form" do %>
|
4
|
-
<%= hidden_field_tag :
|
4
|
+
<%= hidden_field_tag :type, params[:type] %>
|
5
5
|
<div class="block">
|
6
6
|
<div class="error" id="too_short_error" <%= 'style=display:block;' if too_short_query? %>><%= t('search.at_least') %></div>
|
7
7
|
|
8
8
|
<div class="form_row search_row">
|
9
|
-
<%= text_field_tag :
|
9
|
+
<%= text_field_tag :q, params[:q], :autocomplete => :off, :id => :global_search_input %>
|
10
10
|
</div>
|
11
11
|
|
12
12
|
<div id="focus_options" class="form_row search_row">
|
13
13
|
<ul class="menu_plain_list">
|
14
14
|
<li><%= link_to content_tag(:span,
|
15
15
|
t('search.show_all'),
|
16
|
-
:class => "global #{ params[:
|
17
|
-
search_path(:
|
16
|
+
:class => "global #{ params[:type].blank? && 'selected' }"),
|
17
|
+
search_path(:q => params[:q]),
|
18
18
|
:remote => true %></li>
|
19
19
|
<% SocialStream.extended_search_models.each do |model_sym| %>
|
20
20
|
<li>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<%= link_to raw('<li class="more">' +
|
11
11
|
t("search.global.first_result.#{ total == 1 ? 'one' : 'more' }", :count => total) +
|
12
12
|
'<br>' +
|
13
|
-
t('search.global.query', :query => truncate(h(params[:
|
13
|
+
t('search.global.query', :query => truncate(h(params[:q]),:length => 20)) +
|
14
14
|
'</li>'),
|
15
|
-
search_path(:
|
15
|
+
search_path(:q => params[:q]) %>
|
16
16
|
</ul>
|
@@ -3,13 +3,13 @@
|
|
3
3
|
|
4
4
|
$('#focus_options ul li a span').removeClass('selected');
|
5
5
|
|
6
|
-
<% if params[:
|
7
|
-
$('#focus_options ul li a span.<%= params[:
|
6
|
+
<% if params[:type].present? %>
|
7
|
+
$('#focus_options ul li a span.<%= params[:type].pluralize.downcase %>').addClass('selected');
|
8
8
|
<% else %>
|
9
9
|
$('#focus_options ul li a span.global').addClass('selected');
|
10
10
|
<% end %>
|
11
11
|
|
12
|
-
$('title').text('<%= t('search.name')%> <%= escape_javascript(params[:
|
12
|
+
$('title').text('<%= t('search.name')%> <%= escape_javascript(params[:q].present? ? ": #{params[:q]}" : "")%>');
|
13
13
|
|
14
14
|
<% if too_short_query? %>
|
15
15
|
$('#too_short_error').show();
|
@@ -19,4 +19,4 @@
|
|
19
19
|
|
20
20
|
$('#global_search_input').removeClass("searching");
|
21
21
|
|
22
|
-
setActivityPrivacyTooltips();
|
22
|
+
setActivityPrivacyTooltips();
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# This migration comes from social_stream_base_engine (originally 20120403175913)
|
2
|
+
class CreateActivityObjectAudiences < ActiveRecord::Migration
|
3
|
+
def change
|
4
|
+
create_table :activity_object_audiences do |t|
|
5
|
+
t.references :activity_object
|
6
|
+
t.references :relation
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_foreign_key :activity_object_audiences, :activity_objects, :name => 'activity_object_audiences_on_activity_object_id'
|
12
|
+
add_foreign_key :activity_object_audiences, :relations, :name => 'activity_object_audiences_on_relation_id'
|
13
|
+
|
14
|
+
|
15
|
+
ActivityObject.all.each do |ao|
|
16
|
+
post_activity = ao.post_activity
|
17
|
+
next if post_activity.blank?
|
18
|
+
|
19
|
+
ao.relation_ids = post_activity.relation_ids
|
20
|
+
end
|
21
|
+
|
22
|
+
ActivityObjectAudience.record_timestamps = false
|
23
|
+
|
24
|
+
ActivityObject.all.each do |ao|
|
25
|
+
ao.activity_object_audiences.each do |aud|
|
26
|
+
aud.created_at = aud.updated_at = ao.created_at
|
27
|
+
aud.save!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
ActivityObjectAudience.record_timestamps = true
|
32
|
+
ActivityObject.reset_column_information
|
33
|
+
end
|
34
|
+
end
|
@@ -41,3 +41,6 @@ SocialStream.setup do |config|
|
|
41
41
|
# Cleditor controls. It is used in new message editor, for example
|
42
42
|
# config.cleditor_controls = "bold italic underline strikethrough subscript superscript | size style | bullets | image link unlink"
|
43
43
|
end
|
44
|
+
|
45
|
+
# You can customize toolbar, sidebar and location bar from here
|
46
|
+
# See https://github.com/ging/social_stream/wiki/How-to-customize-the-toolbar,-sidebar-and-location
|
data/lib/social_stream-base.rb
CHANGED
@@ -35,7 +35,8 @@ module SocialStream
|
|
35
35
|
end
|
36
36
|
|
37
37
|
module Views
|
38
|
-
autoload :List,
|
38
|
+
autoload :List, 'social_stream/views/list'
|
39
|
+
autoload :Location, 'social_stream/views/location'
|
39
40
|
|
40
41
|
module Settings
|
41
42
|
autoload :Base, 'social_stream/views/settings/base'
|
@@ -13,20 +13,26 @@ module SocialStream
|
|
13
13
|
(SocialStream.objects - [ :actor, :comment ]).map{ |obj|
|
14
14
|
obj.to_s.classify.constantize
|
15
15
|
}.each do |klass|
|
16
|
-
can :create, klass do |
|
17
|
-
|
16
|
+
can :create, klass do |object| # can :create, Post do |post|
|
17
|
+
object.author.present? &&
|
18
|
+
object.owner.present? &&
|
19
|
+
object.author == Actor.normalize(subject) &&
|
20
|
+
( object.author == object.owner ||
|
21
|
+
object.owner.allow?(subject, 'create', 'activity') )
|
18
22
|
end
|
19
23
|
|
20
|
-
can :read, klass do |
|
21
|
-
|
24
|
+
can :read, klass do |object| # can :read, Post do |post|
|
25
|
+
object.authored_or_owned_by?(subject) ||
|
26
|
+
object.relation_ids.include?(Relation::Public.instance.id) ||
|
27
|
+
subject.present? && (object.relation_ids & subject.received_relation_ids).any?
|
22
28
|
end
|
23
29
|
|
24
|
-
can :update, klass do |
|
25
|
-
|
30
|
+
can :update, klass do |object| # can :update, Post do |post|
|
31
|
+
object.authored_or_owned_by?(subject)
|
26
32
|
end
|
27
33
|
|
28
|
-
can :destroy, klass do |
|
29
|
-
|
34
|
+
can :destroy, klass do |object| # can :destroy, Post do |post|
|
35
|
+
object.authored_or_owned_by?(subject)
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SocialStream
|
2
|
+
module Base
|
3
|
+
module ThinkingSphinx
|
4
|
+
module Index
|
5
|
+
module Builder
|
6
|
+
def activity_object_index
|
7
|
+
indexes activity_object.title, :as => :title
|
8
|
+
indexes activity_object.description, :as => :description
|
9
|
+
indexes activity_object.tags.name, :as => :tags
|
10
|
+
|
11
|
+
has created_at
|
12
|
+
has activity_object.author_action(:actor_id), :as => :author_id
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -8,6 +8,8 @@ module SocialStream
|
|
8
8
|
|
9
9
|
before_filter :set_author_ids, :only => [ :new, :create, :update ]
|
10
10
|
|
11
|
+
after_filter :increment_visit_count, :only => :show
|
12
|
+
|
11
13
|
load_and_authorize_resource :except => :index
|
12
14
|
|
13
15
|
respond_to :html, :js
|
@@ -27,6 +29,10 @@ module SocialStream
|
|
27
29
|
|
28
30
|
protected
|
29
31
|
|
32
|
+
def increment_visit_count
|
33
|
+
resource.activity_object.increment!(:visit_count) if request.format == 'html'
|
34
|
+
end
|
35
|
+
|
30
36
|
def set_author_ids
|
31
37
|
resource_params.first[:author_id] = current_subject.try(:actor_id)
|
32
38
|
resource_params.first[:user_author_id] = current_user.try(:actor_id)
|
@@ -34,7 +34,7 @@ module SocialStream
|
|
34
34
|
|
35
35
|
def model_assigned_to contact, relation_ids
|
36
36
|
model_attributes[:owner_id] = contact.receiver.id
|
37
|
-
model_attributes[:
|
37
|
+
model_attributes[:relation_ids] = Array(relation_ids).map(&:id)
|
38
38
|
end
|
39
39
|
|
40
40
|
shared_examples_for "Allow Creating" do
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module SocialStream
|
2
|
+
module Views
|
3
|
+
module Location
|
4
|
+
# Renders the location stack for your view. You can add as many stack levels as you wish.
|
5
|
+
#
|
6
|
+
# Usage:
|
7
|
+
# <%= location(level1,leve2,level3,level4,....) %>
|
8
|
+
#
|
9
|
+
# Output:
|
10
|
+
# base > level1 > level2 > level3 > level 4
|
11
|
+
#
|
12
|
+
# Default configuration:
|
13
|
+
# base => "You are here" ("location.base" on config/locales)
|
14
|
+
# separator => ">" ("location.separator" on config/locales)
|
15
|
+
#
|
16
|
+
# Styles and HTML wrapping:
|
17
|
+
# partial => location/_location.html.erb
|
18
|
+
#
|
19
|
+
# Example:
|
20
|
+
# Render a location with two leves depth:
|
21
|
+
#
|
22
|
+
# <%= location(link_to(leve1.name, level1.url),link_to(leve2.name, level2.url)) %>
|
23
|
+
#
|
24
|
+
def location(*stack)
|
25
|
+
|
26
|
+
location_body = render :partial => "location/location_body", :locals=>{:stack => stack}
|
27
|
+
|
28
|
+
location_div = capture do
|
29
|
+
render :partial => "location/location", :locals=>{:location_body => location_body}
|
30
|
+
end
|
31
|
+
|
32
|
+
case request.format
|
33
|
+
when Mime::JS
|
34
|
+
response = <<-EOJ
|
35
|
+
|
36
|
+
$('#map_location').html("#{ escape_javascript(location_div) }");
|
37
|
+
EOJ
|
38
|
+
|
39
|
+
response.html_safe
|
40
|
+
else
|
41
|
+
content_for(:location) do
|
42
|
+
location_div
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|