social_stream 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
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" %>