effective_messaging 0.1.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +131 -0
- data/Rakefile +18 -0
- data/app/assets/config/effective_messaging_manifest.js +3 -0
- data/app/assets/javascripts/effective_messaging/base.js +0 -0
- data/app/assets/javascripts/effective_messaging.js +1 -0
- data/app/assets/stylesheets/effective_messaging/base.scss +0 -0
- data/app/assets/stylesheets/effective_messaging.scss +1 -0
- data/app/controllers/admin/chat_messages_controller.rb +13 -0
- data/app/controllers/admin/chats_controller.rb +13 -0
- data/app/controllers/effective/chats_controller.rb +16 -0
- data/app/datatables/admin/effective_chat_messages_datatable.rb +30 -0
- data/app/datatables/admin/effective_chats_datatable.rb +51 -0
- data/app/datatables/effective_chats_datatable.rb +21 -0
- data/app/helpers/effective_messaging_helper.rb +3 -0
- data/app/mailers/effective/messaging_mailer.rb +59 -0
- data/app/models/concerns/effective_messaging_user.rb +47 -0
- data/app/models/effective/chat.rb +133 -0
- data/app/models/effective/chat_message.rb +42 -0
- data/app/models/effective/chat_user.rb +48 -0
- data/app/views/admin/chat_messages/_chat_message.html.haml +1 -0
- data/app/views/admin/chats/_chat.html.haml +1 -0
- data/app/views/admin/chats/_form.html.haml +8 -0
- data/app/views/admin/chats/_form_chat.html.haml +17 -0
- data/app/views/admin/chats/_layout.html.haml +2 -0
- data/app/views/effective/chats/_chat.html.haml +10 -0
- data/app/views/effective/chats/_chat_message.html.haml +10 -0
- data/app/views/effective/chats/_form.html.haml +27 -0
- data/app/views/effective/chats/_layout.html.haml +2 -0
- data/app/views/effective/chats/_summary.html.haml +13 -0
- data/app/views/effective/messaging/_dashboard.html.haml +10 -0
- data/app/views/effective/messaging_mailer/chat_new_message.liquid +11 -0
- data/config/effective_messaging.rb +27 -0
- data/config/routes.rb +18 -0
- data/db/migrate/01_create_effective_messaging.rb.erb +44 -0
- data/db/seeds.rb +1 -0
- data/lib/effective_messaging/engine.rb +18 -0
- data/lib/effective_messaging/version.rb +3 -0
- data/lib/effective_messaging.rb +22 -0
- data/lib/generators/effective_messaging/install_generator.rb +32 -0
- data/lib/generators/templates/effective_messaging_mailer_preview.rb +4 -0
- data/lib/tasks/effective_messaging_tasks.rake +8 -0
- metadata +281 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6193093b822303bfc098d13ddaa7fe17787571ba0f65a5531ac0978272381320
|
4
|
+
data.tar.gz: b305d1836ab2a6f37b1236a986f36753d9194b969cc1105431733720a4d68535
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b9b841f95b963670a6471bc6f28ae379ca99e43c7ee686f6d368c9853e4db1aaa2cd50dd7c1fdf15f20fefdb5f43a2d062e103074fbe01a9a9335b88bb465b20
|
7
|
+
data.tar.gz: e9e6c2cd7a336d3bf1fb547bceca70c49a2089728e4927b806ae77d78c9ec04836b8217b6a854be56f8e8af3cc96a01d2ee44a1973c104bef5642a8e5a2030cd
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2023 Code and Effect Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
# Effective Messaging
|
2
|
+
|
3
|
+
Centralize all communications between one or more users.
|
4
|
+
|
5
|
+
## Getting Started
|
6
|
+
|
7
|
+
This requires Rails 6+ and Twitter Bootstrap 4 and just works with Devise.
|
8
|
+
|
9
|
+
Please first install the [effective_datatables](https://github.com/code-and-effect/effective_datatables) gem.
|
10
|
+
|
11
|
+
Please download and install the [Twitter Bootstrap4](http://getbootstrap.com)
|
12
|
+
|
13
|
+
Add to your Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'effective_messaging'
|
17
|
+
```
|
18
|
+
|
19
|
+
Run the bundle command to install it:
|
20
|
+
|
21
|
+
```console
|
22
|
+
bundle install
|
23
|
+
```
|
24
|
+
|
25
|
+
Then run the generator:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
rails generate effective_messaging:install
|
29
|
+
```
|
30
|
+
|
31
|
+
The generator will install an initializer which describes all configuration options and creates a database migration.
|
32
|
+
|
33
|
+
If you want to tweak the table names, manually adjust both the configuration file and the migration now.
|
34
|
+
|
35
|
+
Then migrate the database:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
rake db:migrate
|
39
|
+
```
|
40
|
+
|
41
|
+
Please add the following to your User model:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
effective_messaging_user # effective_messaging_user
|
45
|
+
|
46
|
+
# Effective messaging
|
47
|
+
def effective_messaging_display_name
|
48
|
+
to_s
|
49
|
+
end
|
50
|
+
|
51
|
+
# An anonymous token for your users
|
52
|
+
def effective_messaging_anonymous_name
|
53
|
+
'Anonymous' + Base64::encode64("#{id}-#{created_at.strftime('%F')}").chomp.first(8)
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
Add dashboard:
|
58
|
+
|
59
|
+
```haml
|
60
|
+
.card.card-dashboard.mb-4
|
61
|
+
.card-body= render 'effective/messaging/dashboard'
|
62
|
+
```
|
63
|
+
|
64
|
+
Add a link to the admin menu:
|
65
|
+
|
66
|
+
```haml
|
67
|
+
- if can?(:admin, :effective_messaging) && can?(:index, Effective::Chat)
|
68
|
+
= nav_link_to 'Chats', effective_messaging.admin_chats_path
|
69
|
+
|
70
|
+
- if can?(:admin, :effective_messaging) && can?(:index, Effective::ChatMessage)
|
71
|
+
= nav_link_to 'Chat Messages', effective_messaging.admin_chat_messages_path
|
72
|
+
```
|
73
|
+
|
74
|
+
## Authorization
|
75
|
+
|
76
|
+
All authorization checks are handled via the effective_resources gem found in the `config/initializers/effective_resources.rb` file.
|
77
|
+
|
78
|
+
## Permissions
|
79
|
+
|
80
|
+
The permissions you actually want to define are as follows (using CanCan):
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
can(:index, Effective::Chat)
|
84
|
+
can([:show, :update], Effective::Chat) { |chat| user.chat_user(chat: chat).present? }
|
85
|
+
|
86
|
+
if user.admin?
|
87
|
+
can :admin, :effective_messaging
|
88
|
+
|
89
|
+
can(crud, Effective::Chat)
|
90
|
+
can(crud, Effective::ChatUser)
|
91
|
+
can(crud - [:new, :create], Effective::ChatMessage)
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
## Creating a chat
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
users = User.where(id: [1,2,3])
|
99
|
+
|
100
|
+
chat = Effective::Chat.new(title: 'A cool chat', anonymous: true, users: users)
|
101
|
+
chat.save!
|
102
|
+
```
|
103
|
+
|
104
|
+
and you can just render it *outside of a form*:
|
105
|
+
|
106
|
+
```haml
|
107
|
+
- chat = Effective::Chat.first
|
108
|
+
= render(chat)
|
109
|
+
= render('effective/chats/chat', chat: chat)
|
110
|
+
```
|
111
|
+
|
112
|
+
## License
|
113
|
+
|
114
|
+
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
115
|
+
|
116
|
+
## Testing
|
117
|
+
|
118
|
+
Run tests by:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
rails test
|
122
|
+
```
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
1. Fork it
|
127
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
128
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
129
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
130
|
+
5. Bonus points for test coverage
|
131
|
+
6. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
4
|
+
load "rails/tasks/engine.rake"
|
5
|
+
|
6
|
+
load "rails/tasks/statistics.rake"
|
7
|
+
|
8
|
+
require "bundler/gem_tasks"
|
9
|
+
|
10
|
+
require "rake/testtask"
|
11
|
+
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = false
|
16
|
+
end
|
17
|
+
|
18
|
+
task default: :test
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree ./effective_messaging
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
@import 'effective_messaging/base';
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Admin
|
2
|
+
class ChatMessagesController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_messaging) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
def permitted_params
|
9
|
+
params.require(:effective_chat_message).permit!
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Admin
|
2
|
+
class ChatsController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_messaging) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
def permitted_params
|
9
|
+
params.require(:effective_chat).permit!
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Effective
|
2
|
+
class ChatsController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
|
5
|
+
include Effective::CrudController
|
6
|
+
|
7
|
+
resource_scope -> { Effective::Chat.all.deep }
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def permitted_params
|
12
|
+
params.require(:effective_chat).except(:user_type).permit(chat_messages_attributes: [:body])
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveChatMessagesDatatable < Effective::Datatable
|
3
|
+
|
4
|
+
datatable do
|
5
|
+
col :id, visible: false
|
6
|
+
col :token, visible: false
|
7
|
+
|
8
|
+
col :created_at, label: 'Date'
|
9
|
+
col :chat, search: :string
|
10
|
+
|
11
|
+
col :name
|
12
|
+
col :body, label: 'Message'
|
13
|
+
|
14
|
+
actions_col
|
15
|
+
end
|
16
|
+
|
17
|
+
collection do
|
18
|
+
scope = Effective::ChatMessage.deep.all
|
19
|
+
|
20
|
+
if attributes[:user_id].present? && attributes[:user_type].present?
|
21
|
+
user = attributes[:user_type].constantize.find(attributes[:user_id])
|
22
|
+
scope = Effective::ChatMessage.where(user: user)
|
23
|
+
end
|
24
|
+
|
25
|
+
scope
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Admin
|
2
|
+
class EffectiveChatsDatatable < Effective::Datatable
|
3
|
+
|
4
|
+
datatable do
|
5
|
+
col :id, visible: false
|
6
|
+
col :token, visible: false
|
7
|
+
|
8
|
+
col :created_at, visible: false
|
9
|
+
col :updated_at
|
10
|
+
|
11
|
+
col :parent, visible: false
|
12
|
+
col :title
|
13
|
+
col :anonymous
|
14
|
+
|
15
|
+
col :chat_users
|
16
|
+
|
17
|
+
col(:chat_users, search: :string) do |chat|
|
18
|
+
if chat.anonymous?
|
19
|
+
chat.chat_users.map do |chat_user|
|
20
|
+
content_tag(:div, chat_user.name, class_name: 'col-resource_item')
|
21
|
+
end
|
22
|
+
else
|
23
|
+
chat.chat_users.map do |chat_user|
|
24
|
+
link = link_to(chat_user.name, "/admin/users/#{chat_user.user_id}/edit")
|
25
|
+
content_tag(:div, link, class_name: 'col-resource_item')
|
26
|
+
end
|
27
|
+
end.join
|
28
|
+
end.search do |collection, term|
|
29
|
+
Effective::Chat.search_by_chat_user_name(term)
|
30
|
+
end
|
31
|
+
|
32
|
+
col :chat_messages_count, label: 'Num Messages'
|
33
|
+
|
34
|
+
col :last_notified_at, visible: false
|
35
|
+
|
36
|
+
actions_col(new: false)
|
37
|
+
end
|
38
|
+
|
39
|
+
collection do
|
40
|
+
scope = Effective::Chat.deep.all
|
41
|
+
|
42
|
+
if attributes[:user_id].present? && attributes[:user_type].present?
|
43
|
+
user = attributes[:user_type].constantize.find(attributes[:user_id])
|
44
|
+
scope = Effective::Chat.for_user(user)
|
45
|
+
end
|
46
|
+
|
47
|
+
scope
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Dashboard Chats
|
2
|
+
class EffectiveChatsDatatable < Effective::Datatable
|
3
|
+
datatable do
|
4
|
+
order :updated_at
|
5
|
+
|
6
|
+
col :token, visible: false
|
7
|
+
col :created_at, visible: false
|
8
|
+
col :updated_at, label: 'Last message'
|
9
|
+
|
10
|
+
col :title
|
11
|
+
col :chat_users, label: 'Participants'
|
12
|
+
col :chat_messages_count, label: 'Messages'
|
13
|
+
|
14
|
+
actions_col
|
15
|
+
end
|
16
|
+
|
17
|
+
collection do
|
18
|
+
Effective::Chat.deep.where(id: current_user.chats)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Effective
|
2
|
+
class MessagingMailer < EffectiveMessaging.parent_mailer_class
|
3
|
+
|
4
|
+
include EffectiveMailer
|
5
|
+
include EffectiveEmailTemplatesMailer if EffectiveMessaging.use_effective_email_templates
|
6
|
+
|
7
|
+
def chat_new_message(chat, chat_user, opts = {})
|
8
|
+
raise('expected a chat') unless chat.kind_of?(Chat)
|
9
|
+
raise('expected a chat user') unless chat_user.kind_of?(ChatUser)
|
10
|
+
|
11
|
+
user = chat_user.user
|
12
|
+
raise('expected user to have an email') unless user.try(:email).present?
|
13
|
+
|
14
|
+
@assigns = assigns_for(chat).merge(assigns_for(chat_user))
|
15
|
+
|
16
|
+
subject = subject_for(__method__, "New Message - #{chat}", chat, opts)
|
17
|
+
headers = headers_for(chat, opts)
|
18
|
+
|
19
|
+
mail(to: user.email, subject: subject, **headers)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def assigns_for(resource)
|
25
|
+
if resource.kind_of?(Effective::Chat)
|
26
|
+
return chat_assigns(resource)
|
27
|
+
end
|
28
|
+
|
29
|
+
if resource.kind_of?(Effective::ChatUser)
|
30
|
+
return chat_user_assigns(resource)
|
31
|
+
end
|
32
|
+
|
33
|
+
raise('unexpected resource')
|
34
|
+
end
|
35
|
+
|
36
|
+
def chat_assigns(chat)
|
37
|
+
raise('expected a chat') unless chat.kind_of?(Chat)
|
38
|
+
|
39
|
+
values = {
|
40
|
+
date: chat.created_at.strftime('%F'),
|
41
|
+
title: chat.title,
|
42
|
+
url: effective_messaging.chat_url(chat)
|
43
|
+
}.compact
|
44
|
+
|
45
|
+
{ chat: values }
|
46
|
+
end
|
47
|
+
|
48
|
+
def chat_user_assigns(chat_user)
|
49
|
+
raise('expected a chat_user') unless chat_user.kind_of?(ChatUser)
|
50
|
+
|
51
|
+
values = {
|
52
|
+
name: chat_user.name
|
53
|
+
}.compact
|
54
|
+
|
55
|
+
{ user: values }
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# EffectiveMessagingUser
|
2
|
+
#
|
3
|
+
# Mark your user model with effective_messaging_user to get all the includes
|
4
|
+
|
5
|
+
module EffectiveMessagingUser
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module Base
|
9
|
+
def effective_messaging_user
|
10
|
+
include ::EffectiveMessagingUser
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def effective_messaging_user?; true; end
|
16
|
+
end
|
17
|
+
|
18
|
+
included do
|
19
|
+
has_many :chat_users, -> { Effective::ChatUser.sorted },
|
20
|
+
class_name: 'Effective::ChatUser', inverse_of: :user, dependent: :nullify
|
21
|
+
|
22
|
+
accepts_nested_attributes_for :chat_users, allow_destroy: true
|
23
|
+
|
24
|
+
has_many :chats, -> { Effective::Chat.sorted }, through: :chat_users, class_name: 'Effective::Chat'
|
25
|
+
accepts_nested_attributes_for :chats, allow_destroy: true
|
26
|
+
end
|
27
|
+
|
28
|
+
# Instance Methods
|
29
|
+
def chat_user(chat:)
|
30
|
+
chat_users.find { |cu| cu.chat_id == chat.id }
|
31
|
+
end
|
32
|
+
|
33
|
+
def effective_messaging_display_name
|
34
|
+
to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def effective_messaging_anonymous_name
|
38
|
+
raise('to be implemented by the app')
|
39
|
+
# Base64::encode64("#{id}-#{created_at.strftime('%F')}").chomp.first(8)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Find or build
|
43
|
+
# def build_chat_user(chat:)
|
44
|
+
# chat_user(chat: chat) || chat_users.build(chat: chat)
|
45
|
+
# end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
class Chat < ActiveRecord::Base
|
5
|
+
self.table_name = EffectiveMessaging.chats_table_name.to_s
|
6
|
+
|
7
|
+
NOTIFY_AFTER = 2.minutes
|
8
|
+
|
9
|
+
attr_accessor :current_user
|
10
|
+
attr_accessor :user_type # Must be set when creating a chat by admin/new form, and passing user_ids
|
11
|
+
|
12
|
+
acts_as_tokened
|
13
|
+
log_changes if respond_to?(:log_changes)
|
14
|
+
|
15
|
+
# If we want to use chats in a has_many way
|
16
|
+
belongs_to :parent, polymorphic: true, optional: true
|
17
|
+
|
18
|
+
has_many :chat_users, -> { ChatUser.sorted }, inverse_of: :chat, dependent: :destroy
|
19
|
+
accepts_nested_attributes_for :chat_users, allow_destroy: true
|
20
|
+
|
21
|
+
has_many :chat_messages, -> { ChatMessage.sorted }, inverse_of: :chat, dependent: :destroy
|
22
|
+
accepts_nested_attributes_for :chat_messages, allow_destroy: true
|
23
|
+
|
24
|
+
effective_resource do
|
25
|
+
title :string
|
26
|
+
anonymous :boolean
|
27
|
+
|
28
|
+
chat_messages_count :integer
|
29
|
+
token :string
|
30
|
+
|
31
|
+
timestamps
|
32
|
+
end
|
33
|
+
|
34
|
+
scope :sorted, -> { order(id: :desc) }
|
35
|
+
scope :deep, -> { includes(:chat_users, :chat_messages) }
|
36
|
+
|
37
|
+
scope :for_user, -> (user) { where(id: ChatUser.where(user: user).select(:chat_id)) }
|
38
|
+
scope :search_by_chat_user_name, -> (name) { where(id: ChatUser.with_name(name).select(:chat_id)) }
|
39
|
+
|
40
|
+
validates :title, presence: true, length: { maximum: 255 }
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
title.presence || 'New Chat'
|
44
|
+
end
|
45
|
+
|
46
|
+
# This is an API for sending a message.
|
47
|
+
def send_message!(user:, body:)
|
48
|
+
raise('expected an effective_messaging_user') unless user.class.respond_to?(:effective_messaging_user?)
|
49
|
+
|
50
|
+
chat_user = chat_user(user: user)
|
51
|
+
raise('expected user to be a chat_user in this chat') unless chat_user.present?
|
52
|
+
|
53
|
+
# Build and send message
|
54
|
+
chat_message = chat_messages.build(body: body, user: user, chat_user: chat_user, name: chat_user.name)
|
55
|
+
|
56
|
+
# Creates message, which also calls notify! below
|
57
|
+
save!
|
58
|
+
|
59
|
+
chat_message
|
60
|
+
end
|
61
|
+
|
62
|
+
# Called by an after_commit on chat message
|
63
|
+
def notify!(except: nil, force: false)
|
64
|
+
raise('expected a ChatUser') if except.present? && !except.kind_of?(ChatUser)
|
65
|
+
|
66
|
+
# Notify everyone in the chat except the user that created this message
|
67
|
+
notified = (chat_users - [except]).map do |chat_user|
|
68
|
+
|
69
|
+
# Only notify once every 5 minutes unless force
|
70
|
+
if chat_user.last_notified_at.present? && !force
|
71
|
+
next if (Time.zone.now - chat_user.last_notified_at) < NOTIFY_AFTER
|
72
|
+
end
|
73
|
+
|
74
|
+
EffectiveMessaging.send_email(:chat_new_message, self, chat_user)
|
75
|
+
chat_user
|
76
|
+
end
|
77
|
+
|
78
|
+
ChatUser.where(id: notified).update_all(last_notified_at: Time.zone.now) if notified.present?
|
79
|
+
|
80
|
+
# updated_at is when last message was sent
|
81
|
+
touch
|
82
|
+
end
|
83
|
+
|
84
|
+
def chat_user(user:)
|
85
|
+
raise('expected an effective_messaging_user') unless user.class.respond_to?(:effective_messaging_user?)
|
86
|
+
chat_users.find { |cu| cu.user_id == user.id && cu.user_type == user.class.name }
|
87
|
+
end
|
88
|
+
|
89
|
+
def build_chat_user(user:)
|
90
|
+
chat_user(user: user) || chat_users.build(user: user)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Always build
|
94
|
+
def build_chat_message(user:, body: nil)
|
95
|
+
raise('expected an effective_messaging_user') unless user.class.respond_to?(:effective_messaging_user?)
|
96
|
+
chat_messages.build(user: user, body: body)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Builders for polymorphic users form
|
100
|
+
def users
|
101
|
+
chat_users.map(&:user)
|
102
|
+
end
|
103
|
+
|
104
|
+
def user_ids
|
105
|
+
chat_users.map(&:user_id)
|
106
|
+
end
|
107
|
+
|
108
|
+
def user_ids=(user_ids)
|
109
|
+
raise('expected a user_type') unless user_type.present?
|
110
|
+
|
111
|
+
# The users in this chat
|
112
|
+
self.users = user_type.constantize.where(id: user_ids)
|
113
|
+
|
114
|
+
# Return user_ids
|
115
|
+
user_ids
|
116
|
+
end
|
117
|
+
|
118
|
+
def users=(users)
|
119
|
+
users = Array(users)
|
120
|
+
raise('expected a effective_messaging_user') unless users.all? { |user| user.class.respond_to?(:effective_messaging_user?) }
|
121
|
+
|
122
|
+
# Mark for destruction
|
123
|
+
chat_users.each { |cu| cu.mark_for_destruction unless users.include?(cu.user) }
|
124
|
+
|
125
|
+
# Find or build chat_users
|
126
|
+
users.each { |user| build_chat_user(user: user) }
|
127
|
+
|
128
|
+
# Return users
|
129
|
+
users
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
class ChatMessage < ActiveRecord::Base
|
5
|
+
self.table_name = EffectiveMessaging.chat_messages_table_name.to_s
|
6
|
+
|
7
|
+
log_changes(to: :chat) if respond_to?(:log_changes)
|
8
|
+
|
9
|
+
belongs_to :chat, counter_cache: true
|
10
|
+
|
11
|
+
# Who sent this message
|
12
|
+
belongs_to :chat_user
|
13
|
+
belongs_to :user, polymorphic: true
|
14
|
+
|
15
|
+
effective_resource do
|
16
|
+
name :string # The name, anonymous or display, when sent
|
17
|
+
body :text
|
18
|
+
|
19
|
+
timestamps
|
20
|
+
end
|
21
|
+
|
22
|
+
scope :sorted, -> { order(:id) }
|
23
|
+
scope :deep, -> { includes(:chat) }
|
24
|
+
|
25
|
+
# Use the controller's current_user to initialize the chat_user, user and name
|
26
|
+
before_validation(if: -> { new_record? && chat.present? }) do
|
27
|
+
self.user ||= chat.current_user
|
28
|
+
self.chat_user ||= chat.chat_user(user: self.user)
|
29
|
+
self.name ||= self.chat_user&.name
|
30
|
+
end
|
31
|
+
|
32
|
+
after_commit(on: :create) { chat.notify!(except: chat_user) }
|
33
|
+
|
34
|
+
validates :name, presence: true
|
35
|
+
validates :body, presence: true
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
body.presence || 'New Chat Message'
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
class ChatUser < ActiveRecord::Base
|
5
|
+
self.table_name = EffectiveMessaging.chat_users_table_name.to_s
|
6
|
+
|
7
|
+
log_changes(to: :chat) if respond_to?(:log_changes)
|
8
|
+
|
9
|
+
belongs_to :chat
|
10
|
+
belongs_to :user, polymorphic: true
|
11
|
+
|
12
|
+
scope :with_name, -> (name) {
|
13
|
+
anonymous = where(chat_id: Chat.where(anonymous: true)).where('anonymous_name ILIKE ?', "%#{name}%")
|
14
|
+
displayed = where(chat_id: Chat.where(anonymous: false)).where('display_name ILIKE ?', "%#{name}%")
|
15
|
+
|
16
|
+
anonymous.or(displayed)
|
17
|
+
}
|
18
|
+
|
19
|
+
effective_resource do
|
20
|
+
display_name :string
|
21
|
+
anonymous_name :string
|
22
|
+
|
23
|
+
last_notified_at :datetime
|
24
|
+
|
25
|
+
timestamps
|
26
|
+
end
|
27
|
+
|
28
|
+
scope :sorted, -> { order(:id) }
|
29
|
+
scope :deep, -> { includes(:chat) }
|
30
|
+
|
31
|
+
before_validation do
|
32
|
+
self.display_name ||= user.effective_messaging_display_name
|
33
|
+
self.anonymous_name ||= user.effective_messaging_anonymous_name
|
34
|
+
end
|
35
|
+
|
36
|
+
validates :display_name, presence: true, length: { maximum: 255 }
|
37
|
+
validates :anonymous_name, presence: true, length: { maximum: 255 }
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
name.presence || 'New Chat User'
|
41
|
+
end
|
42
|
+
|
43
|
+
def name
|
44
|
+
chat&.anonymous? ? anonymous_name : display_name
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'effective/chats/chat_message', chat_message: :chat_message
|
@@ -0,0 +1 @@
|
|
1
|
+
= render 'effective/chats/chat', chat: chat, admin: true
|
@@ -0,0 +1,17 @@
|
|
1
|
+
= effective_form_with(model: [:admin, chat], engine: true) do |f|
|
2
|
+
= f.text_field :title, label: "Title"
|
3
|
+
|
4
|
+
- if f.object.anonymous?
|
5
|
+
= f.static_field :anonymous do
|
6
|
+
%p Yes, this is an anonymous chat. User names and emails will not be displayed
|
7
|
+
- else
|
8
|
+
= f.check_box :anonymous, label: 'Yes, this is an anonymous chat', hint: 'user names and emails will not be displayed'
|
9
|
+
|
10
|
+
= f.hidden_field :user_type, value: current_user.class.name
|
11
|
+
|
12
|
+
- ajax_url = (@select2_ajax_path || effective_resources.users_admin_select2_ajax_index_path) unless Rails.env.test?
|
13
|
+
|
14
|
+
= f.select :user_ids, current_user.class.all, required: true,
|
15
|
+
ajax_url: ajax_url, hint: 'The users that can participate in this chat'
|
16
|
+
|
17
|
+
= effective_submit(f)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
= render 'layout' do
|
2
|
+
- chat_user = chat.chat_user(user: current_user)
|
3
|
+
|
4
|
+
- # New message form
|
5
|
+
- if chat_user.present? && EffectiveResources.authorized?(self, :update, chat)
|
6
|
+
= render('effective/chats/form', chat: chat)
|
7
|
+
|
8
|
+
- elsif EffectiveResources.authorized?(self, :show, chat)
|
9
|
+
= render('effective/chats/summary', chat: chat)
|
10
|
+
= render(partial: 'effective/chats/chat_message', collection: chat.chat_messages, chat: chat)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
= effective_form_with(model: chat, engine: true, remote: true) do |f|
|
2
|
+
-# Doesn't do anything, we just need something to submit thats not the ID
|
3
|
+
= f.hidden_field :user_type
|
4
|
+
|
5
|
+
- # This is a remote form so we refresh all the chat messages each time we submit
|
6
|
+
= render('effective/chats/summary', chat: chat)
|
7
|
+
= render(partial: 'effective/chats/chat_message', collection: chat.chat_messages, chat: chat)
|
8
|
+
|
9
|
+
- if chat.chat_messages.blank?
|
10
|
+
%p There are no messages so far. Please send one!
|
11
|
+
|
12
|
+
%hr
|
13
|
+
|
14
|
+
- chat_message = chat.build_chat_message(user: current_user)
|
15
|
+
- chat_user = chat.chat_user(user: current_user)
|
16
|
+
|
17
|
+
.card
|
18
|
+
.card-header.bg-secondary
|
19
|
+
Send message
|
20
|
+
.card-body
|
21
|
+
%p Your name is displayed as <strong>#{chat_user.name}</strong>.
|
22
|
+
|
23
|
+
= f.fields_for :chat_messages, chat_message do |fcm|
|
24
|
+
- # The user and name are set by controller's current_user
|
25
|
+
= fcm.text_area :body, required: true, label: 'Send message...'
|
26
|
+
|
27
|
+
= f.submit 'Send Message'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%p
|
2
|
+
- if chat.anonymous?
|
3
|
+
= badges('anonymous')
|
4
|
+
|
5
|
+
= succeed('.') do
|
6
|
+
A chat with
|
7
|
+
= pluralize(chat.chat_users.count, 'participants')
|
8
|
+
opened
|
9
|
+
= time_ago_in_words(chat.created_at)
|
10
|
+
ago
|
11
|
+
|
12
|
+
= succeed('.') do
|
13
|
+
= pluralize(chat.chat_messages_count, 'message')
|
@@ -0,0 +1,10 @@
|
|
1
|
+
%h2 Messages and Chat
|
2
|
+
|
3
|
+
- if current_user.chats.present?
|
4
|
+
%p You are a member of #{pluralize(current_user.chats.length, 'chat')}.
|
5
|
+
|
6
|
+
- datatable = EffectiveResources.best('EffectiveChatsDatatable').new(self, namespace: :effective)
|
7
|
+
= render_datatable(datatable, simple: true)
|
8
|
+
|
9
|
+
- else
|
10
|
+
%p You haven't received any messages. When you do, we'll show it here.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
EffectiveMessaging.setup do |config|
|
2
|
+
config.chats_table_name = :chats
|
3
|
+
config.chat_users_table_name = :chat_users
|
4
|
+
config.chat_messages_table_name = :chat_messages
|
5
|
+
|
6
|
+
# Layout Settings
|
7
|
+
# Configure the Layout per controller, or all at once
|
8
|
+
# config.layout = { application: 'application', admin: 'admin' }
|
9
|
+
|
10
|
+
# Mailer Settings
|
11
|
+
# Please see config/initializers/effective_messaging.rb for default effective_* gem mailer settings
|
12
|
+
#
|
13
|
+
# Configure the class responsible to send e-mails.
|
14
|
+
# config.mailer = 'Effective::MessagingMailer'
|
15
|
+
#
|
16
|
+
# Override effective_resource mailer defaults
|
17
|
+
#
|
18
|
+
# config.parent_mailer = nil # The parent class responsible for sending emails
|
19
|
+
# config.deliver_method = nil # The deliver method, deliver_later or deliver_now
|
20
|
+
# config.mailer_layout = nil # Default mailer layout
|
21
|
+
# config.mailer_sender = nil # Default From value
|
22
|
+
# config.mailer_admin = nil # Default To value for Admin correspondence
|
23
|
+
# config.mailer_subject = nil # Proc.new method used to customize Subject
|
24
|
+
|
25
|
+
# Will work with effective_email_templates gem
|
26
|
+
config.use_effective_email_templates = true
|
27
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Rails.application.routes.draw do
|
4
|
+
mount EffectiveMessaging::Engine => '/', as: 'effective_messaging'
|
5
|
+
end
|
6
|
+
|
7
|
+
EffectiveMessaging::Engine.routes.draw do
|
8
|
+
# Public routes
|
9
|
+
scope module: 'effective' do
|
10
|
+
resources :chats, only: [:show, :update]
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :admin do
|
14
|
+
resources :chats
|
15
|
+
resources :chat_messages, only: [:index, :show, :destroy]
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class CreateEffectiveMessaging < ActiveRecord::Migration[6.0]
|
2
|
+
def change
|
3
|
+
create_table <%= @chats_table_name %> do |t|
|
4
|
+
t.integer :parent_id
|
5
|
+
t.string :parent_type
|
6
|
+
|
7
|
+
t.string :title
|
8
|
+
t.boolean :anonymous, default: false
|
9
|
+
|
10
|
+
t.integer :chat_messages_count, default: 0
|
11
|
+
t.string :token
|
12
|
+
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table <%= @chat_users_table_name %> do |t|
|
17
|
+
t.integer :chat_id
|
18
|
+
|
19
|
+
t.integer :user_id
|
20
|
+
t.string :user_type
|
21
|
+
|
22
|
+
t.string :display_name
|
23
|
+
t.string :anonymous_name
|
24
|
+
|
25
|
+
t.datetime :last_notified_at
|
26
|
+
|
27
|
+
t.timestamps
|
28
|
+
end
|
29
|
+
|
30
|
+
create_table <%= @chat_messages_table_name %> do |t|
|
31
|
+
t.integer :chat_id
|
32
|
+
t.integer :chat_user_id
|
33
|
+
|
34
|
+
t.integer :user_id
|
35
|
+
t.string :user_type
|
36
|
+
|
37
|
+
t.string :name
|
38
|
+
t.text :body
|
39
|
+
|
40
|
+
t.timestamps
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/db/seeds.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
puts "Running effective_messaging seeds"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module EffectiveMessaging
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
engine_name 'effective_messaging'
|
4
|
+
|
5
|
+
# Set up our default configuration options.
|
6
|
+
initializer 'effective_messaging.defaults', before: :load_config_initializers do |app|
|
7
|
+
eval File.read("#{config.root}/config/effective_messaging.rb")
|
8
|
+
end
|
9
|
+
|
10
|
+
# Include acts_as_messaging concern and allow any ActiveRecord object to call it
|
11
|
+
initializer 'effective_messaging.active_record' do |app|
|
12
|
+
app.config.to_prepare do
|
13
|
+
ActiveRecord::Base.extend(EffectiveMessagingUser::Base)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'effective_resources'
|
2
|
+
require 'effective_datatables'
|
3
|
+
require 'effective_messaging/engine'
|
4
|
+
require 'effective_messaging/version'
|
5
|
+
|
6
|
+
module EffectiveMessaging
|
7
|
+
|
8
|
+
def self.config_keys
|
9
|
+
[
|
10
|
+
:chats_table_name, :chat_users_table_name, :chat_messages_table_name,
|
11
|
+
:layout,
|
12
|
+
:mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject, :use_effective_email_templates
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
include EffectiveGem
|
17
|
+
|
18
|
+
def self.mailer_class
|
19
|
+
mailer&.constantize || Effective::MessagingMailer
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module EffectiveMessaging
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
|
6
|
+
desc 'Creates an EffectiveMessaging initializer in your application.'
|
7
|
+
|
8
|
+
source_root File.expand_path('../../templates', __FILE__)
|
9
|
+
|
10
|
+
def self.next_migration_number(dirname)
|
11
|
+
if not ActiveRecord::Base.timestamped_migrations
|
12
|
+
Time.new.utc.strftime("%Y%m%d%H%M%S")
|
13
|
+
else
|
14
|
+
'%.3d' % (current_migration_number(dirname) + 1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def copy_initializer
|
19
|
+
template ('../' * 3) + 'config/effective_messaging.rb', 'config/initializers/effective_messaging.rb'
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_migration_file
|
23
|
+
@chats_table_name = ':' + EffectiveMessaging.chats_table_name.to_s
|
24
|
+
@chat_users_table_name = ':' + EffectiveMessaging.chat_users_table_name.to_s
|
25
|
+
@chat_messages_table_name = ':' + EffectiveMessaging.chat_messages_table_name.to_s
|
26
|
+
|
27
|
+
migration_template ('../' * 3) + 'db/migrate/01_create_effective_messaging.rb.erb', 'db/migrate/create_effective_messaging.rb'
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,281 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: effective_messaging
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Code and Effect
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-01-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 6.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 6.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: effective_bootstrap
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: effective_datatables
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 4.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 4.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: effective_orders
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: effective_resources
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: effective_roles
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: wicked
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sqlite3
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: devise
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: haml-rails
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: pry-byebug
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: effective_test_bot
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: effective_developer
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: effective_email_templates
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
description: Centralize the communication between one or more users.
|
210
|
+
email:
|
211
|
+
- info@codeandeffect.com
|
212
|
+
executables: []
|
213
|
+
extensions: []
|
214
|
+
extra_rdoc_files: []
|
215
|
+
files:
|
216
|
+
- MIT-LICENSE
|
217
|
+
- README.md
|
218
|
+
- Rakefile
|
219
|
+
- app/assets/config/effective_messaging_manifest.js
|
220
|
+
- app/assets/javascripts/effective_messaging.js
|
221
|
+
- app/assets/javascripts/effective_messaging/base.js
|
222
|
+
- app/assets/stylesheets/effective_messaging.scss
|
223
|
+
- app/assets/stylesheets/effective_messaging/base.scss
|
224
|
+
- app/controllers/admin/chat_messages_controller.rb
|
225
|
+
- app/controllers/admin/chats_controller.rb
|
226
|
+
- app/controllers/effective/chats_controller.rb
|
227
|
+
- app/datatables/admin/effective_chat_messages_datatable.rb
|
228
|
+
- app/datatables/admin/effective_chats_datatable.rb
|
229
|
+
- app/datatables/effective_chats_datatable.rb
|
230
|
+
- app/helpers/effective_messaging_helper.rb
|
231
|
+
- app/mailers/effective/messaging_mailer.rb
|
232
|
+
- app/models/concerns/effective_messaging_user.rb
|
233
|
+
- app/models/effective/chat.rb
|
234
|
+
- app/models/effective/chat_message.rb
|
235
|
+
- app/models/effective/chat_user.rb
|
236
|
+
- app/views/admin/chat_messages/_chat_message.html.haml
|
237
|
+
- app/views/admin/chats/_chat.html.haml
|
238
|
+
- app/views/admin/chats/_form.html.haml
|
239
|
+
- app/views/admin/chats/_form_chat.html.haml
|
240
|
+
- app/views/admin/chats/_layout.html.haml
|
241
|
+
- app/views/effective/chats/_chat.html.haml
|
242
|
+
- app/views/effective/chats/_chat_message.html.haml
|
243
|
+
- app/views/effective/chats/_form.html.haml
|
244
|
+
- app/views/effective/chats/_layout.html.haml
|
245
|
+
- app/views/effective/chats/_summary.html.haml
|
246
|
+
- app/views/effective/messaging/_dashboard.html.haml
|
247
|
+
- app/views/effective/messaging_mailer/chat_new_message.liquid
|
248
|
+
- config/effective_messaging.rb
|
249
|
+
- config/routes.rb
|
250
|
+
- db/migrate/01_create_effective_messaging.rb.erb
|
251
|
+
- db/seeds.rb
|
252
|
+
- lib/effective_messaging.rb
|
253
|
+
- lib/effective_messaging/engine.rb
|
254
|
+
- lib/effective_messaging/version.rb
|
255
|
+
- lib/generators/effective_messaging/install_generator.rb
|
256
|
+
- lib/generators/templates/effective_messaging_mailer_preview.rb
|
257
|
+
- lib/tasks/effective_messaging_tasks.rake
|
258
|
+
homepage: https://github.com/code-and-effect/effective_messaging
|
259
|
+
licenses:
|
260
|
+
- MIT
|
261
|
+
metadata: {}
|
262
|
+
post_install_message:
|
263
|
+
rdoc_options: []
|
264
|
+
require_paths:
|
265
|
+
- lib
|
266
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
267
|
+
requirements:
|
268
|
+
- - ">="
|
269
|
+
- !ruby/object:Gem::Version
|
270
|
+
version: '0'
|
271
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
272
|
+
requirements:
|
273
|
+
- - ">="
|
274
|
+
- !ruby/object:Gem::Version
|
275
|
+
version: '0'
|
276
|
+
requirements: []
|
277
|
+
rubygems_version: 3.1.2
|
278
|
+
signing_key:
|
279
|
+
specification_version: 4
|
280
|
+
summary: Centralize the communication between one or more users.
|
281
|
+
test_files: []
|