messaged 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2607ebea948e9c5464a9fba7e3153def8d1e0093fccc7c72570b9aeced8b910f
4
- data.tar.gz: 4ab6464c09f420b6f18e6761317e0638d60d6fa30f0263f9cb67d7e174a5753d
3
+ metadata.gz: fe41021cc17ab7a3f9b46a8c036345c738b54539eda08f6a176604d0cf75c85b
4
+ data.tar.gz: d16f56a11dc02c6117e4965e02ac845451b85ae353351fa22a16bba292999d05
5
5
  SHA512:
6
- metadata.gz: 68b45ab5fa04546608da02a3aaf1cd945b497be9ea599ac9518ab4c0c076b8bf2f0885cbf2bb478ae0eb30e9f473bc455e3f9aa856be688477976bf92b39e42f
7
- data.tar.gz: bcdcdebc54df17cfe5107e4926f57947c445b7ea14e217ed8bb006ccc741fec622fd51983ed15b06e870a9cf502340d3ddefd5e64c43ca775793cc92d4b110df
6
+ metadata.gz: 63a7e3bd9685a055e0f1f29b0d807036570f7114997d0fd7bde2e155f99b98fe1267f55843baf7d8319ca9e615306d7be92c45fb9ba6df4cbeac353a2fce9a75
7
+ data.tar.gz: ddee84cb919cd85685050f5aa550fab336486323b6e8645180e39b8b2b9d78d32f5c407cfc96089521c1ebdcada8c2d75d7dc86b07259c2908a399e15efc64b3
data/README.md CHANGED
@@ -26,6 +26,15 @@ rails generate messaged:install
26
26
  rails messaged:install:migrations
27
27
  ```
28
28
 
29
+ ### Importmap
30
+
31
+ If you do not yet have importmap-rails added to your application, be sure to add `config/importmap.rb`:
32
+ ```ruby
33
+ # config/importmap.rb
34
+ pin "application", preload: true
35
+ pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
36
+ ```
37
+
29
38
  ## Usage
30
39
  Messages broadcast to the DOM element id `messages`
31
40
  ```html
@@ -36,6 +45,24 @@ To get started with a basic HTML structure, run in your terminal: `rails generat
36
45
 
37
46
  If you're using this engine or `turbo-rails` for the first time, it is recommended to generate the views to familiarize yourself with how turbo tags are used when turbo streaming.
38
47
 
48
+ ### Routes
49
+
50
+ If you're starting a fresh application, ensure your application has a root path.
51
+ ```ruby
52
+ # For example:
53
+ root to: "home#index"
54
+ ```
55
+
56
+ Next, set up your ActionCable routes if you haven't already.
57
+ ```ruby
58
+ mount ActionCable.server => '/cable'
59
+ ```
60
+
61
+ Lastly, mount the Messaged engine's paths.
62
+ ```ruby
63
+ mount Messaged::Engine => "/messaged"
64
+ ```
65
+
39
66
  ### Users
40
67
  Messaged assumes you have a user model. You may customize the user model name in the initializer. For example, if your user model is called Member:
41
68
  ```ruby
@@ -78,8 +105,11 @@ Messaged is intended to be named through the nomenclature used in [Noticed](http
78
105
  —Ian
79
106
 
80
107
  ## TODO
81
- * Add dynamic configurations for message broadcasting to tenants (like an organization chat room), rooms (like a Discord channel), or users (like direct messages in most direct-messaging apps such as Signal)
82
- * Figure out how to support permissioning/authorization (such as Pundit/Cancancan) without being opinionated
83
108
  * Complete adding rich_text support
84
- * Ensure I18n support for hard-coded English strings that are seen by the end-user
85
- * Create and finish the test suite
109
+ * Complete multi-tenant support
110
+ * Create and finish the test suite via TestKit
111
+
112
+ ### TODO on `bleeding` pre-merge
113
+ * Add documentation about how to extend messages and rooms
114
+ * If not for anyone else, do it for future you
115
+ * Add to docs about how it is up to the dev to determine how messages/rooms are authorized
@@ -1,5 +1,5 @@
1
1
  module Messaged
2
- class ApplicationController < ActionController::Base
2
+ class ApplicationController < ::ApplicationController
3
3
  helper Messaged::Engine.helpers
4
4
  helper_method \
5
5
  :messaged_current_user,
@@ -1,30 +1,31 @@
1
1
  module Messaged
2
2
  class MessagesController < ApplicationController
3
- # TODO: How does the enginer user require authnetication without assuming Devise?
4
- # before_action :authenticate_user!
3
+ # User should be authenticated by main.app
5
4
  before_action :set_message, only: [:destroy, :edit, :show, :update]
6
5
 
7
6
  def index
8
- # TODO: How does the enginer user require authnetication without assuming Devise / ActsAsTenant?
9
- # @messages = Message.where(account: current_account)
10
7
  @messages = Message.all
11
8
  @new_message = Message.new
12
- @new_message = messaged_current_owner.messages.build if messaged_current_owner
9
+ return unless messaged_current_owner && messaged_current_owner.class != Messaged::NullUser
10
+ @new_message = messaged_current_owner.messages.build
13
11
  end
14
12
 
15
13
  def show; end
16
14
 
17
15
  def new
18
16
  @message = Message.new
19
- @message = messaged_current_owner.messages.build if messaged_current_owner
17
+ return unless messaged_current_owner && messaged_current_owner.class != Messaged::NullUser
18
+ @message = messaged_current_owner.messages.build
20
19
  end
21
20
 
22
21
  def create
23
- # TODO: How does the enginer user require authnetication without assuming Devise / ActsAsTenant?
24
- # @message = Message.new(message_params.merge(account: current_account, user: current_user))
25
22
  @message = Message.new(message_params)
26
23
  if @message.save
27
- @new_message = messaged_current_owner.messages.build if messaged_current_owner
24
+ if messaged_current_owner && messaged_current_owner.class != Messaged::NullUser
25
+ @new_message = messaged_current_owner.messages.build
26
+ else
27
+ @new_message = Message.new
28
+ end
28
29
  respond_to do |format|
29
30
  format.turbo_stream do
30
31
  render turbo_stream: turbo_stream.append(:messages, partial: "messaged/messages/message",
@@ -40,7 +41,6 @@ module Messaged
40
41
  def edit; end
41
42
 
42
43
  def update
43
- # TODO: (Security risk) How to authenticate user agnostically?
44
44
  if @message.update(message_params)
45
45
  render @message
46
46
  else
@@ -49,7 +49,6 @@ module Messaged
49
49
  end
50
50
 
51
51
  def destroy
52
- # TODO: (Security risk) How to authenticate user agnostically?
53
52
  @message.destroy
54
53
  respond_to do |format|
55
54
  format.turbo_stream { render turbo_stream: turbo_stream.remove(@message) }
@@ -60,7 +59,6 @@ module Messaged
60
59
  private
61
60
 
62
61
  def set_message
63
- # TODO: (Security risk) How to authenticate user agnostically before declaring?
64
62
  @message = Message.find(params[:id])
65
63
  end
66
64
 
@@ -0,0 +1,62 @@
1
+ module Messaged
2
+ class RoomsController < ApplicationController
3
+ # User should be authenticated by main.app
4
+ before_action :set_room, only: [:destroy, :edit, :show, :update]
5
+
6
+ def index
7
+ @rooms = Room.all
8
+ end
9
+
10
+ def show
11
+ @new_message = Message.new
12
+ return unless messaged_current_owner && messaged_current_owner.class != Messaged::NullUser
13
+ @new_message = messaged_current_owner.messages.build
14
+ end
15
+
16
+ def new
17
+ @room = Room.new
18
+ @recipient = Messaged.user_class.find(params[:recipient]) if params.dig(:recipient)
19
+ return unless messaged_current_owner && messaged_current_owner.class != Messaged::NullUser
20
+ @room = messaged_current_owner.rooms.build
21
+ end
22
+
23
+ def create
24
+ @room = Room.new(room_params)
25
+ if @room.save
26
+ respond_to do |format|
27
+ format.html { redirect_to @room }
28
+ end
29
+ else
30
+ render :new, status: :unprocessable_entity
31
+ end
32
+ end
33
+
34
+ def edit; end
35
+
36
+ def update
37
+ if @room.update(room_params)
38
+ render @room
39
+ else
40
+ render :edit, status: :unprocessable_entity
41
+ end
42
+ end
43
+
44
+ def destroy
45
+ @room.destroy
46
+ respond_to do |format|
47
+ format.turbo_stream { render turbo_stream: turbo_stream.remove(@room) }
48
+ format.html { redirect_to rooms_url }
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def set_room
55
+ @room = Room.find(params[:id])
56
+ end
57
+
58
+ def room_params
59
+ params.require(:room).permit(:title, :user_id, :tenant_id, :recipient_id)
60
+ end
61
+ end
62
+ end
@@ -14,12 +14,11 @@ module Messaged
14
14
  inverse_of: :messages,
15
15
  optional: true
16
16
  end
17
- belongs_to :room, optional: true
17
+ belongs_to :messaged_room, optional: true, class_name: 'Messaged::Room'
18
18
 
19
19
  has_rich_text :content
20
20
  validates :content, presence: true
21
21
 
22
- # TODO: This needs to be added to a generator
23
22
  after_create_commit -> { broadcast_append_later_to ["messages"], target: "messages", partial: "messaged/messages/message" }
24
23
  after_update_commit -> { broadcast_replace_later_to ["messages"], target: "#{dom_id(self)}", partial: "messaged/messages/message" }
25
24
  after_destroy_commit -> { broadcast_remove_to ["messages"] }
@@ -28,7 +27,7 @@ module Messaged
28
27
  # fallback to the chat room, and finally tenant if they exist.
29
28
  def owner
30
29
  return user if user
31
- return room if room
30
+ return messaged_room if messaged_room
32
31
  return tenant if Messaged.tenant_class_name && tenant
33
32
  return nil # replace with user, tenant, or room
34
33
  end
@@ -3,20 +3,25 @@ module Messaged
3
3
  # User association
4
4
  belongs_to :user,
5
5
  class_name: Messaged.user_class_name,
6
- inverse_of: :messages,
6
+ inverse_of: :rooms,
7
+ optional: true
8
+ # Recipient user association
9
+ belongs_to :recipient,
10
+ class_name: Messaged.user_class_name,
11
+ inverse_of: :rooms,
7
12
  optional: true
8
13
  # Multi-tenant option
9
14
  if Messaged.tenant_class_name
10
15
  belongs_to :tenant,
11
16
  class_name: Messaged.tenant_class_name,
12
- inverse_of: :messages,
17
+ inverse_of: :rooms,
13
18
  optional: true
14
19
  end
15
20
  validates :title, presence: true
16
21
 
17
- has_many :messages, dependent: :destroy
22
+ has_many :messaged_messages, dependent: :destroy, class_name: 'Messaged::Message', foreign_key: 'messaged_room_id'
18
23
 
19
- # Messages should default to the person sending them, otherwise
24
+ # Rooms should default to the person sending them, otherwise
20
25
  # fallback to the chat room, and finally tenant if they exist.
21
26
  def owner
22
27
  return user if user
@@ -5,7 +5,6 @@
5
5
  <%= csrf_meta_tags %>
6
6
  <%= csp_meta_tag %>
7
7
 
8
- <%= stylesheet_link_tag "messaged/application", media: "all" %>
9
8
  <%= javascript_importmap_tags %>
10
9
  </head>
11
10
  <body>
@@ -7,3 +7,5 @@ en:
7
7
  delete: 'Delete'
8
8
  header: Messages
9
9
  null_user_name: 'Deleted User'
10
+ room_name: 'Room Name'
11
+ room_index: 'Rooms'
data/config/routes.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  Messaged::Engine.routes.draw do
2
2
  resources :messages
3
+ resources :rooms
3
4
  end
@@ -1,31 +1,34 @@
1
1
  require 'messaged/base_migration'
2
2
  class CreateMessaged < Messaged::BaseMigration
3
3
  def change
4
- create_table :messaged_messages do |t|
4
+ create_table :messaged_rooms do |t|
5
5
  t.references :tenant, type: user_id_type, index: false
6
- t.index [:tenant_id], name: :index_messaged_messages_on_tenant_id
6
+ t.index [:tenant_id], name: :index_messaged_rooms_on_tenant_id
7
7
 
8
8
  t.references :user, type: tenant_id_type, index: false
9
- t.index [:user_id], name: :index_messaged_messages_on_user_id
10
-
11
- t.references :messaged_room, foreign_key: true
9
+ t.index [:user_id], name: :index_messaged_rooms_on_user_id
12
10
 
13
- t.text :content
11
+ t.references :recipient, type: user_id_type, index: false
12
+ t.index [:recipient_id], name: :index_messaged_rooms_on_recipient_id
14
13
 
15
- # Choose an association: room, user, tenant
16
- t.string :delivery_target
14
+ t.string :title
17
15
 
18
16
  t.timestamps
19
17
  end
20
18
 
21
- create_table :messaged_rooms do |t|
19
+ create_table :messaged_messages do |t|
22
20
  t.references :tenant, type: user_id_type, index: false
23
- t.index [:tenant_id], name: :index_messaged_rooms_on_tenant_id
21
+ t.index [:tenant_id], name: :index_messaged_messages_on_tenant_id
24
22
 
25
23
  t.references :user, type: tenant_id_type, index: false
26
- t.index [:user_id], name: :index_messaged_rooms_on_user_id
24
+ t.index [:user_id], name: :index_messaged_messages_on_user_id
27
25
 
28
- t.string :title
26
+ t.belongs_to :messaged_room, index: true
27
+
28
+ t.text :content
29
+
30
+ # Choose an association: room, user, tenant
31
+ t.string :delivery_target
29
32
 
30
33
  t.timestamps
31
34
  end
@@ -1,8 +1,8 @@
1
1
  <%= form_with model: message, class: 'messaged-form' do |f| %>
2
2
  <%= f.label :content, t('messaged.send_a_message') %>
3
- <%= f.hidden_field :user_id %>
3
+ <%= f.hidden_field :user_id, value: messaged_current_user.id if messaged_current_user %>
4
4
  <%= f.hidden_field :tenant_id %>
5
- <%= f.hidden_field :messaged_room_id %>
5
+ <%= f.hidden_field :messaged_room_id, value: room.id if room %>
6
6
  <%= f.text_area :content %>
7
7
  <%= f.submit nil, class: 'messaged-button' %>
8
8
  <% end %>
@@ -5,7 +5,7 @@
5
5
  <% if t('messaged.header').present? %>
6
6
  <h1 class="messaged-header"><%= t('messaged.header') %></h1>
7
7
  <% end %>
8
- <% # TODO: How do we make current_user model agnostic? %>
8
+
9
9
  <%#= turbo_stream_from current_account, "messages" %>
10
10
  <%= turbo_stream_from "messages" %>
11
11
  <div class="messaged-messages" id="messages">
@@ -0,0 +1,8 @@
1
+ <%= form_with model: room, class: 'messaged-room-form' do |f| %>
2
+ <%= f.label :title, t('messaged.room_name') %>
3
+ <%= f.text_field :title, value: params[:title] %>
4
+ <%= f.hidden_field :user_id, value: messaged_current_user.id if messaged_current_user %>
5
+ <%= f.hidden_field :recipient_id, value: @recipient.id if @recipient %>
6
+ <%= f.hidden_field :tenant_id %>
7
+ <%= f.submit nil, class: 'messaged-button' %>
8
+ <% end %>
@@ -0,0 +1,28 @@
1
+ <div class="messaged-room-container">
2
+ <div>
3
+ <div class="messaged-options">
4
+ <span><%= link_to t('messaged.edit'), messaged.edit_room_path(room), class: "messaged-edit-link", "data-turbo-action": "replace" %></span>
5
+ <%= button_to t('messaged.delete'), messaged.room_path(room), method: :delete, form: { data: { turbo_confirm: t('messaged.confirm') } }, class: "messaged-delete-link", "data-turbo-action": "delete" %>
6
+ </div>
7
+ <div class="messaged-index-container">
8
+ <div class="messaged-outer-wrapper">
9
+ <div class="messaged-inner-wrapper">
10
+ <div class="messaged-index">
11
+ <% if room.title.present? %>
12
+ <h1 class="messaged-header"><%= room.title %></h1>
13
+ <% end %>
14
+
15
+ <%= turbo_stream_from "messages" %>
16
+ <div class="messaged-messages" id="messages">
17
+ <%= render @room.messaged_messages %>
18
+ </div>
19
+
20
+ <%= turbo_frame_tag "new_message" do %>
21
+ <%= render "messaged/messages/form", message: @new_message, room: @room %>
22
+ <% end %>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ </div>
@@ -0,0 +1,2 @@
1
+ <%= turbo_stream.append "rooms", @room %>
2
+ <%= turbo_stream.update "new_room", partial: "form", locals: { room: @new_room } %>
@@ -0,0 +1 @@
1
+ <%= render "form", room: @room %>
@@ -0,0 +1,14 @@
1
+ <div class="messaged-index-container">
2
+ <div class="messaged-outer-wrapper">
3
+ <div class="messaged-inner-wrapper">
4
+ <div class="messaged-index">
5
+ <% if t('messaged.header').present? %>
6
+ <h1 class="messaged-header"><%= t('messaged.room_index') %></h1>
7
+ <% end %>
8
+ <div class="messaged-rooms" id="rooms">
9
+ <%= render @rooms %>
10
+ </div>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ </div>
@@ -0,0 +1 @@
1
+ <%= render "form", room: @room %>
@@ -0,0 +1 @@
1
+ <%= render @room %>
@@ -8,7 +8,7 @@ module Messaged
8
8
  ]
9
9
  end
10
10
 
11
- def copy_view_templates
11
+ def copy_message_view_templates
12
12
  copy_file \
13
13
  'messages/_form.html.erb',
14
14
  'app/views/messaged/messages/_form.html.erb'
@@ -37,6 +37,36 @@ module Messaged
37
37
  'messages/show.html.erb',
38
38
  'app/views/messaged/messages/show.html.erb'
39
39
  end
40
+
41
+ def copy_room_view_templates
42
+ copy_file \
43
+ 'rooms/_form.html.erb',
44
+ 'app/views/messaged/rooms/_form.html.erb'
45
+
46
+ copy_file \
47
+ 'rooms/_room.html.erb',
48
+ 'app/views/messaged/rooms/_room.html.erb'
49
+
50
+ copy_file \
51
+ 'rooms/create.turbostream.erb',
52
+ 'app/views/messaged/rooms/create.turbostream.erb'
53
+
54
+ copy_file \
55
+ 'rooms/edit.html.erb',
56
+ 'app/views/messaged/rooms/edit.html.erb'
57
+
58
+ copy_file \
59
+ 'rooms/index.html.erb',
60
+ 'app/views/messaged/rooms/index.html.erb'
61
+
62
+ copy_file \
63
+ 'rooms/new.html.erb',
64
+ 'app/views/messaged/rooms/new.html.erb'
65
+
66
+ copy_file \
67
+ 'rooms/show.html.erb',
68
+ 'app/views/messaged/rooms/show.html.erb'
69
+ end
40
70
  end
41
71
  end
42
72
  end
@@ -7,9 +7,5 @@ module Messaged
7
7
  config.to_prepare do
8
8
  Messaged.user_class&.send(:include, Messaged::UserExtender)
9
9
  end
10
-
11
- # initializer "messaged.assets.precompile" do |app|
12
- # app.config.assets.precompile += %w( messaged/application.css )
13
- # end
14
10
  end
15
11
  end
@@ -1,3 +1,3 @@
1
1
  module Messaged
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: messaged
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - cjilbert504, ianrandmckenzie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-29 00:00:00.000000000 Z
11
+ date: 2023-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -28,30 +28,30 @@ dependencies:
28
28
  name: importmap-rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.1.5
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.1.5
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: turbo-rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 1.3.0
47
+ version: 1.2.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 1.3.0
54
+ version: 1.2.0
55
55
  description: A quick and easy way to implement an instant-messaging module using Turbo
56
56
  Rails.
57
57
  email:
@@ -62,10 +62,9 @@ extra_rdoc_files: []
62
62
  files:
63
63
  - README.md
64
64
  - Rakefile
65
- - app/assets/config/messaged_manifest.js
66
- - app/assets/stylesheets/messaged/application.css
67
65
  - app/controllers/messaged/application_controller.rb
68
66
  - app/controllers/messaged/messages_controller.rb
67
+ - app/controllers/messaged/rooms_controller.rb
69
68
  - app/javascript/application.js
70
69
  - app/jobs/messaged/application_job.rb
71
70
  - app/models/messaged/application_record.rb
@@ -90,6 +89,13 @@ files:
90
89
  - lib/generators/messaged/views/templates/messages/index.html.erb
91
90
  - lib/generators/messaged/views/templates/messages/new.html.erb
92
91
  - lib/generators/messaged/views/templates/messages/show.html.erb
92
+ - lib/generators/messaged/views/templates/rooms/_form.html.erb
93
+ - lib/generators/messaged/views/templates/rooms/_room.html.erb
94
+ - lib/generators/messaged/views/templates/rooms/create.turbostream.erb
95
+ - lib/generators/messaged/views/templates/rooms/edit.html.erb
96
+ - lib/generators/messaged/views/templates/rooms/index.html.erb
97
+ - lib/generators/messaged/views/templates/rooms/new.html.erb
98
+ - lib/generators/messaged/views/templates/rooms/show.html.erb
93
99
  - lib/generators/messaged/views/views_generator.rb
94
100
  - lib/messaged.rb
95
101
  - lib/messaged/base_migration.rb
@@ -1 +0,0 @@
1
- //= link_directory ../stylesheets/messaged .css
@@ -1,15 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */