social_stream 0.4.2 → 0.4.3

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 (78) hide show
  1. data/app/controllers/activities_controller.rb +1 -0
  2. data/app/controllers/avatars_controller.rb +17 -10
  3. data/app/controllers/comments_controller.rb +2 -0
  4. data/app/controllers/conversations_controller.rb +98 -103
  5. data/app/controllers/groups_controller.rb +3 -1
  6. data/app/controllers/likes_controller.rb +2 -0
  7. data/app/controllers/messages_controller.rb +4 -0
  8. data/app/controllers/posts_controller.rb +2 -2
  9. data/app/controllers/ties_controller.rb +6 -0
  10. data/app/helpers/subjects_helper.rb +32 -7
  11. data/app/helpers/ties_helper.rb +7 -2
  12. data/app/models/activity.rb +1 -1
  13. data/app/models/actor.rb +5 -8
  14. data/app/models/relation.rb +65 -0
  15. data/app/models/tie.rb +27 -7
  16. data/app/views/activities/_child.html.erb +1 -5
  17. data/app/views/activities/_root.html.erb +2 -4
  18. data/app/views/avatars/_form.html.erb +5 -16
  19. data/app/views/avatars/_precrop.html.erb +24 -17
  20. data/app/views/avatars/index.html.erb +47 -36
  21. data/app/views/avatars/new.html.erb +19 -3
  22. data/app/views/contacts/index.html.erb +1 -1
  23. data/app/views/contacts/index.js.erb +2 -0
  24. data/app/views/conversations/_conversation_full.html.erb +2 -1
  25. data/app/views/conversations/_index.html.erb +0 -7
  26. data/app/views/conversations/_show.html.erb +0 -7
  27. data/app/views/conversations/index.html.erb +9 -1
  28. data/app/views/conversations/index.js.erb +1 -0
  29. data/app/views/conversations/show.html.erb +1 -1
  30. data/app/views/conversations/show.js.erb +2 -0
  31. data/app/views/groups/_new.html.erb +9 -2
  32. data/app/views/groups/new.html.erb +5 -1
  33. data/app/views/layouts/_header.erb +23 -1
  34. data/app/views/layouts/_representation.html.erb +1 -1
  35. data/app/views/messages/new.html.erb +1 -1
  36. data/app/views/messages/new.js.erb +3 -0
  37. data/app/views/profiles/_profile.html.erb +18 -13
  38. data/app/views/profiles/edit.html.erb +29 -4
  39. data/app/views/profiles/update.js.erb +3 -3
  40. data/app/views/subjects/_toolbar_home_menu_options.html.erb +1 -1
  41. data/app/views/subjects/_toolbar_home_menu_options_subjects.html.erb +2 -2
  42. data/app/views/subjects/_toolbar_logo.html.erb +14 -2
  43. data/app/views/subjects/_toolbar_message_menu.html.erb +1 -1
  44. data/app/views/subjects/_toolbar_profile_menu_tie_options.html.erb +18 -7
  45. data/app/views/ties/_edit.html.erb +102 -0
  46. data/app/views/ties/_new.html.erb +48 -19
  47. data/app/views/ties/edit.html.erb +1 -0
  48. data/config/locales/en.yml +42 -27
  49. data/config/routes.rb +0 -6
  50. data/lib/generators/social_stream/templates/public/images/btn/arrowBlue.png +0 -0
  51. data/lib/generators/social_stream/templates/public/images/btn/shadow.png +0 -0
  52. data/lib/generators/social_stream/templates/public/javascripts/addContact.js +100 -0
  53. data/lib/generators/social_stream/templates/public/javascripts/avatars.js +8 -0
  54. data/lib/generators/social_stream/templates/public/javascripts/hoverIntent.js +84 -0
  55. data/lib/generators/social_stream/templates/public/javascripts/main.js +10 -1
  56. data/lib/generators/social_stream/templates/public/javascripts/menu.js +22 -6
  57. data/lib/generators/social_stream/templates/public/stylesheets/default/activities.css +2 -2
  58. data/lib/generators/social_stream/templates/public/stylesheets/default/addContact.css +29 -0
  59. data/lib/generators/social_stream/templates/public/stylesheets/default/avatars.css +79 -0
  60. data/lib/generators/social_stream/templates/public/stylesheets/default/base.css +44 -5
  61. data/lib/generators/social_stream/templates/public/stylesheets/default/header.css +151 -1
  62. data/lib/generators/social_stream/templates/public/stylesheets/default/home.css +1 -1
  63. data/lib/generators/social_stream/templates/public/stylesheets/default/jquery-ui.css +1 -1
  64. data/lib/generators/social_stream/templates/public/stylesheets/default/messages.css +6 -4
  65. data/lib/social_stream.rb +1 -1
  66. data/lib/social_stream/ability.rb +20 -0
  67. data/lib/social_stream/models/subject.rb +5 -1
  68. data/lib/social_stream/test_helpers/controllers.rb +55 -0
  69. data/lib/social_stream/version.rb +1 -1
  70. data/social_stream.gemspec +1 -1
  71. data/spec/controllers/comments_controller_spec.rb +38 -0
  72. data/spec/controllers/groups_controller_spec.rb +75 -5
  73. data/spec/factories/comment.rb +4 -0
  74. data/spec/models/tie_spec.rb +25 -15
  75. metadata +18 -10
  76. data/app/controllers/pshb_controller.rb +0 -55
  77. data/app/views/ties/new.js.erb +0 -12
  78. data/lib/social_stream/relations.rb +0 -46
@@ -27,18 +27,66 @@
27
27
  # See the documentation of {Permission} for more details on permission definition.
28
28
  #
29
29
  class Relation < ActiveRecord::Base
30
+ # The actor this relation belongs to
31
+ attr_accessor :actor
32
+
33
+ # Default relations are defined in this configuration file
34
+ CONFIG = File.join(::Rails.root, 'config', 'relations.yml')
35
+
30
36
  acts_as_nested_set
31
37
 
32
38
  scope :mode, lambda { |st, rt|
33
39
  where(:sender_type => st, :receiver_type => rt)
34
40
  }
35
41
 
42
+ validates_presence_of :name
43
+
36
44
  has_many :relation_permissions, :dependent => :destroy
37
45
  has_many :permissions, :through => :relation_permissions
38
46
 
39
47
  has_many :ties, :dependent => :destroy
40
48
 
49
+ before_create :initialize_sender_type
50
+ after_create :initialize_ties
51
+
41
52
  class << self
53
+ # Relations configuration
54
+ def config
55
+ @config ||= YAML.load_file(CONFIG)
56
+ end
57
+
58
+ def defaults_for(actor)
59
+ cfg_rels = config[actor.subject_type.underscore]
60
+
61
+ if cfg_rels.nil?
62
+ raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG }"
63
+ end
64
+
65
+ rels = {}
66
+
67
+ cfg_rels.each_pair do |name, cfg_rel|
68
+ rels[name] =
69
+ Relation.create! :actor => actor,
70
+ :receiver_type => cfg_rel['receiver_type'],
71
+ :name => cfg_rel['name']
72
+
73
+ if (ps = cfg_rel['permissions']).present?
74
+ ps.each do |p|
75
+ rels[name].permissions <<
76
+ Permission.find_or_create_by_action_and_object_and_function(*p)
77
+ end
78
+ end
79
+ end
80
+
81
+ # Parent, relations must be set after creation
82
+ # FIXME: Can fix with ruby 1.9 and ordered hashes
83
+ cfg_rels.each_pair do |name, cfg_rel|
84
+ rels[name].update_attribute(:parent, rels[cfg_rel['parent']]) if cfg_rel['parent'].present?
85
+ end
86
+
87
+ rels.values
88
+ end
89
+
42
90
  # Get relation from object, if possible
43
91
  #
44
92
  # Options::
@@ -103,4 +151,21 @@ class Relation < ActiveRecord::Base
103
151
  def mode
104
152
  Relation.mode(sender_type, receiver_type)
105
153
  end
154
+
155
+ private
156
+
157
+ # Before create callback
158
+ def initialize_sender_type
159
+ return if actor.blank?
160
+
161
+ self.sender_type = actor.subject_type
162
+ end
163
+
164
+ # Create reflexive ties for this actor
165
+ def initialize_ties
166
+ return if actor.blank?
167
+
168
+ ties.create! :sender => actor,
169
+ :receiver => actor
170
+ end
106
171
  end
data/app/models/tie.rb CHANGED
@@ -46,9 +46,12 @@
46
46
  #
47
47
  class Tie < ActiveRecord::Base
48
48
  attr_accessor :message
49
+ attr_accessor :relation_permissions
49
50
 
50
51
  # Facilitates relation assigment along with find_relation callback
51
52
  attr_writer :relation_name
53
+ # Facilitates new relation permissions assigment along with find_or build_relation callback
54
+ attr_reader :relation_permissions
52
55
 
53
56
  belongs_to :sender,
54
57
  :class_name => "Actor",
@@ -77,7 +80,6 @@ class Tie < ActiveRecord::Base
77
80
  scope :sent_or_received_by, lambda { |a|
78
81
  where(arel_table[:sender_id].eq(Actor.normalize_id(a)).
79
82
  or(arel_table[:receiver_id].eq(Actor.normalize_id(a))))
80
-
81
83
  }
82
84
 
83
85
  scope :related_by, lambda { |r|
@@ -97,10 +99,11 @@ class Tie < ActiveRecord::Base
97
99
  joins(:relation => :permissions).merge(Permission.follow)
98
100
  }
99
101
 
100
- validates_presence_of :sender_id, :receiver_id, :relation_id
102
+ validates_presence_of :sender_id, :receiver_id, :relation
101
103
 
102
- before_validation :find_relation
104
+ before_validation :find_or_build_relation
103
105
 
106
+ before_create :save_relation
104
107
  after_create :complete_weak_set
105
108
  after_create :create_activity
106
109
  after_create :send_message
@@ -236,14 +239,31 @@ class Tie < ActiveRecord::Base
236
239
  private
237
240
 
238
241
  # Before validation callback
242
+ # Assigns relation or builds it based on the param
243
+ def find_or_build_relation
244
+ return if find_relation || relation_name.blank?
245
+
246
+ self.relation = Relation.new :name => relation_name,
247
+ :actor => sender
248
+
249
+ relation.permission_ids = relation_permissions
250
+ end
251
+
239
252
  # Infers relation from its name and the type of the actors
240
253
  def find_relation
241
- if relation_name.present? &&
242
- relation_name != relation.try(:name) &&
243
- sender.present?
254
+ return if relation_name.blank?
255
+
256
+ if relation_name == relation.try(:name)
257
+ relation
258
+ elsif sender.present?
244
259
  self.relation = sender.relation(relation_name)
245
260
  end
261
+ end
262
+
263
+ def save_relation
264
+ relation.save! if relation.new_record?
246
265
  end
266
+
247
267
 
248
268
  # After create callback
249
269
  # Creates ties with weaker relations in the strength hierarchy of this tie
@@ -268,7 +288,7 @@ class Tie < ActiveRecord::Base
268
288
  # Send a message to the receiver of the tie
269
289
  def send_message
270
290
  if original? && message.present?
271
- sender.send_message(receiver, message, I18n.t("activity.verb.#{ contact_verb }.message", :name => sender.name))
291
+ sender.send_message(receiver, message, I18n.t("activity.verb.#{ contact_verb }.#{ receiver.subject_type }.message", :name => sender.name))
272
292
  end
273
293
  end
274
294
 
@@ -4,7 +4,6 @@
4
4
  :alt => activity.sender_subject.name),
5
5
  activity.sender_subject %>
6
6
  </div>
7
-
8
7
  <div class="activity_content">
9
8
  <div class="actor_name-activity_objects">
10
9
  <%= link_to(activity.sender_subject.name, activity.sender_subject) %>
@@ -12,11 +11,8 @@
12
11
  <%= render activity.activity_objects %>
13
12
  </span>
14
13
  </div>
15
-
16
14
  <%= render :partial => 'activities/options',
17
15
  :locals => { :activity => activity } %>
18
-
19
16
  </div>
20
17
  <% end %>
21
- <div class="space_comments">
22
- </div>
18
+ <div class="space_comments"></div>
@@ -25,15 +25,13 @@
25
25
  <%= render :partial => 'comments/new',
26
26
  :locals => { :activity => activity } %>
27
27
 
28
- </div>
29
- <div class="space_comments"></div>
30
-
28
+ </div>
31
29
 
32
30
  <div class="space_activities">
33
31
  <% if activity.activity_objects.count > 1 %>
34
32
  <div class="space_sub"></div>
35
33
  <%else %>
36
- <div class="space_center"></div>
34
+ <div class="#"></div>
37
35
  <%end%>
38
36
  </div>
39
37
  <% end %>
@@ -1,21 +1,10 @@
1
1
  <div class= "block">
2
2
  <div class = "content">
3
- <%= form_for :logo, @avatar,:url => avatars_path, :html => { :multipart => true, :id=>'new_logo_form' }, :remote => false do |f| %>
4
- <% if @avatar.errors.any? %>
5
- <div id="error_explanation">
6
- <h2><%= pluralize(@avatar.errors.count, "error") %> prohibited this logo from being saved:</h2>
7
- <ul>
8
- <% @avatar.errors.each do |msg| %><!--.full_messages -->
9
- <li>
10
- <%= msg[1] %>
11
- </li>
12
- <% end %>
13
- </ul>
14
- </div>
15
- <% end %>
16
- <%= f.file_field :logo %>
17
- <div class="actions">
18
- <%= f.submit t('avatar.upload') %>
3
+ <%= form_for Avatar.new,:html => { :multipart => true} do |f| %>
4
+ <div class="form_row">
5
+ <%= f.file_field :logo %>
6
+
7
+ <%= f.submit t('avatar.upload'), :class => "button" %>
19
8
  </div>
20
9
  <div id= "prueba">
21
10
  </div>
@@ -1,19 +1,25 @@
1
1
  <% my_file_name = File.basename(@avatar.logo.queued_for_write[:original].path) %>
2
2
 
3
-
4
- <div id="precropDiv" class = "block title content" style="width:500px;display:inline-block;padding: 5px 4px 5px 4px;">
5
- <%= image_tag "tmp/#{my_file_name}",:id=>"cropImage" %>
6
- </div>
7
-
8
- <div class = "block logo" style = "vertical-align:top;display:inline-block;padding: 5px 4px 5px 4px;" ><%= t('avatar.preview') %></br>
9
- <div style="width:100px;height:100px;overflow:hidden;margin-left:5px;" >
10
- <%= image_tag "tmp/#{my_file_name}",:id=>"preview" %>
3
+ <div class = "block">
4
+ <div id="precropPrev" >
5
+ <div class="form_row">
6
+ <%= t('avatar.preview') %>
7
+ </div>
8
+ <div id="precropPrevImg" class="logo">
9
+ <%= image_tag "tmp/#{my_file_name}",:id=>"preview" %>
10
+ </div>
11
+ </div>
12
+
13
+ <div class="form_row">
14
+ <%= t('avatar.original') %>
15
+ </div>
16
+
17
+ <div id="precropDiv" class = "block title content">
18
+ <%= image_tag "tmp/#{my_file_name}",:id=>"cropImage" %>
11
19
  </div>
12
20
  </div>
13
-
14
21
  <% content_for :javascript do %>
15
- $("#sidebar").remove();
16
- jQuery('#cropImage').Jcrop({
22
+ jQuery('#cropImage').Jcrop({
17
23
  bgColor: 'clear',
18
24
  bgOpacity: .6,
19
25
  setSelect: [ 0, 0, 200, 200 ],
@@ -31,8 +37,7 @@ function update_crop(coords) {
31
37
  ry = 100/$("#cropImage").height();
32
38
  coords.x = 0;
33
39
  coords.y = 0;
34
- }
35
-
40
+ }
36
41
 
37
42
  $('#preview').css({
38
43
  width: Math.round(rx * $("#cropImage").width()) + 'px',
@@ -48,12 +53,14 @@ function update_crop(coords) {
48
53
  }
49
54
  <% end %>
50
55
 
51
- <%= form_for :logo, @avatar,:url => avatars_path, :html => { :multipart => true } do |f| %>
52
-
56
+ <%= form_for @avatar, :html => { :multipart => true } do |f| %>
57
+ <div class= "block">
53
58
  <% for attribute in [:crop_x, :crop_y, :crop_w, :crop_h] %>
54
59
  <%= f.hidden_field attribute, :id => attribute %>
55
60
  <% end %>
56
61
  <%= f.hidden_field :name, :value => my_file_name %>
57
- <br>
58
- <p><%= f.submit t('avatar.crop_submit') %></p>
62
+ <div class="form_row center">
63
+ <%= f.submit t('avatar.crop_submit'), :class => "button" %>
64
+ </div>
65
+ </div>
59
66
  <% end %>
@@ -1,42 +1,53 @@
1
1
  <% toolbar :profile => current_subject %>
2
2
 
3
- <h1><%= t('avatar.list') %></h1>
4
-
5
- <table>
6
- <tr>
7
- <th></th>
8
- <th></th>
9
- <th></th>
10
- </tr>
3
+ <% content_for :headers do %>
4
+ <%= stylesheet_link_tag "avatars.css", :media => "screen, projection" %>
5
+ <%= javascript_include_tag 'avatars.js' %>
6
+ <% end %>
11
7
 
12
- <% current_subject.avatars.each do |avatar| %>
13
- <% unless avatar.id.blank? && (current_subject.avatars.size == 1) %>
14
- <% unless avatar.id.blank? %>
15
- <tr>
16
- <td style="margin-left: 5px;">
17
- <% if avatar.active%>
18
- <%= image_tag avatar.logo.url(:profile), :style => "border: 7px solid #e0eef5" %></image_tag>
19
- <td><%= link_to image_tag("btn/close.png", :class => "menu_icon"), avatar, :confirm => t('avatar.destroy_sure'), :method => :delete %></td>
20
- <td></td>
21
- <% else %>
22
- <%= image_tag avatar.logo.url(:profile), :style => "margin: 7px" %></image_tag>
23
- <td><%= link_to image_tag("btn/close.png"), avatar, :confirm => t('avatar.destroy_sure'), :method => :delete %></td>
24
- <td><%= link_to t('avatar.set_default'), avatar, :confirm => t('avatar.set_default_sure'), :method => :put %></td>
25
- <% end %>
26
- </td>
27
- </tr>
28
- <%end%>
29
- <%else%>
30
- <tr>
31
- <td>
32
- <%= t('avatar.no_avatars') %>
33
- </td>
34
- </tr>
35
-
36
- <% end %>
8
+ <% content_for :sidebar do %>
9
+ <%= render :partial => 'home/sidebar' %>
37
10
  <% end %>
38
- </table>
39
11
 
40
- <br />
12
+ <%= location(
13
+ link_to(image_tag("btn/btn_edit.png", :class => "menu_icon")+t('profile.one'), [current_subject,:profile]),
14
+ link_to(image_tag("btn/edit.png", :class => "menu_icon")+t('avatar.other'), avatars_path)
15
+ ) %>
41
16
 
42
- <%= link_to t('avatar.new_short'), new_avatar_path %>
17
+ <br class="clearfloat" />
18
+ <div class="space_center"></div>
19
+ <div class="space_center"></div>
20
+ <% unless(@avatars.empty? || (@avatars.first.present? && @avatars.first.id.blank?)) %>
21
+ <h2>Use your saved avatars ...</h2>
22
+ <div class="space_center"></div>
23
+ <div class="space_center"></div>
24
+ <div class="avatars">
25
+ <% @avatars.each do |avatar| %>
26
+ <% unless avatar.id.blank? %>
27
+ <%= div_for(avatar) do %>
28
+ <div class="boxgrid captionfull">
29
+ <%= image_tag(avatar.logo.url(:profile), :class => avatar.active ? 'default' : 'non_default', :size => '94x94') %>
30
+ <% if avatar.active %>
31
+ <div class="cover boxcaption">
32
+ <%= link_to "Delete avatar", avatar, :confirm => t('avatar.destroy_sure'), :method => :delete %>
33
+ </div>
34
+ <% else %>
35
+ <div class="cover boxcaption">
36
+ <%= link_to "Set as default", avatar, :confirm => t('avatar.set_default_sure'), :method => :put %>
37
+ <%= link_to "Delete avatar", avatar, :confirm => t('avatar.destroy_sure'), :method => :delete %>
38
+ </div>
39
+ <% end %>
40
+ </div>
41
+ <% end %>
42
+ <% end %>
43
+ <% end %>
44
+ </div>
45
+ <br />
46
+ <br class="clearfloat" />
47
+ <div class="space_center"></div>
48
+ <div class="space_center"></div>
49
+ <h2>... our upload a new one</h2>
50
+ <% else %>
51
+ <h2><%= t('avatar.new') %></h2>
52
+ <% end %>
53
+ <%= render :partial => 'form' %>
@@ -1,15 +1,31 @@
1
1
  <% content_for :headers do %>
2
2
  <%= javascript_include_tag 'jquery.Jcrop.min' %>
3
3
  <%= stylesheet_link_tag "jquery.Jcrop", :media => "screen, projection" %>
4
- <%= stylesheet_link_tag "logos", :media => "screen, projection" %>
4
+ <%= stylesheet_link_tag "avatars", :media => "screen, projection" %>
5
5
  <%end%>
6
+
6
7
  <% toolbar :profile => current_subject %>
8
+
9
+ <% content_for :sidebar do %>
10
+ <%= render :partial => 'home/sidebar' %>
11
+ <% end %>
12
+
13
+ <%= location(
14
+ link_to(image_tag("btn/btn_edit.png", :class => "menu_icon")+t('profile.one'), [current_subject,:profile]),
15
+ link_to(image_tag("btn/edit.png", :class => "menu_icon")+t('avatar.other'), avatars_path)
16
+ ) %>
17
+
18
+ <br class="clearfloat" />
19
+ <div class="space_center"></div>
20
+ <div class="space_center"></div>
7
21
  <div id="content_logo">
8
22
  <% if !@avatar.logo.errors['precrop'].blank? %>
9
- <h1><%= t('avatar.crop_image') %></h1>
23
+ <h2><%= t('avatar.crop_image') %></h2>
24
+ <br class="clearfloat" />
25
+ <div class="space_center"></div>
10
26
  <%= render :partial => 'precrop' %>
11
27
  <% else %>
12
- <h1><%= t('avatar.new') %></h1>
28
+ <h2><%= t('avatar.new') %></h2>
13
29
  <%= render :partial => 'form' %>
14
30
  <% end %>
15
31
  </div>
@@ -2,7 +2,7 @@
2
2
  <%= javascript_include_tag 'jquery.ba-url','ajax.paginate' %>
3
3
  <% end %>
4
4
 
5
- <% toolbar %>
5
+ <% toolbar :option => :contacts %>
6
6
 
7
7
  <div id="my_conferences">
8
8
  <div id="contacts" class="block">
@@ -1 +1,3 @@
1
1
  $('#list_contacts_ajax').html("<%= escape_javascript(render :partial => "contacts/index") %>");
2
+
3
+ <% toolbar :option => :contacts %>
@@ -10,6 +10,7 @@
10
10
  <div class="clearfloat">
11
11
  </div>
12
12
  <div class="participants">
13
+ <h3><%= t("message.participants") %>:</h3>
13
14
  <% conversation.recipients.each do |recp| %>
14
15
  <%= link_to image_tag(recp.logo.url(:tie), :title=>recp.name, :alt => recp.name), recp.subject %>
15
16
  <% end %>
@@ -38,7 +39,7 @@
38
39
  <% end %>
39
40
  <div class="block">
40
41
  <div class="form_row">
41
- Write your answer:
42
+ <%= t("message.answer") %>
42
43
  </div>
43
44
  <div class="form_row">
44
45
  <%= text_area_tag :body, nil,:rows =>6, :cols=> 53, :class => "required form_tag" %>