social_stream-base 0.12.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/app/assets/images/flags/en.png +0 -0
  2. data/app/assets/images/flags/es.png +0 -0
  3. data/app/assets/javascripts/toolbar.js +22 -1
  4. data/app/assets/stylesheets/activities.css.scss +1 -1
  5. data/app/assets/stylesheets/cheesecake.css.scss +46 -4
  6. data/app/assets/stylesheets/settings.css +11 -0
  7. data/app/controllers/cheesecake_controller.rb +15 -3
  8. data/app/controllers/contacts_controller.rb +2 -0
  9. data/app/controllers/conversations_controller.rb +5 -5
  10. data/app/controllers/likes_controller.rb +1 -1
  11. data/app/helpers/notifications_helper.rb +10 -0
  12. data/app/models/activity.rb +55 -36
  13. data/app/models/activity_object.rb +3 -23
  14. data/app/models/actor.rb +20 -4
  15. data/app/models/channel.rb +13 -1
  16. data/app/models/comment.rb +4 -0
  17. data/app/models/contact.rb +55 -19
  18. data/app/models/group.rb +5 -2
  19. data/app/models/like.rb +2 -2
  20. data/app/models/relation/custom.rb +1 -1
  21. data/app/models/tie.rb +4 -3
  22. data/app/views/cheesecake/_cheesecake.html.erb +63 -0
  23. data/app/views/cheesecake/_index.html.erb +43 -86
  24. data/app/views/cheesecake/index.html.erb +2 -0
  25. data/app/views/cheesecake/update.js.erb +3 -0
  26. data/app/views/devise/passwords/new.html.erb +1 -1
  27. data/app/views/devise/registrations/new.html.erb +1 -1
  28. data/app/views/devise/sessions/new.html.erb +1 -1
  29. data/app/{assets/stylesheets/0_devise_sign.css → views/layouts/_devise_style.html.erb} +3 -1
  30. data/app/views/layouts/_header_signed_in.erb +1 -1
  31. data/app/views/message_mailer/new_message_email.html.erb +2 -1
  32. data/app/views/message_mailer/new_message_email.text.erb +2 -1
  33. data/app/views/message_mailer/reply_message_email.html.erb +2 -1
  34. data/app/views/message_mailer/reply_message_email.text.erb +2 -1
  35. data/app/views/notification_mailer/new_notification_email.html.erb +2 -1
  36. data/app/views/notification_mailer/new_notification_email.text.erb +2 -1
  37. data/app/views/notifications/activities/_post.html.erb +24 -1
  38. data/app/views/notifications/activities/_post.text.erb +22 -3
  39. data/app/views/settings/_language.html.erb +1 -1
  40. data/config/locales/en.yml +3 -2
  41. data/config/locales/es.yml +4 -3
  42. data/config/routes.rb +1 -0
  43. data/db/migrate/20120111141717_activity_channels.rb +74 -0
  44. data/lib/social_stream-base.rb +1 -0
  45. data/lib/social_stream/base/engine.rb +2 -1
  46. data/lib/social_stream/base/version.rb +1 -1
  47. data/lib/social_stream/models/channeled.rb +50 -0
  48. data/lib/social_stream/models/object.rb +4 -13
  49. data/lib/social_stream/toolbar_config/base.rb +1 -1
  50. data/lib/tasks/db/populate.rake +1 -1
  51. data/social_stream-base.gemspec +2 -2
  52. data/spec/controllers/comments_controller_spec.rb +3 -3
  53. data/spec/factories/activity.rb +3 -3
  54. data/spec/factories/contact.rb +2 -0
  55. data/spec/models/activity_authorization_spec.rb +5 -1
  56. data/spec/models/like_spec.rb +3 -3
  57. data/spec/models/tie_spec.rb +4 -4
  58. metadata +70 -64
  59. data/vendor/assets/javascripts/menu.js +0 -25
Binary file
Binary file
@@ -1 +1,22 @@
1
- //= require menu
1
+ function initMenu() {
2
+ $('.toolbar_menu ul li ul').hide();
3
+ $('.toolbar_menu li a').click( function() {
4
+ $(this).next().slideToggle('normal');
5
+ }
6
+ );
7
+ //Logo menu for current subject
8
+ //Full Caption Sliding (Hidden to Visible)
9
+ $('.logo_grid.logo_full').hover( function() {
10
+ $(".logo_menu", this).stop().animate({top:'101px'},{queue:false,duration:160});
11
+ }, function() {
12
+ $(".logo_menu", this).stop().animate({top:'1119px'},{queue:false,duration:160});
13
+ });
14
+ }
15
+
16
+ function expandSubMenu(id) {
17
+ $('#' + id + '_menu').next().show();
18
+ }
19
+
20
+ $(document).ready(function() {
21
+ initMenu();
22
+ });
@@ -33,7 +33,7 @@
33
33
  .super_activity{width: 95%;}
34
34
  .activity { text-align:left; display: block; vertical-align: top; padding: 10px 0px 5px 0px;
35
35
  display: inline-block; color: $sentence-color; font-size: 13px; color: $main-color;border-bottom:1px solid #E9E9E9;}
36
- .actor_logo { width: 38px; padding: 8px 0px 5px 5px; display: inline-block; vertical-align: top;}
36
+ .actor_logo { width: 38px; padding: 0px 0px 5px 5px; display: inline-block; vertical-align: top;}
37
37
  .activity_content { padding: 0px; display: inline-block; color: $sentence-color; width: 89%; word-wrap: break-word; }
38
38
  .actor_name {font-size: 13px;}
39
39
  .actor_name a{font-weight: bold;}
@@ -3,11 +3,13 @@
3
3
  #cheesecake {
4
4
  position: relative;
5
5
  padding: 20px;
6
+ padding-top: 0px;
6
7
  }
7
8
  #contacts_cheesecake {
8
9
  width: 440px;
9
10
  height: 440px;
10
- padding: 0px;
11
+ padding: 0px;
12
+ margin-top: 45px;
11
13
  float: left;
12
14
  }
13
15
  #contacts_filter {
@@ -39,19 +41,59 @@
39
41
  }
40
42
  #contacts_grid_extra {
41
43
  width: 270px;
42
- padding: 5px;
43
- height: 10px;
44
- border: solid 1px $input-border-color;
45
44
  text-align: center;
46
45
  float: right;
47
46
  margin-right: 20px;
48
47
  cursor: pointer;
48
+ vertical-align: middle;
49
+ padding-top: 6px;
50
+ background: #DEEFF8;
51
+ padding-left: 10px;
52
+ display: block;
53
+ height: 20px;
54
+ font-weight: bold;
55
+ }
56
+ #contacts_save {
57
+ width: 270px;
58
+ padding-right: 5px;
59
+ height: 25px;
60
+ text-align: right;
61
+ float: right;
62
+ margin-right: 20px;
63
+ }
64
+ #contacts_save_form {
65
+ overflow: visible;
66
+ }
67
+ #contacts_changes {
68
+ width: 705px;
69
+ margin-left: 20px;
70
+ }
71
+ #contacts_changes_title {
72
+ vertical-align: middle;
73
+ padding-top: 6px;
74
+ background: $secondary-color;
75
+ padding-left: 10px;
76
+ display: block;
77
+ height: 20px;
78
+ font-weight: bold;
79
+ cursor: pointer;
80
+ }
81
+ #contacts_changes_details {
82
+ border: solid 1px $secondary-color;
83
+ border-top: 0px;
84
+ padding: 5px;
85
+ display: none;
86
+ max-height: 200px;
87
+ }
88
+ #contacts_changes_details ul{
89
+ padding-left: 20px;
49
90
  }
50
91
  #contacts_grid .actor {
51
92
  width: 48px;
52
93
  height: 48px;
53
94
  float: left;
54
95
  margin: 4px;
96
+ display: none;
55
97
  }
56
98
  #contacts_grid .actor.focused {
57
99
  border: 2px solid $main-color;
@@ -3,6 +3,17 @@
3
3
  display:block;
4
4
  padding-left:10px;
5
5
  }
6
+ select#language {
7
+ background: #fff;
8
+ }
9
+ select#language option {
10
+ padding: 3px 0 3px 30px;
11
+ background-repeat: no-repeat;
12
+ background-position: 3px center;
13
+ }
14
+ select#language option[value=browser] { padding-left: 0; }
15
+ select#language option[value=en] { background-image: url(flags/en.png); }
16
+ select#language option[value=es] { background-image: url(flags/es.png); }
6
17
  #api_token {
7
18
  font-weight: bold;
8
19
  font-style: italic;
@@ -1,9 +1,21 @@
1
1
  class CheesecakeController < ApplicationController
2
-
2
+
3
3
  before_filter :authenticate_user!
4
-
5
4
  def index
6
5
  @actors = current_subject.contact_actors(:direction => :sent)
7
6
  end
8
-
7
+
8
+ def update
9
+ changes = JSON.parse params[:contacts_save_changes] if params[:contacts_save_changes].is_a? String
10
+
11
+ if (actors = changes["actors"]).present? and actors.is_a? Array
12
+ actors.each do |actor|
13
+ next if (contact = Contact.find_by_id(actor["extraInfo"].to_i)).nil?
14
+ contact.relation_ids = actor["subsectors"]
15
+ end
16
+ end
17
+
18
+ @actors = current_subject.contact_actors(:direction => :sent)
19
+ end
20
+
9
21
  end
@@ -24,6 +24,8 @@ class ContactsController < ApplicationController
24
24
  params[:contact][:relation_ids].present? &&
25
25
  params[:contact][:relation_ids].delete("0")
26
26
 
27
+ params[:contact][:user_author] = current_user
28
+
27
29
  if @contact.update_attributes(params[:contact])
28
30
  redirect_to @contact.receiver_subject
29
31
  else
@@ -4,12 +4,12 @@ class ConversationsController < ApplicationController
4
4
  before_filter :get_mailbox, :get_box, :get_actor
5
5
  before_filter :check_current_subject_in_conversation, :only => [:show, :update, :destroy]
6
6
  def index
7
- if @box.eql?"inbox"
8
- @conversations = Kaminari.paginate_array(@mailbox.inbox).page(params[:page]).per(9)
9
- elsif @box.eql?"sentbox"
10
- @conversations = Kaminari.paginate_array(@mailbox.sentbox).page(params[:page]).per(9)
7
+ if @box.eql? "inbox"
8
+ @conversations = @mailbox.inbox.page(params[:page]).per(9)
9
+ elsif @box.eql? "sentbox"
10
+ @conversations = @mailbox.sentbox.page(params[:page]).per(9)
11
11
  else
12
- @conversations = Kaminari.paginate_array(@mailbox.trash).page(params[:page]).per(9)
12
+ @conversations = @mailbox.trash.page(params[:page]).per(9)
13
13
  end
14
14
  end
15
15
 
@@ -3,7 +3,7 @@ class LikesController < ApplicationController
3
3
 
4
4
  # POST /activities/1/like.js
5
5
  def create
6
- @like = Like.build(current_subject, @indirect_id)
6
+ @like = Like.build(current_subject, current_user, @indirect_id)
7
7
 
8
8
  respond_to do |format|
9
9
  if @like.save
@@ -0,0 +1,10 @@
1
+ module NotificationsHelper
2
+
3
+ # Set locale as per subject preference
4
+ def locale_as(subject)
5
+ if subject.respond_to? :language
6
+ I18n.locale = subject.language || I18n.default_locale
7
+ end
8
+ end
9
+
10
+ end
@@ -1,10 +1,10 @@
1
1
  # Activities follow the {Activity Streams}[http://activitystrea.ms/] standard.
2
2
  #
3
- # == Activities, Contacts and Audiences
4
- # Every activity is attached to a {Contact}, which defines the sender and the receiver of the {Activity}
3
+ # == {Activity Activities}, {Channel Channels} and Audiences
4
+ # Every activity is attached to a {Channel}, which defines the sender and the receiver of the {Activity}
5
5
  #
6
- # Besides, the activity is attached to one or more relations, which define the audicence of the activity,
7
- # the {actors Actor} that can reach it and their {permissions Permission}
6
+ # Besides, the activity is attached to one or more relations, which define the audience of the activity,
7
+ # in other words, the {actors Actor} that can reach it and their {permissions Permission}
8
8
  #
9
9
  # == Wall
10
10
  # The Activity.wall(args) scope provides all the activities appearing in a wall
@@ -12,16 +12,15 @@
12
12
  # There are two types of wall, :home and :profile. Check {Actor#wall} for more information
13
13
  #
14
14
  class Activity < ActiveRecord::Base
15
+ # See {SocialStream::Models::Channeled}
16
+ channeled
17
+
15
18
  has_ancestry
16
19
 
17
20
  paginates_per 10
18
21
 
19
22
  belongs_to :activity_verb
20
23
 
21
- belongs_to :contact
22
- has_one :sender, :through => :contact
23
- has_one :receiver, :through => :contact
24
-
25
24
  has_many :audiences, :dependent => :destroy
26
25
  has_many :relations, :through => :audiences
27
26
 
@@ -33,7 +32,7 @@ class Activity < ActiveRecord::Base
33
32
  scope :wall, lambda { |args|
34
33
  q =
35
34
  select("DISTINCT activities.*").
36
- joins(:contact).
35
+ joins(:channel).
37
36
  joins(:audiences).
38
37
  joins(:relations).
39
38
  roots
@@ -43,13 +42,14 @@ class Activity < ActiveRecord::Base
43
42
  where('activity_objects.object_type' => args[:object_type])
44
43
  end
45
44
 
46
- contacts = Contact.arel_table
45
+ channels = Channel.arel_table
47
46
  audiences = Audience.arel_table
48
47
  relations = Relation.arel_table
49
48
 
50
49
  owner_conditions =
51
- contacts[:sender_id].eq(Actor.normalize_id(args[:owner])).
52
- or(contacts[:receiver_id].eq(Actor.normalize_id(args[:owner])))
50
+ channels[:author_id].eq(Actor.normalize_id(args[:owner])).
51
+ or(channels[:user_author_id].eq(Actor.normalize_id(args[:owner]))).
52
+ or(channels[:owner_id].eq(Actor.normalize_id(args[:owner])))
53
53
 
54
54
  audience_conditions =
55
55
  audiences[:relation_id].in(args[:relation_ids]).
@@ -59,16 +59,16 @@ class Activity < ActiveRecord::Base
59
59
  case args[:type]
60
60
  when :home
61
61
  followed_conditions =
62
- contacts[:sender_id].in(args[:followed]).
63
- or(contacts[:receiver_id].in(args[:followed]))
62
+ channels[:author_id].in(args[:followed]).
63
+ or(channels[:owner_id].in(args[:followed]))
64
64
 
65
65
  owner_conditions.
66
66
  or(followed_conditions.and(audience_conditions))
67
67
  when :profile
68
68
  if args[:for].present?
69
69
  visitor_conditions =
70
- contacts[:sender_id].eq(Actor.normalize_id(args[:for])).
71
- or(contacts[:receiver_id].eq(Actor.normalize_id(args[:for])))
70
+ channels[:author_id].eq(Actor.normalize_id(args[:for])).
71
+ or(channels[:owner_id].eq(Actor.normalize_id(args[:for])))
72
72
 
73
73
  owner_conditions.
74
74
  and(visitor_conditions.or(audience_conditions))
@@ -110,7 +110,7 @@ class Activity < ActiveRecord::Base
110
110
  # This method provides the {Actor}. Use {#sender_subject} for the {SocialStream::Models::Subject Subject}
111
111
  # ({User}, {Group}, etc..)
112
112
  def sender
113
- contact.sender
113
+ channel.author
114
114
  end
115
115
 
116
116
  # The {SocialStream::Models::Subject Subject} author of this activity
@@ -118,7 +118,7 @@ class Activity < ActiveRecord::Base
118
118
  # This method provides the {SocialStream::Models::Subject Subject} ({User}, {Group}, etc...).
119
119
  # Use {#sender} for the {Actor}.
120
120
  def sender_subject
121
- contact.sender_subject
121
+ channel.author_subject
122
122
  end
123
123
 
124
124
  # The wall where the activity is shown belongs to receiver
@@ -126,7 +126,7 @@ class Activity < ActiveRecord::Base
126
126
  # This method provides the {Actor}. Use {#receiver_subject} for the {SocialStream::Models::Subject Subject}
127
127
  # ({User}, {Group}, etc..)
128
128
  def receiver
129
- contact.receiver
129
+ channel.owner
130
130
  end
131
131
 
132
132
  # The wall where the activity is shown belongs to the receiver
@@ -134,7 +134,7 @@ class Activity < ActiveRecord::Base
134
134
  # This method provides the {SocialStream::Models::Subject Subject} ({User}, {Group}, etc...).
135
135
  # Use {#receiver} for the {Actor}.
136
136
  def receiver_subject
137
- contact.receiver_subject
137
+ channel.owner_subject
138
138
  end
139
139
 
140
140
  # The comments about this activity
@@ -148,7 +148,7 @@ class Activity < ActiveRecord::Base
148
148
  end
149
149
 
150
150
  def liked_by(user) #:nodoc:
151
- likes.joins(:contact).merge(Contact.sent_by(user))
151
+ likes.joins(:channel).merge(Channel.subject_authored_by(user))
152
152
  end
153
153
 
154
154
  # Does user like this activity?
@@ -157,9 +157,12 @@ class Activity < ActiveRecord::Base
157
157
  end
158
158
 
159
159
  # Build a new children activity where subject like this
160
- def new_like(subject)
160
+ def new_like(subject, user)
161
+ channel = Channel.new :author => Actor.normalize(subject),
162
+ :user_author => Actor.normalize(user),
163
+ :owner => owner
161
164
  a = children.new :verb => "like",
162
- :contact => subject.contact_to!(receiver),
165
+ :channel => channel,
163
166
  :relation_ids => self.relation_ids
164
167
 
165
168
  if direct_activity_object.present?
@@ -207,7 +210,7 @@ class Activity < ActiveRecord::Base
207
210
  return true if !notificable?
208
211
  #Avaible verbs: follow, like, make-friend, post, update
209
212
 
210
- if ['like','follow','make-friend','post','update'].include? verb and !contact.reflexive?
213
+ if ['like','follow','make-friend','post','update'].include? verb and !channel.reflexive?
211
214
  receiver.notify(notification_subject, "Youre not supposed to see this", self)
212
215
  end
213
216
  true
@@ -215,15 +218,15 @@ class Activity < ActiveRecord::Base
215
218
 
216
219
  # Is subject allowed to perform action on this {Activity}?
217
220
  def allow?(subject, action)
218
- return false if contact.blank?
221
+ return false if channel.blank?
219
222
 
220
223
  case action
221
224
  when 'create'
222
- return false if contact.sender_id != Actor.normalize_id(subject)
225
+ return false if subject.blank? || channel.author_id != Actor.normalize_id(subject)
223
226
 
224
227
  rels = Relation.normalize(relation_ids)
225
228
 
226
- own_rels = rels.select{ |r| r.actor_id == contact.sender_id }
229
+ own_rels = rels.select{ |r| r.actor_id == channel.author_id }
227
230
  foreign_rels = rels - own_rels
228
231
 
229
232
  # Only posting to own relations or allowed to post to foreign relations
@@ -239,12 +242,12 @@ class Activity < ActiveRecord::Base
239
242
 
240
243
  return false if subject.blank?
241
244
 
242
- return true if [contact.sender_id, contact.receiver_id].include?(Actor.normalize_id(subject))
245
+ return true if [channel.author_id, channel.owner_id].include?(Actor.normalize_id(subject))
243
246
  when 'update'
244
- return true if contact.sender_id == Actor.normalize_id(subject)
247
+ return true if [channel.author_id, channel.owner_id].include?(Actor.normalize_id(subject))
245
248
  when 'destroy'
246
249
  # We only allow destroying to sender and receiver by now
247
- return [contact.sender_id, contact.receiver_id].include?(Actor.normalize_id(subject))
250
+ return [channel.author_id, channel.owner_id].include?(Actor.normalize_id(subject))
248
251
  end
249
252
 
250
253
  Relation.
@@ -302,10 +305,10 @@ class Activity < ActiveRecord::Base
302
305
 
303
306
  # FIXME: repeated in SocialStream::Models::Object#_relation_ids
304
307
  self.relation_ids =
305
- if contact.reflexive?
308
+ if channel.reflexive?
306
309
  receiver.relation_customs.map(&:id)
307
310
  else
308
- receiver.relation_customs.allow(contact.sender, 'create', 'activity').map(&:id)
311
+ receiver.relation_customs.allow(channel.author, 'create', 'activity').map(&:id)
309
312
  end
310
313
  end
311
314
 
@@ -340,11 +343,27 @@ class Activity < ActiveRecord::Base
340
343
  :who => I18n.t('notification.who.'+ receiver.subject.class.to_s.underscore,
341
344
  :name => receiver_name))
342
345
  when 'post'
343
- I18n.t('notification.post.'+ receiver.subject.class.to_s.underscore,
346
+ if direct_object.is_a? Comment
347
+ I18n.t('notification.post.'+ receiver.subject.class.to_s.underscore,
344
348
  :sender => sender_name,
345
- :whose => I18n.t('notification.whose.'+ receiver.subject.class.to_s.underscore,
346
- :receiver => receiver_name),
347
- :thing => I18n.t(direct_object.class.to_s.underscore+'.one'))
349
+ :whose => I18n.t('notification.whose.'+ receiver.subject.class.to_s.underscore,
350
+ :receiver => receiver_name),
351
+ :title => 'Re: ' + direct_object.parent_post.text.truncate(30, :separator => ' '))
352
+ elsif direct_object.is_a? Post
353
+ I18n.t('notification.post.'+ receiver.subject.class.to_s.underscore,
354
+ :sender => sender_name,
355
+ :whose => I18n.t('notification.whose.'+ receiver.subject.class.to_s.underscore,
356
+ :receiver => receiver_name),
357
+ :title => direct_object.text.truncate(30, :separator => ' '))
358
+ elsif direct_object.respond_to? :title
359
+ I18n.t('notification.post.'+ receiver.subject.class.to_s.underscore,
360
+ :sender => sender_name,
361
+ :whose => I18n.t('notification.whose.'+ receiver.subject.class.to_s.underscore,
362
+ :receiver => receiver_name),
363
+ :title => direct_object.title.truncate(30, :separator => ' '))
364
+ else
365
+ I18n.t('notification.default')
366
+ end
348
367
  when 'update'
349
368
  I18n.t('notification.update.'+ receiver.subject.class.to_s.underscore,
350
369
  :sender => sender_name,
@@ -9,10 +9,9 @@
9
9
  # Objects are added to +config/initializers/social_stream.rb+
10
10
  #
11
11
  class ActivityObject < ActiveRecord::Base
12
- # ActivityObject is a subtype of Channel
13
- # Author, owner and user_author of this ActivityObject are defined in its channel
14
- subtype_of :channel,
15
- :belongs => { :dependent => nil }
12
+ # See {SocialStream::Models::Channeled}
13
+ channeled
14
+
16
15
  # ActivityObject is a supertype of SocialStream.objects
17
16
  supertype_of :object
18
17
 
@@ -27,8 +26,6 @@ class ActivityObject < ActiveRecord::Base
27
26
  joins(:channel).merge(Channel.authored_by(subject))
28
27
  }
29
28
 
30
- before_validation :check_existing_channel
31
-
32
29
  # The object of this activity object
33
30
  def object
34
31
  subtype_instance.is_a?(Actor) ?
@@ -45,21 +42,4 @@ class ActivityObject < ActiveRecord::Base
45
42
  def acts_as_actor?
46
43
  object_type == "Actor"
47
44
  end
48
-
49
- protected
50
-
51
- def check_existing_channel
52
- return unless channel!.new_record?
53
-
54
- existing_channel =
55
- Channel.
56
- where(:author_id => author_id,
57
- :owner_id => owner_id,
58
- :user_author_id => user_author_id).
59
- first
60
-
61
- return if existing_channel.blank?
62
-
63
- self.channel = existing_channel
64
- end
65
45
  end