social_stream-base 2.0.4 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +2 -0
  3. data/app/assets/javascripts/social_stream/relation_customs.js +8 -3
  4. data/app/assets/javascripts/social_stream/timeline.js +1 -2
  5. data/app/assets/javascripts/social_stream/wall.js +11 -0
  6. data/app/assets/stylesheets/social_stream/base/contacts/_contacts.css.sass +1 -0
  7. data/app/assets/stylesheets/social_stream/base/contacts/layouts/_contacts.css.sass +1 -42
  8. data/app/assets/stylesheets/social_stream/base/footer/layout/_footer.css.sass +3 -2
  9. data/app/assets/stylesheets/social_stream/base/layouts/_layout.css.sass +4 -1
  10. data/app/assets/stylesheets/social_stream/base/mixins/_layout.css.sass +48 -0
  11. data/app/assets/stylesheets/social_stream/base/profile/_profile.css.sass +21 -25
  12. data/app/assets/stylesheets/social_stream/base/sidebar/_sidebar.css.sass +1 -27
  13. data/app/assets/stylesheets/social_stream/base/sidebar/layout/_sidebar.css.sass +1 -24
  14. data/app/assets/stylesheets/social_stream/base/toolbar/_toolbar.css.sass +2 -11
  15. data/app/assets/stylesheets/social_stream/base/toolbar/layout/_toolbar.css.sass +18 -5
  16. data/app/controllers/contacts_controller.rb +17 -22
  17. data/app/controllers/permissions_controller.rb +3 -1
  18. data/app/helpers/contacts_helper.rb +9 -14
  19. data/app/models/actor.rb +28 -2
  20. data/app/models/contact.rb +18 -1
  21. data/app/models/permission.rb +21 -1
  22. data/app/models/relation.rb +14 -15
  23. data/app/models/relation/custom.rb +27 -24
  24. data/app/views/activities/_new.html.erb +1 -1
  25. data/app/views/contacts/{_link_custom.html.erb → _button.html.erb} +0 -0
  26. data/app/views/contacts/_contact.html.erb +1 -1
  27. data/app/views/contacts/index.html.erb +1 -1
  28. data/app/views/devise/passwords/new.html.erb +6 -8
  29. data/app/views/devise/registrations/new.html.erb +5 -7
  30. data/app/views/layouts/application.html.erb +7 -8
  31. data/app/views/permissions/_index.html.erb +12 -12
  32. data/app/views/permissions/_list.html.erb +10 -0
  33. data/app/views/permissions/index.js.erb +1 -15
  34. data/app/views/posts/create.js.erb +5 -4
  35. data/app/views/profiles/_personal.html.erb +2 -2
  36. data/app/views/relation/customs/_custom.html.erb +2 -27
  37. data/app/views/relation/customs/_form.html.erb +1 -1
  38. data/app/views/relation/customs/_index.html.erb +1 -1
  39. data/app/views/relation/customs/_list.html.erb +5 -4
  40. data/app/views/relation/customs/index.html.erb +1 -1
  41. data/app/views/relations/_relation.html.erb +33 -0
  42. data/config/locales/en.yml +10 -5
  43. data/config/locales/es.yml +20 -40
  44. data/config/locales/pt.yml +5 -1
  45. data/config/locales/zh.yml +17 -9
  46. data/lib/generators/social_stream/base/install_generator.rb +0 -4
  47. data/lib/generators/social_stream/base/templates/initializer.rb +24 -0
  48. data/lib/social_stream/base.rb +70 -0
  49. data/lib/social_stream/base/ability.rb +13 -1
  50. data/lib/social_stream/base/version.rb +1 -1
  51. data/lib/social_stream/test_helpers/controllers.rb +12 -6
  52. data/social_stream-base.gemspec +1 -1
  53. data/spec/controllers/permissions_controller_spec.rb +2 -6
  54. metadata +7 -7
  55. data/app/helpers/permissions_helper.rb +0 -21
  56. data/lib/generators/social_stream/base/templates/relations.yml +0 -39
@@ -15,6 +15,8 @@ class PermissionsController < ApplicationController
15
15
  private
16
16
 
17
17
  def relation!
18
- @relation = current_subject.relations.find(params[:relation_id])
18
+ @relation = Relation.find(params[:relation_id])
19
+
20
+ authorize! :read, @relation
19
21
  end
20
22
  end
@@ -10,38 +10,33 @@ module ContactsHelper
10
10
  # Add contact button
11
11
  def contact_button(contact_or_actor)
12
12
  if user_signed_in?
13
- current_actor_contact_button contact_or_actor
13
+ signed_in_contact_button contact_or_actor
14
14
  else
15
15
  anonymous_contact_button
16
16
  end
17
17
  end
18
18
 
19
- def current_actor_contact_button contact_or_actor
19
+ def signed_in_contact_button contact_or_actor
20
20
  c =
21
21
  if contact_or_actor.is_a?(Contact)
22
- if contact_or_actor.sender == current_actor
23
- contact_or_actor
24
- else
25
- current_actor.contact_to!(contact_or_actor.receiver)
26
- end
22
+ contact_or_actor
27
23
  else
28
24
  current_actor.contact_to!(contact_or_actor)
29
25
  end
30
26
 
31
27
  if c.reflexive?
32
28
  t('subject.this_is_you')
29
+ elsif can? :update, c
30
+ render partial: "contacts/button",
31
+ locals: { contact: c }
33
32
  else
34
- render :partial => "contacts/link_#{ SocialStream.relation_model }", :locals => { :contact => c }
33
+ ""
35
34
  end
36
35
  end
37
36
 
38
37
  def anonymous_contact_button
39
- if SocialStream.relation_model == :follow
40
- form_tag new_user_session_path do |f|
41
- submit_tag t('contact.follow')
42
- end
43
- else
44
- link_to t("contact.new.link"), new_user_session_path
38
+ form_tag new_user_session_path do |f|
39
+ submit_tag t('contact.new.button.zero')
45
40
  end
46
41
  end
47
42
 
@@ -51,10 +51,22 @@ class Actor < ActiveRecord::Base
51
51
  :through => :received_contacts,
52
52
  :source => :ties
53
53
 
54
+ has_many :sent_relations,
55
+ :through => :sent_ties,
56
+ :source => :relation
57
+
54
58
  has_many :received_relations,
55
59
  :through => :received_ties,
56
60
  :source => :relation
57
-
61
+
62
+ has_many :sent_permissions,
63
+ :through => :sent_relations,
64
+ :source => :permissions
65
+
66
+ has_many :received_permissions,
67
+ :through => :received_relations,
68
+ :source => :permissions
69
+
58
70
  has_many :senders,
59
71
  :through => :received_contacts,
60
72
  :uniq => true
@@ -200,6 +212,20 @@ class Actor < ActiveRecord::Base
200
212
  relations.joins(:relation_permissions => :permission).where('permissions.action' => 'notify')
201
213
  end
202
214
 
215
+ # The relations that will appear in privacy forms
216
+ #
217
+ # They usually include {Relation::Custom} but may also include other system-defined
218
+ # relations that are not editable but appear in add contact buttons
219
+ def relations_list
220
+ Relation.extra_list(subject) + relation_customs
221
+ end
222
+
223
+ # The relations offered in the "Add contact" button when subjects
224
+ # add new contacts
225
+ def relations_for_button
226
+ relations_list
227
+ end
228
+
203
229
  # All the {Actor Actors} this one has ties with:
204
230
  #
205
231
  # actor.contact_actors #=> array of actors that sent and receive ties from actor
@@ -334,7 +360,7 @@ class Actor < ActiveRecord::Base
334
360
  end
335
361
 
336
362
  # Does this {Actor} allow subject to perform action on object?
337
- def allow?(subject, action, object)
363
+ def allow?(subject, action, object = nil)
338
364
  ties_to(subject).with_permissions(action, object).any?
339
365
  end
340
366
 
@@ -48,6 +48,14 @@ class Contact < ActiveRecord::Base
48
48
  or(arel_table[:receiver_id].eq(Actor.normalize_id(a))))
49
49
  }
50
50
 
51
+ scope :in_direction_with, lambda { |subject, d = 'sent'|
52
+ if d == 'sent'
53
+ sent_by(subject).joins(:receiver)
54
+ else
55
+ received_by(subject).joins(:sender)
56
+ end
57
+ }
58
+
51
59
  scope :recent, order("contacts.created_at DESC")
52
60
 
53
61
  scope :active, where(arel_table[:ties_count].gt(0))
@@ -72,6 +80,15 @@ class Contact < ActiveRecord::Base
72
80
  end
73
81
  }
74
82
 
83
+ scope :index, lambda { |params|
84
+ in_direction_with(params[:subject], params[:d]).
85
+ positive.
86
+ merge(Actor.subject_type(params[:type])).
87
+ merge(Actor.name_search(params[:q])).
88
+ related_by_param(params[:relation]).
89
+ page(params[:page])
90
+ }
91
+
75
92
  validates_presence_of :sender_id, :receiver_id
76
93
  validates_uniqueness_of :sender_id, :scope => :receiver_id
77
94
  validates_uniqueness_of :receiver_id, :scope => :sender_id
@@ -165,7 +182,7 @@ class Contact < ActiveRecord::Base
165
182
 
166
183
  # Return an array of options suitable for the contact add button
167
184
  def options_for_select
168
- sender.relation_customs.map{ |r| [ r.name, r.id ] }
185
+ sender.relations_for_button.map{ |r| [ r.name, r.id ] }
169
186
  end
170
187
 
171
188
  private
@@ -43,9 +43,29 @@ class Permission < ActiveRecord::Base
43
43
  scope p, where(:action => p) # scope :represent, where(:action => 'represent')
44
44
  end
45
45
 
46
+ class << self
47
+ # Finds or creates in the database the instances of the permissions described in
48
+ # {ary} by arrays of [ action, object ]
49
+ def instances ary
50
+ ary.map{ |p| find_or_create_by_action_and_object *p }
51
+ end
52
+ end
53
+
54
+ # The permission title
55
+ def title(options = {})
56
+ i18n_description :brief, options
57
+ end
58
+
59
+ # The permission description
60
+ def description(options = {})
61
+ i18n_description :detailed, options
62
+ end
63
+
64
+ private
65
+
46
66
  # An explanation of the permissions. Type can be brief or detailed.
47
67
  # If detailed, description includes more information about the relation
48
- def description(type, options = {})
68
+ def i18n_description(type, options = {})
49
69
  unless options[:subject].present?
50
70
  raise "Now we need subject for permission description"
51
71
  end
@@ -44,8 +44,6 @@ class Relation < ActiveRecord::Base
44
44
  Positive = %w{ custom public follow }
45
45
  Negative = %w{ reject }
46
46
 
47
- belongs_to :actor
48
-
49
47
  has_many :relation_permissions, :dependent => :destroy
50
48
  has_many :permissions, :through => :relation_permissions
51
49
 
@@ -57,10 +55,6 @@ class Relation < ActiveRecord::Base
57
55
 
58
56
  has_many :activity_object_audiences, :dependent => :destroy
59
57
 
60
- scope :actor, lambda { |a|
61
- where(:actor_id => Actor.normalize_id(a))
62
- }
63
-
64
58
  scope :mode, lambda { |st, rt|
65
59
  where(:sender_type => st, :receiver_type => rt)
66
60
  }
@@ -74,8 +68,6 @@ class Relation < ActiveRecord::Base
74
68
  merge(Permission.where(:action => action).where(:object => object))
75
69
  }
76
70
 
77
- before_create :initialize_sender_type
78
-
79
71
  class << self
80
72
  # Get relation from object, if possible
81
73
  #
@@ -173,6 +165,15 @@ class Relation < ActiveRecord::Base
173
165
  def create_activity?
174
166
  true
175
167
  end
168
+
169
+ # Default extra relations that are displayed in {Actor}'s relation list,
170
+ # typically in /relation/customs
171
+ def extra_list subject
172
+ l = SocialStream.list_relations[subject.class.to_s.underscore]
173
+ return [] if l.blank?
174
+
175
+ l.map{ |r| "Relation::#{ r.to_s.classify }".constantize.instance }
176
+ end
176
177
  end
177
178
 
178
179
  # Relation class scoped in the same mode that this relation
@@ -190,12 +191,10 @@ class Relation < ActiveRecord::Base
190
191
  permissions.follow.any?
191
192
  end
192
193
 
193
- private
194
-
195
- # Before create callback
196
- def initialize_sender_type
197
- return if actor.blank?
198
-
199
- self.sender_type = actor.subject_type
194
+ # The permissions that can be assigned to this relation.
195
+ #
196
+ # They are principally used in the privacy form in /relation/customs form
197
+ def available_permissions
198
+ []
200
199
  end
201
200
  end
@@ -5,14 +5,6 @@
5
5
  # Default relations are defined at config/relations.yml
6
6
  #
7
7
  class Relation::Custom < Relation
8
- # Default relations shipped with Social Stream
9
- DEFAULT = {
10
- 'site' => {}
11
- }
12
-
13
- # Default relations are re-defined in this configuration file
14
- CONFIG_FILE = File.join(::Rails.root, 'config', 'relations.yml')
15
-
16
8
  # This is weird. We must call #inspect before has_ancestry for Relation::Custom
17
9
  # to recognize STI
18
10
  inspect
@@ -23,17 +15,20 @@ class Relation::Custom < Relation
23
15
  validates_presence_of :name, :actor_id
24
16
  validates_uniqueness_of :name, :scope => :actor_id
25
17
 
26
- class << self
27
- # Relations configuration
28
- def config
29
- @config ||= build_config
30
- end
18
+ scope :actor, lambda { |a|
19
+ where(:actor_id => Actor.normalize_id(a))
20
+ }
21
+
22
+ before_create :initialize_sender_type
31
23
 
24
+ class << self
32
25
  def defaults_for(actor)
33
- cfg_rels = config[actor.subject_type.underscore]
26
+ subject_type = actor.subject.class.to_s.underscore
27
+ cfg_rels = SocialStream.custom_relations[subject_type] ||
28
+ SocialStream.custom_relations[subject_type.to_sym]
34
29
 
35
30
  if cfg_rels.nil?
36
- raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG_FILE }"
31
+ raise "Undefined relations for subject type #{ subject_type }. Please, add an entry to config/initializers/social_stream.rb"
37
32
  end
38
33
 
39
34
  rels = {}
@@ -67,14 +62,11 @@ class Relation::Custom < Relation
67
62
  def strongest
68
63
  roots
69
64
  end
65
+ end
70
66
 
71
- private
72
-
73
- # Gets the default relations defined in DEFAULT and updates the values
74
- # from the CONFIG_FILE configuration file
75
- def build_config
76
- DEFAULT.merge YAML.load_file(CONFIG_FILE)
77
- end
67
+ # The subject who defined of this relation
68
+ def subject
69
+ actor.subject
78
70
  end
79
71
 
80
72
  # Compare two relations
@@ -109,6 +101,17 @@ class Relation::Custom < Relation
109
101
  def stronger_or_equal
110
102
  path
111
103
  end
112
- end
113
104
 
114
- ActiveSupport.run_load_hooks(:relation_custom, Relation::Custom)
105
+ def available_permissions
106
+ Permission.instances SocialStream.available_permissions[subject.class.to_s.underscore]
107
+ end
108
+
109
+ private
110
+
111
+ # Before create callback
112
+ def initialize_sender_type
113
+ return if actor.blank?
114
+
115
+ self.sender_type = actor.subject_type
116
+ end
117
+ end
@@ -6,7 +6,7 @@
6
6
  <%= f.text_area :text, rows: 1, placeholder: t('post.input') %>
7
7
 
8
8
  <section class="wall_input-actions">
9
- <%= f.submit t('activity.share'), class: "btn" %>
9
+ <%= f.submit t('activity.share'), class: "btn", 'data-loading-text' => t('activity.share_loading') %>
10
10
 
11
11
  <% SocialStream.activity_forms.each do |element| %>
12
12
  <%= render partial: "#{ element.to_s.pluralize }/new_activity",
@@ -1,4 +1,4 @@
1
- <% destroy_params ||= {} %>
1
+ <% destroy_params ||= {} %>
2
2
 
3
3
  <section class="contact" id="<%= dom_id contact %>">
4
4
  <div class="avatar">
@@ -29,7 +29,7 @@
29
29
  <div class="contact-list">
30
30
  <% if current_contact_section?(type) %>
31
31
  <% if @contacts.any? %>
32
- <%= render @contacts %>
32
+ <%= render current_subject_contacts_to(@contacts) %>
33
33
  <% else %>
34
34
  <%= raw t("contact.empty", explore: explore_path) %>
35
35
  <% end %>
@@ -1,15 +1,13 @@
1
1
  <section id="forgot-pass">
2
- <section class="forgot-img">
3
-
4
- </section>
5
2
  <section class="forgot">
6
3
  <header>
7
- <h2>
8
- <%= t('devise.passwords.forgot') %>
9
- </h2>
4
+ <h2>
5
+ <%= t('devise.passwords.forgot') %>
6
+ </h2>
7
+
8
+ <%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
9
+ <%= devise_error_messages! %>
10
10
 
11
- <%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
12
- <%= devise_error_messages! %>
13
11
  <h4>
14
12
  <%= t('devise.passwords.instructions') %>
15
13
  </h4>
@@ -13,21 +13,19 @@
13
13
  <div class="reg-labels">
14
14
  <%= f.label :name %>
15
15
 
16
- <%= f.text_field :name, :class =>"form_tag" %>
16
+ <%= f.text_field :name, :class =>"form_tag", :placeholder => "Homo Sapiens apiens" %>
17
17
 
18
18
  <%= f.label :email %>
19
19
 
20
- <%= f.text_field :email, :class =>"form_tag" %>
20
+ <%= f.text_field :email, :class =>"form_tag", :placeholder => "user@email.soc" %>
21
21
 
22
22
  <%= f.label :password %>
23
23
 
24
- <%= f.password_field :password, :class =>"form_tag", :id => "password" %>
24
+ <%= f.password_field :password, :class =>"form_tag", :id => "password", :placeholder => "********" %>
25
25
 
26
- <div id="user_password_confirmation_label">
27
- <%= f.label :password_confirmation %>
28
- </div>
26
+ <%= f.label :password_confirmation %>
29
27
 
30
- <%= f.password_field :password_confirmation, :class =>"form_tag" %>
28
+ <%= f.password_field :password_confirmation, :class =>"form_tag", :placeholder => "********" %>
31
29
 
32
30
  <%= f.submit t('action.accept').capitalize,:class=>"btn pull-right"%>
33
31
  </div>
@@ -33,15 +33,14 @@
33
33
  </head>
34
34
 
35
35
  <body>
36
- <div class="container-fluid">
37
- <div class="wrapper">
38
- <%= render :partial => "layouts/header" %>
36
+ <div class="wrapper container-fluid">
37
+ <%= render :partial => "layouts/header" %>
39
38
 
40
- <%= flashy %>
39
+ <%= flashy %>
41
40
 
42
- <%= yield %>
43
- </div>
44
- <%= render :partial => "layouts/footer" %>
45
- </div>
41
+ <%= yield %>
42
+ <div class="push"></div>
43
+ </div>
44
+ <%= render :partial => "layouts/footer" %>
46
45
  </body>
47
46
  </html>
@@ -1,18 +1,18 @@
1
- <article class="permissions">
1
+ <section class="permissions">
2
2
  <h4>
3
3
  <%= raw t('permission.of_relation.choose', :name => h(@relation.name)) %>
4
4
  </h4>
5
5
 
6
- <%= form_for @relation, url: polymorphic_path(@relation, section: 'permissions'), remote: true do |f| %>
7
- <%= hidden_field_tag 'relation_custom[permission_ids][]', "" %>
6
+ <% if can? :update, @relation %>
8
7
 
9
- <ul>
10
- <% default_permissions.each do |p| %>
11
- <li>
12
- <%= check_box_tag 'relation_custom[permission_ids][]', p.id, @relation.permission_ids.include?(p.id), id: "checkbox_relation_#{ @relation.id }_permission_#{ p.id }" %>
13
- <%= label_tag "checkbox_relation_#{ @relation.id }_permission_#{ p.id }", p.description(:brief, subject: current_subject), title: p.description(:detailed, subject: current_subject, state: (@relation.permission_ids.include?(p.id) ? 'positive' : 'negative'), relation: @relation.name) %>
14
- </li>
15
- <% end %>
16
- </ul>
8
+ <%= form_for @relation, url: polymorphic_path(@relation, section: 'permissions'), remote: true do |f| %>
9
+ <%= hidden_field_tag 'relation_custom[permission_ids][]', "" %>
10
+
11
+ <%= render partial: 'permissions/list',
12
+ locals: { relation: @relation } %>
13
+ <% end %>
14
+ <% else %>
15
+ <%= render partial: 'permissions/list',
16
+ locals: { relation: @relation } %>
17
17
  <% end %>
18
- </article>
18
+ </section>