talkie 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -0
  3. data/README.md +25 -0
  4. data/app/assets/javascripts/talkie/application.js +6 -0
  5. data/app/assets/javascripts/talkie/talkie.mentions.js +25 -0
  6. data/app/assets/stylesheets/talkie/_form.scss +7 -1
  7. data/app/assets/stylesheets/talkie/_variables.scss +6 -1
  8. data/app/assets/stylesheets/talkie/application.scss +2 -0
  9. data/app/blueprints/mentionees_blueprint.rb +15 -0
  10. data/app/controllers/talkie/comments_controller.rb +3 -1
  11. data/app/controllers/talkie/mentions_controller.rb +24 -0
  12. data/app/mailers/talkie/notifications_mailer.rb +15 -0
  13. data/app/models/concerns/talkie/mentionable.rb +55 -0
  14. data/app/models/talkie/comment.rb +6 -0
  15. data/app/models/talkie/subscription.rb +11 -0
  16. data/app/views/talkie/comments/_comment.html.erb +7 -3
  17. data/app/views/talkie/comments/_form.html.erb +6 -2
  18. data/app/views/talkie/notifications_mailer/mentioned.html.erb +15 -0
  19. data/app/views/talkie/notifications_mailer/mentioned.text.erb +5 -0
  20. data/config/locales/en.yml +8 -0
  21. data/config/locales/es.yml +8 -0
  22. data/config/routes.rb +4 -0
  23. data/lib/generators/talkie/templates/create_talkie_comments.rb +14 -0
  24. data/lib/generators/talkie/templates/talkie.rb +28 -1
  25. data/lib/generators/talkie/views_generator.rb +15 -0
  26. data/lib/talkie/acts_as_talker.rb +7 -0
  27. data/lib/talkie/blueprinter.rb +5 -0
  28. data/lib/talkie/nil_mention_tokens.rb +18 -0
  29. data/lib/talkie/permission.rb +3 -3
  30. data/lib/talkie/subscription_error.rb +6 -0
  31. data/lib/talkie/version.rb +1 -1
  32. data/lib/talkie.rb +28 -0
  33. data/talkie.gemspec +2 -0
  34. data/vendor/assets/javascripts/jquery.elastic.js +151 -0
  35. data/vendor/assets/javascripts/jquery.mentionsinput.js +543 -0
  36. data/vendor/assets/javascripts/underscore.js +1590 -0
  37. data/vendor/assets/stylesheets/jquery.mentionsinput.css +112 -0
  38. metadata +46 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82f6715118d4b0022047d97dc002dba51f831e09da19bc374cc0d75ddc2a62aa
4
- data.tar.gz: df4af0404f088395e42c5c92c5dfdd55624292dc0759dbb421d18a941a775e1b
3
+ metadata.gz: 6d5b6edfa12387d4b10f492f9a518f3e4fcbf21b684429a62580c2b2fea20dfb
4
+ data.tar.gz: efef1cb019c0c484c01f00eeea7a845726345b5d70b350f8f0813e5e5a2d42b4
5
5
  SHA512:
6
- metadata.gz: 3dea24f754eb1f95328120601f284ef6530f798c1de001ff233963b8bff83becad84d98cf064741df7df74c3541887c11c7d3855f535785b6538b8be11a100cf
7
- data.tar.gz: f52e51279684b0fa5266ed13d30d5a5ca29d4ff247f76b32012ffacb41549c0a3598d0de4ca2b6707b75538c08d3d76fecede184aa0afcba34755c1d56ebae47
6
+ metadata.gz: 8ededccc1c6b9e9e085d1afb9e8593e052e3afa10dacbab0318a6cf3e2f39cb5cc85d60740aec15f177ce3b99f0abebbdf06e3e25367aeb22ee1c24024816c08
7
+ data.tar.gz: f09bbbf6c55d1cb25b340094961bfa304de3bf91bc49bf782a508541e656586c65d7fce4d0358b55971976986fc06e60542a61f9165b8a57d6bde361144ebf55
data/Gemfile.lock CHANGED
@@ -3,6 +3,8 @@ PATH
3
3
  specs:
4
4
  talkie (0.2.0)
5
5
  awesome_nested_set (~> 3.1)
6
+ blueprinter
7
+ oj
6
8
  rails (~> 5.0)
7
9
  sassc-rails (~> 2.1)
8
10
 
@@ -57,6 +59,7 @@ GEM
57
59
  arel (9.0.0)
58
60
  awesome_nested_set (3.1.4)
59
61
  activerecord (>= 4.0.0, < 5.3)
62
+ blueprinter (0.18.0)
60
63
  builder (3.2.3)
61
64
  coderay (1.1.2)
62
65
  concurrent-ruby (1.1.5)
@@ -90,6 +93,7 @@ GEM
90
93
  nio4r (2.3.1)
91
94
  nokogiri (1.10.3)
92
95
  mini_portile2 (~> 2.4.0)
96
+ oj (3.7.12)
93
97
  pry (0.12.2)
94
98
  coderay (~> 1.1.0)
95
99
  method_source (~> 0.9.0)
data/README.md CHANGED
@@ -11,6 +11,7 @@ Talkie is highly customizable comments engine to easily integrate threads to any
11
11
  - [Usage](#usage)
12
12
  - [Customization](#customization)
13
13
  - [Styles](#styles)
14
+ - [Enabling mentions](#enabling-mentions)
14
15
  - [Development](#development)
15
16
  - [Contributing](#contributing)
16
17
  - [License](#license)
@@ -104,6 +105,30 @@ Talkie is all about customization, so almost every default style provided by the
104
105
  @import "talkie/application";
105
106
  ```
106
107
 
108
+ #### Enabling mentions
109
+
110
+ Talkie comes with a handy feature that you can toggle in order to
111
+ enable/disable user mentions.
112
+
113
+ To enable it, just go to you `talkie.rb` initializer file and uncomment
114
+ or add:
115
+
116
+ ```ruby
117
+ config.enable_mentions = true
118
+ ```
119
+
120
+ For customization, check the
121
+ [template](lib/generators/talkie/templates/talkie.rb), you can basically
122
+ override anything to fulfill your needs.
123
+
124
+ When enabling this module, you need to setup your mailer configuration,
125
+ as with each mentions the commenter subscribes to the comment and
126
+ receives an email, just be aware of that.
127
+
128
+ If you have a hard time understanding this, you can check the [dummy
129
+ application](spec/dummy) I use for testing or contact
130
+ [me](https://twitter.com/kurenn)
131
+
107
132
  ## Development
108
133
 
109
134
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake` to run the tests.
@@ -1,5 +1,11 @@
1
+ //= require underscore
2
+ //= require jquery.elastic
3
+ //= require jquery.mentionsinput
4
+ //= require talkie/talkie.mentions
5
+
1
6
  $("body").on("click", ".talkie-comment-reply-link", function(e){
2
7
  e.preventDefault();
3
8
 
4
9
  $(this).parent().parent().find("> .talkie-comments-reply-form-container").toggle();
5
10
  });
11
+
@@ -0,0 +1,25 @@
1
+ $( document ).on('ready turbolinks:load', function() {
2
+ $('textarea.talkie-comment-body-textarea').mentionsInput({
3
+ showAvatars: false,
4
+ allowRepeat: true,
5
+ minChars: 2,
6
+ onDataRequest: function (mode, query, callback) {
7
+ $.getJSON('/talkie/mentions',
8
+ { q: query },
9
+ function(responseData) {
10
+ callback.call(this, responseData);
11
+ });
12
+ }
13
+ });
14
+
15
+ $("form.talkie-comments-form").on("submit", function(event) {
16
+ event.stopPropagation();
17
+
18
+ $commentsForm = $(this);
19
+
20
+ $commentsForm.find('textarea.talkie-comment-body-textarea').mentionsInput('getMentions', function(data) {
21
+ $commentsForm.find(".comment-mentions").val(JSON.stringify(data));
22
+ });
23
+
24
+ })
25
+ })
@@ -1,4 +1,11 @@
1
1
  .talkie {
2
+ &-hint {
3
+ color: $talkie-hint-color;
4
+ font-size: $talkie-hint-font-size;
5
+ font-style: $talkie-hint-font-style;
6
+ margin: $talkie-hint-margin;
7
+ }
8
+
2
9
  &-comments-form-container,
3
10
  &-comments-reply-form-container {
4
11
  border-bottom: $talkie-form-border-bottom;
@@ -15,7 +22,6 @@
15
22
  font-size: $talkie-form-textarea-font-size;
16
23
  height: $talkie-form-textarea-height;
17
24
  line-height: $talkie-form-textarea-line-height;
18
- margin-bottom: 10px;
19
25
  padding: 10px;
20
26
  vertical-align: top;
21
27
  width: 100%;
@@ -1,5 +1,10 @@
1
1
  // Form variable styles
2
2
 
3
+ $talkie-hint-color: #666 !default;
4
+ $talkie-hint-font-size: 14px !default;
5
+ $talkie-hint-font-style: italic !default;
6
+ $talkie-hint-margin: 0 0 10px 0 !default;
7
+
3
8
  $talkie-form-border-bottom: 1px solid #EEE !default;
4
9
  $talkie-form-padding-bottom: 10px !default;
5
10
  $talkie-form-margin-bottom: 10px !default;
@@ -17,7 +22,7 @@ $talkie-form-submit-border: 1px solid #3079ED !default;
17
22
  $talkie-form-submit-color: #FFF !default;
18
23
  $talkie-form-submit-border-radius: 2px !default;
19
24
  $talkie-form-submit-font-weight: bold !default;
20
- $talkie-form-submit-margin: 0 8px 6px 0!default;
25
+ $talkie-form-submit-margin: 10px 8px 6px 0 !default;
21
26
  $talkie-form-submit-font-size: 11px !default;
22
27
  $talkie-form-submit-padding: 10px 12px !default;
23
28
  $talkie-form-submit-text-shadow: 0 1px rgba(0,0,0,.1) !default;
@@ -1,3 +1,5 @@
1
1
  @import "variables";
2
2
  @import "form";
3
3
  @import "comment";
4
+ @import "jquery.mentionsinput";
5
+
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MentioneesBlueprint < Blueprinter::Base
4
+ identifier :id
5
+
6
+ fields :email
7
+
8
+ field :type do |mentionee, _|
9
+ "#{mentionee.class.to_s}"
10
+ end
11
+
12
+ field :name do |mentionee, _|
13
+ "#{Talkie.autocomplete_mention_display.call(mentionee)}"
14
+ end
15
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Talkie
2
4
  class CommentsController < TalkieController
3
5
  before_action :current_comment, only: [:destroy]
@@ -28,7 +30,7 @@ module Talkie
28
30
  private
29
31
 
30
32
  def comment_params
31
- params.require(:comment).permit(:body, :commentable_id, :commentable_type)
33
+ params.require(:comment).permit(:body, :commentable_id, :commentable_type, :mention_tokens)
32
34
  end
33
35
 
34
36
  def reply?
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Talkie
4
+ class MentionsController < TalkieController
5
+ def index
6
+ if query.size < 2
7
+ render json: { error: 'Query string is too short (minimum 2 characters)' },
8
+ status: :unprocessable_entity
9
+ else
10
+ render json: MentioneesBlueprint.render(mentionees)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def query
17
+ @query ||= params[:q].to_s
18
+ end
19
+
20
+ def mentionees
21
+ @mentionees ||= current_user.class.mentionees(query)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Talkie
4
+ class NotificationsMailer < ActionMailer::Base
5
+ default from: Talkie.from_mailer_address
6
+
7
+ def mentioned
8
+ @comment = params[:comment]
9
+ @creator = @comment.creator
10
+ recipients = params[:recipients]
11
+ mail to: recipients,
12
+ subject: t("talkie.mailers.notifications.subject", creator: @creator.email)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Talkie
4
+ module Mentionable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attr_writer :mention_tokens
9
+
10
+ before_create :check_for_mentions!, if: :mentions?
11
+ after_create :notify_mentionees!, if: :enabled_notifications?
12
+ end
13
+
14
+ def check_for_mentions!
15
+ subscribers.each do |subscriber|
16
+ self.subscriptions.build(subscriber: subscriber)
17
+ end
18
+ end
19
+
20
+ def mentions?
21
+ mention_tokens.present?
22
+ end
23
+
24
+ def notify_mentionees!
25
+ NotificationsMailer.with(comment: self, recipients: subscribers.pluck(:email)).mentioned.deliver_now
26
+ end
27
+
28
+ def mention_tokens
29
+ @mention_tokens || Talkie::NilMentionTokens.new.to_s
30
+ end
31
+
32
+ private
33
+
34
+ def subscribers
35
+ @subscribers ||= mentionee_klass.find(subscriber_ids)
36
+ end
37
+
38
+ def subscriber_ids
39
+ @subscriber_ids ||= mentions.map { |mention| mention["id"] }
40
+ end
41
+
42
+ def mentionee_klass
43
+ @mentionee_klass ||= mentions.first["type"]&.constantize
44
+ end
45
+
46
+ def mentions
47
+ @mentions ||= JSON.parse(mention_tokens)
48
+ end
49
+
50
+ def enabled_notifications?
51
+ Talkie.notifications_mentions_enabled?
52
+ end
53
+
54
+ end
55
+ end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Talkie
2
4
  class Comment < ActiveRecord::Base
5
+ include Talkie::Mentionable if Talkie.mentions_enabled?
6
+
3
7
  default_scope Talkie.default_comments_scope
4
8
 
5
9
  acts_as_nested_set :scope => [:commentable_id, :commentable_type],
@@ -8,6 +12,8 @@ module Talkie
8
12
  belongs_to :creator, polymorphic: true, inverse_of: :comments
9
13
  belongs_to :commentable, polymorphic: true, inverse_of: :comments
10
14
 
15
+ has_many :subscriptions, dependent: :destroy, inverse_of: :comment
16
+
11
17
  validates :body, :creator, :commentable, presence: true
12
18
  end
13
19
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Talkie
4
+ class Subscription < ActiveRecord::Base
5
+ belongs_to :subscriber, polymorphic: true, inverse_of: :subscriptions
6
+ belongs_to :comment, inverse_of: :subscriptions, class_name: "Talkie::Comment"
7
+
8
+ validates_presence_of :subscriber, :comment
9
+ validates_uniqueness_of :comment, scope: [:subscriber_type, :subscriber_id]
10
+ end
11
+ end
@@ -1,4 +1,4 @@
1
- <div class="talkie-comment-holder">
1
+ <div class="talkie-comment-holder" id="talkie-comment-<%= comment.id %>">
2
2
  <% if display_user_avatar? %>
3
3
  <div class="talkie-comment-creator-avatar">
4
4
  <%= avatar_image_tag comment.creator %>
@@ -32,12 +32,16 @@
32
32
  <% end %>
33
33
  </div>
34
34
  <div class="talkie-comments-reply-form-container" style="display:none">
35
- <%= form_for [talkie, Talkie::Comment.new] do |f| %>
35
+ <%= form_for [talkie, Talkie::Comment.new], html: { class: "talkie-comments-form" } do |f| %>
36
36
  <%= f.hidden_field :commentable_id, value: commentable.id %>
37
37
  <%= f.hidden_field :commentable_type, value: commentable.class.name %>
38
38
  <%= hidden_field_tag :parent_comment_id, comment.id %>
39
39
 
40
- <%= f.text_area :body, placeholder: t("talkie.comment.form.body_placeholder") %>
40
+ <%= f.text_area :body, placeholder: t("talkie.comment.form.body_placeholder"), class: "talkie-comment-body-textarea", required: "required" %>
41
+ <% if Talkie.mentions_enabled? %>
42
+ <p class="talkie-hint"><%= t("talkie.comments.form.hint_html") %></p>
43
+ <%= f.hidden_field :mention_tokens, class: "comment-mentions" %>
44
+ <% end %>
41
45
  <%= submit_tag t("talkie.comment.form.reply"), class: 'talkie-comments-form-submit' %>
42
46
  <% end %>
43
47
  </div>
@@ -1,9 +1,13 @@
1
1
  <div class="talkie-comments-form-container">
2
- <%= form_for [talkie, Talkie::Comment.new] do |f| %>
2
+ <%= form_for [talkie, Talkie::Comment.new], html: { class: "talkie-comments-form" } do |f| %>
3
3
  <%= f.hidden_field :commentable_id, value: commentable.id %>
4
4
  <%= f.hidden_field :commentable_type, value: commentable.class.name %>
5
5
 
6
- <%= f.text_area :body, placeholder: t("talkie.comments.form.body_placeholder") %>
6
+ <%= f.text_area :body, placeholder: t("talkie.comments.form.body_placeholder"), class: "talkie-comment-body-textarea", required: "required" %>
7
+ <% if Talkie.mentions_enabled? %>
8
+ <p class="talkie-hint"><%= t("talkie.comments.form.hint_html") %></p>
9
+ <%= f.hidden_field :mention_tokens, class: "comment-mentions" %>
10
+ <% end %>
7
11
  <%= f.submit t("talkie.comments.form.submit"), class: "talkie-comments-form-submit" %>
8
12
  <% end %>
9
13
  </div>
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
5
+ </head>
6
+ <body>
7
+ <h4><%= t("talkie.mailers.notifications.headline") %></h4>
8
+ <p>
9
+ <%= t("talkie.mailers.notifications.reason", creator: @creator.email) %>
10
+ </p>
11
+ <p>
12
+ <%= t "talkie.mailers.notifications.to_view_conversation_html", link_to: (link_to t("talkie.mailers.notifications.here"), main_app.polymorphic_url(@comment.commentable, anchor: "talkie-comment-#{@comment.id}")) %>
13
+ </p>
14
+ </body>
15
+ </html>
@@ -0,0 +1,5 @@
1
+ <%= t("talkie.mailers.notifications.headline") %>
2
+
3
+ <%= t("talkie.mailers.notifications.reason", creator: @creator.email) %>
4
+
5
+ <%= t "talkie.mailers.notifications.to_view_conversation_html", link_to: (link_to t("talkie.mailers.notifications.here"), main_app.polymorphic_url(@comment.commentable, anchor: "talkie-comment-#{@comment.id}")) %>
@@ -1,6 +1,13 @@
1
1
  ---
2
2
  en:
3
3
  talkie:
4
+ mailers:
5
+ notifications:
6
+ subject: "You have been mentioned by %{creator}"
7
+ headline: "This is an automatic notification system"
8
+ reason: "You are receiving this notification because %{creator} mentioned you on a conversation."
9
+ to_view_conversation_html: "To view the conversation on the site, just click %{link_to}"
10
+ here: "here"
4
11
  controllers:
5
12
  comments:
6
13
  flash:
@@ -8,6 +15,7 @@ en:
8
15
  error: "Something went wrong, blank comments are not allowed."
9
16
  comments:
10
17
  form:
18
+ hint_html: "<strong>Hint: </strong> To autocomplete the users, you can add an '@' to activate the autocomplete"
11
19
  submit: "Publish"
12
20
  body_placeholder: "Write your comment..."
13
21
  count:
@@ -1,6 +1,13 @@
1
1
  ---
2
2
  es:
3
3
  talkie:
4
+ mailers:
5
+ notifications:
6
+ subject: "%{creator} te ha mencionado en una conversación"
7
+ headline: "Esto es un sistema automático de notificación"
8
+ reason: "Estas recibiendo este correo por que %{creator} te menciono en una conversación."
9
+ to_view_conversation_html: "Para responder da clic %{link_to}"
10
+ here: "aquí"
4
11
  controllers:
5
12
  comments:
6
13
  flash:
@@ -8,6 +15,7 @@ es:
8
15
  error: "Algo salió mal, tu comentario no puede estar en blanco."
9
16
  comments:
10
17
  form:
18
+ hint_html: "<strong>Ayuda: </strong> Para autocompletar a los usuarios, puedes agregar un '@' antes de su nombre"
11
19
  submit: "Publicar"
12
20
  body_placeholder: "Escribe tu comentario..."
13
21
  count:
data/config/routes.rb CHANGED
@@ -1,3 +1,7 @@
1
1
  Talkie::Engine.routes.draw do
2
2
  resources :comments, only: [:create, :destroy]
3
+
4
+ if Talkie.mentions_enabled?
5
+ resources :mentions, only: [:index]
6
+ end
3
7
  end
@@ -18,6 +18,20 @@ class CreateTalkieComments < ActiveRecord::Migration[5.0]
18
18
  add_index :talkie_comments, :commentable_type
19
19
  add_index :talkie_comments, [:creator_id, :creator_type],
20
20
  name: 'index_talkie_comments_on_creator_id_and_creator_type'
21
+
22
+ create_table :talkie_subscriptions do |t|
23
+ t.string :subscriber_type, null: false
24
+ t.integer :subscriber_id, null: false
25
+ t.integer :comment_id, null: false
26
+
27
+ t.timestamps null: false
28
+ end
29
+
30
+ add_index :talkie_subscriptions, [:subscriber_id, :subscriber_type, :comment_id],
31
+ unique: true,
32
+ name: 'index_talkie_subscriptions_on_s_id_and_s_type_and_c_id'
33
+
34
+ add_index :talkie_subscriptions, :comment_id
21
35
  end
22
36
 
23
37
  def self.down
@@ -29,7 +29,6 @@ Talkie.configure do |config|
29
29
  # The default looks like:
30
30
  # config.creator_path = lambda { |user, router| "#" }
31
31
 
32
-
33
32
  # ==> Creator avatar url
34
33
  # Configure the avatar url for the comment creator
35
34
  # By default it will use a http:////api.adorable.io/avatars/40/abott@adorable.png
@@ -43,7 +42,35 @@ Talkie.configure do |config|
43
42
  #
44
43
  # The default looks like:
45
44
  # config.creator_avatar_url = lambda { |user| "//api.adorable.io/avatars/40/abott@adorable.png" }
45
+
46
+ # ==> Mentions support
47
+ # If you decide to enable mentions, be aware on some further configuration
48
+ # The first thing to do is to just enable it:
49
+ #
50
+ # config.enable_mentions = true
51
+ #
52
+ # By default it will send an email to notify the mentioned users
53
+ # but you can override this default configuration like:
54
+ #
55
+ # config.enable_mentions_notifications = false
56
+ #
57
+ # You can override the query that filter the mentionees
58
+ # By default the lambda function is
59
+ # config.mentions_scope_query = lambda { |query| where("email LIKE ?", "#{query}%") }
60
+ # Just keep in mind that the query variable is what you receive when the user
61
+ # types '@' on the textarea, so maybe kurenn@icalialabs.com or so
62
+ # You can change to obey a username column, like so:
63
+ #
64
+ # config.mentions_scope_query = lambda { |query| where("username ILIKE ?", "%#{query}%") }
65
+ #
66
+ # There is another configuration for the mention module you may want to look at it
67
+ # The autocomplete text, which is by default the email, but probably that would look nasty,
68
+ # you can override this and use any method or attribute you want for your talker class:
69
+ #
70
+ # config.autocomplete_mention_display = lambda { |mentionee| mentionee.username }
46
71
  #
72
+ # Or maybe something more complex
73
+ # config.autocomplete_mention_display = lambda { |mentionee| "#{mentionee.first_name} #{mentionee.last_name}" }
47
74
 
48
75
  # ==> Redirect for comments controller
49
76
  # There are sometimes you want to redirect to different locations
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+
5
+ module Talkie
6
+ module Generators
7
+ class ViewsGenerator < Rails::Generators::Base
8
+ source_root File.expand_path('../../../../app/views/talkie', __FILE__)
9
+
10
+ def copy_views
11
+ directory "notifications_mailer", "app/views/talkie/notifications_mailer"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -13,6 +13,13 @@ module Talkie
13
13
  class_name: 'Talkie::Comment',
14
14
  inverse_of: :creator
15
15
 
16
+ has_many :subscriptions, as: :subscriber,
17
+ class_name: 'Talkie::Subscription',
18
+ dependent: :destroy,
19
+ inverse_of: :subscriber
20
+
21
+ scope :mentionees, Talkie.mentions_scope_query if Talkie.mentions_enabled?
22
+
16
23
  def owns_comment?(comment)
17
24
  self == comment.creator
18
25
  end
@@ -0,0 +1,5 @@
1
+ require 'oj'
2
+
3
+ Blueprinter.configure do |config|
4
+ config.generator = Oj # default is JSON
5
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Talkie
4
+ class NilMentionTokens
5
+
6
+ def self.find(ids = [])
7
+ []
8
+ end
9
+
10
+ def to_s
11
+ %Q{#{[
12
+ {
13
+ type: self.class.to_s
14
+ }
15
+ ].to_json}}
16
+ end
17
+ end
18
+ end
@@ -2,12 +2,12 @@
2
2
 
3
3
  module Talkie
4
4
  class Permission < Struct.new(:user)
5
- def allow?(action, comment)
5
+ def allow?(action, comment = Talkie::Comment.new)
6
6
  action = action.to_s
7
7
 
8
8
  if user
9
- return true if action.in? %w[create]
10
- return true if user.owns_comment?(comment) && action.in?(%w[destroy])
9
+ return true if action.in? %w[create index]
10
+ return true if action.in?(%w[destroy]) && user.owns_comment?(comment)
11
11
  end
12
12
 
13
13
  false
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Talkie
4
+ class SubscriptionError < StandardError
5
+ end
6
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Talkie
4
- VERSION = '0.2.0'.freeze
4
+ VERSION = '0.3.0'.freeze
5
5
  end
data/lib/talkie.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "talkie/version"
4
4
  require "talkie/engine"
5
5
  require "awesome_nested_set"
6
+ require "blueprinter"
6
7
 
7
8
  module Talkie
8
9
 
@@ -24,6 +25,30 @@ module Talkie
24
25
  mattr_accessor :fail_redirect_to,
25
26
  default: lambda { |router| router.root_url }
26
27
 
28
+ mattr_accessor :enable_mentions,
29
+ default: false
30
+
31
+ mattr_accessor :mentions_scope_query,
32
+ default: lambda { |query| where("email LIKE ?", "#{query}%") }
33
+
34
+
35
+ mattr_accessor :enable_mentions_notifications,
36
+ default: true
37
+
38
+ mattr_accessor :from_mailer_address,
39
+ default: "no-reply@change-me-to-your-domain.com"
40
+
41
+ mattr_accessor :autocomplete_mention_display,
42
+ default: lambda { |mentionee| mentionee.email }
43
+
44
+ def self.mentions_enabled?
45
+ @@enable_mentions
46
+ end
47
+
48
+ def self.notifications_mentions_enabled?
49
+ @@enable_mentions_notifications
50
+ end
51
+
27
52
  def self.configure
28
53
  yield self
29
54
  end
@@ -34,3 +59,6 @@ require "talkie/acts_as_commentable"
34
59
  require "talkie/permission"
35
60
  require "talkie/controller"
36
61
  require "talkie/renderer_helper"
62
+ require "talkie/subscription_error"
63
+ require "talkie/blueprinter"
64
+ require "talkie/nil_mention_tokens"
data/talkie.gemspec CHANGED
@@ -38,4 +38,6 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency "rails", "~> 5.0"
39
39
  spec.add_dependency "sassc-rails", "~> 2.1"
40
40
  spec.add_dependency "awesome_nested_set", "~> 3.1"
41
+ spec.add_dependency "blueprinter", "~> 0.18.0"
42
+ spec.add_dependency "oj", "~> 3.17"
41
43
  end