-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add chat logic, add chat members logic
- Loading branch information
Showing
26 changed files
with
413 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,3 +52,4 @@ end | |
|
||
gem "devise" | ||
gem "listen", "~> 3.9" | ||
gem 'pundit' | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
class ChatMembersController < ApplicationController | ||
before_action :authenticate_user! | ||
before_action :set_workspace | ||
before_action :set_chat | ||
before_action :set_chat_member, only: [:destroy, :index, :new, :create] | ||
Check failure on line 5 in app/controllers/chat_members_controller.rb GitHub Actions / lint
|
||
before_action :require_admin_or_owner!, only: [:new, :create] | ||
Check failure on line 6 in app/controllers/chat_members_controller.rb GitHub Actions / lint
|
||
|
||
def index | ||
@chat_members = @chat.chat_members | ||
end | ||
|
||
def new | ||
@chat_member = @chat.chat_members.new | ||
end | ||
|
||
def create | ||
@chat_member = @chat.chat_members.new(chat_member_params) | ||
@chat_member.role = 'member' | ||
@chat_member.chat = @chat | ||
if @chat_member.save | ||
redirect_to workspace_path, notice: 'User was succesfully added to the chat' | ||
else | ||
render :new, notice: 'Failed creation. Try again' | ||
end | ||
end | ||
|
||
def destroy | ||
@chat_member.destroy | ||
redirect_to workspaces_path, notice: 'User were succesfully removed from the chat' | ||
end | ||
|
||
private | ||
|
||
def set_workspace | ||
@workspace = current_user.workspaces.find_by(id: params[:workspace_id]) | ||
unless @workspace | ||
redirect_to workspaces_path, notice: 'Workspace not found or not accessible.' | ||
end | ||
end | ||
|
||
def set_chat | ||
@chat = @workspace.chats.find(params[:chat_id]) | ||
end | ||
|
||
def set_chat_member | ||
@chat_member = @chat.chat_members.find_by(user_id: current_user.id) | ||
end | ||
|
||
def require_admin_or_owner! | ||
if ChatMemberPolicy.new(current_user, @chat_member).member? | ||
redirect_to workspaces_path, notice: 'You can not manage chat members because you have no access' | ||
end | ||
end | ||
|
||
def chat_member_params | ||
params.require(:chat_member).permit(:user_id) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
class ChatsController < ApplicationController | ||
before_action :authenticate_user! | ||
before_action :set_workspace | ||
before_action :require_workspace_owner!, only: [:new, :create, :destroy] | ||
|
||
def index | ||
@chats = ChatsQuery.new(@workspace, current_user).all_chats | ||
end | ||
|
||
def show | ||
@chat = @workspace.chats.find(params[:id]) | ||
end | ||
|
||
def new | ||
@chat = @workspace.chats.new | ||
end | ||
|
||
def create | ||
result = ChatsService::Create.call(current_user, chat_params, @workspace) | ||
if result.success? | ||
redirect_to workspace_chats_path(@workspace), notice: result[:payload][:text] | ||
else | ||
@chat = @workspace.chats.new(chat_params) | ||
render :new | ||
end | ||
end | ||
|
||
|
||
|
||
def destroy | ||
@chat = @workspace.chats.find(params[:id]) | ||
@chat.destroy | ||
redirect_to workspace_chats_path(@workspace), notice: 'Chat was successfully deleted.' | ||
end | ||
|
||
private | ||
|
||
def set_workspace | ||
@workspace = current_user.workspaces.find_by(id: params[:workspace_id]) | ||
|
||
unless @workspace | ||
redirect_to workspaces_path, alert: 'Workspace not found or not accessible.' | ||
end | ||
end | ||
|
||
def chat_params | ||
params.require(:chat).permit(:name, :chat_type, :companion_id) | ||
end | ||
|
||
def require_workspace_owner! | ||
if !WorkspacePolicy.new(current_user, @workspace).owner? | ||
redirect_to workspaces_path, notice: 'You can not manage the chat because you are not workspace owner' | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module ChatMembersHelper | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module ChatsHelper | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails | ||
import "@hotwired/turbo-rails" | ||
import "controllers" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
class Chat < ApplicationRecord | ||
belongs_to :workspace | ||
has_many :chat_members | ||
|
||
validates :name, presence: true | ||
validates :chat_type, inclusion: { in: %w[public private p2p], message: "%{value} is not a valid type" } | ||
validates :chat_status, inclusion: { in: %w[active archive], message: "%{value} is not a valid type" } | ||
|
||
def private_or_p2p? | ||
chat_type.in?(%w[private p2p]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class ChatMember < ApplicationRecord | ||
belongs_to :chat | ||
belongs_to :user | ||
|
||
validates :role, inclusion: { in: %w[member owner admin], message: "%{value} is not a valid role" } | ||
validate :chat_must_be_private_or_p2p | ||
|
||
private | ||
|
||
def chat_must_be_private_or_p2p | ||
unless chat.chat_type.in?(%w[private p2p]) | ||
errors.add(:chat, 'must be private or p2p') | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class ChatMemberPolicy < ApplicationPolicy | ||
def member? | ||
record.role == 'member' | ||
end | ||
|
||
def admin? | ||
record.role == 'admin' | ||
end | ||
|
||
def owner? | ||
record.role == 'owner' | ||
end | ||
|
||
def can_remove? | ||
['owner', 'admin'].include?(record.role) | ||
end | ||
|
||
def can_add_members? | ||
['owner', 'admin'].include?(record.role) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,8 @@ class WorkspacePolicy < ApplicationPolicy | |
def can_destroy? | ||
record_owner? | ||
end | ||
|
||
def owner? | ||
record_owner? | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
class ChatsQuery | ||
def initialize(workspace, user) | ||
@workspace = workspace | ||
@user = user | ||
end | ||
|
||
def all_chats | ||
Chat.find_by_sql([combined_chats_sql]) | ||
end | ||
|
||
private | ||
|
||
def combined_chats_sql | ||
<<-SQL | ||
(#{public_chats_sql.to_sql}) | ||
UNION | ||
(#{private_chats_sql.to_sql}) | ||
UNION | ||
(#{p2p_chats_sql.to_sql}) | ||
SQL | ||
end | ||
|
||
def public_chats_sql | ||
Chat.select('*') | ||
.where(workspace_id: @workspace.id, chat_type: 'public', chat_status: 'active') | ||
end | ||
|
||
def private_chats_sql | ||
Chat.select('chats.*') | ||
.joins(:chat_members) | ||
.where(workspace_id: @workspace.id, chat_type: 'private', chat_status: 'active') | ||
.where(chat_members: { user_id: @user.id }) | ||
end | ||
|
||
def p2p_chats_sql | ||
Chat.select('chats.*') | ||
.joins(:chat_members) | ||
.where(workspace_id: @workspace.id, chat_type: 'p2p', chat_status: 'active') | ||
.where(chat_members: { user_id: @user.id }) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
module ChatsService | ||
class Create < ApplicationService | ||
def call(current_user, params, workspace) | ||
@user = current_user | ||
@params = params | ||
@chat = Chat.new(chat_type: @params[:chat_type], chat_status: 'active', name: @params[:name], workspace: workspace) | ||
|
||
if @params[:chat_type] == 'p2p' | ||
create_p2p_chat | ||
else | ||
create_general_chat | ||
end | ||
end | ||
|
||
private | ||
|
||
def create_p2p_chat | ||
if @chat.save | ||
ChatMember.create!(user: @user, chat: @chat, role: 'owner') | ||
ChatMember.create!(user_id: @params[:companion_id], chat: @chat, role: 'owner') | ||
success({ text: "Chat was successfully created" }) | ||
else | ||
log_chat_errors | ||
failure({ text: "Chat can't be created. Please try again later." }) | ||
end | ||
end | ||
|
||
def create_general_chat | ||
if @chat.save | ||
puts "HELLO" | ||
new_chat_member = ChatMember.new(user: @user, chat: @chat, role: 'owner') | ||
if new_chat_member.save | ||
success({ text: "Chat was successfully created" }) | ||
else | ||
Rails.logger.error "Chat creation failed: #{new_chat_member.errors.full_messages.join(', ')}" | ||
failure({ text: "Chat can't be created. Please try again later." }) | ||
end | ||
else | ||
log_chat_errors | ||
failure({ text: "Chat can't be created. Please try again later." }) | ||
end | ||
end | ||
|
||
def log_chat_errors | ||
Rails.logger.error "Chat creation failed: #{@chat.errors.full_messages.join(', ')}" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<h1>Members in Chat: <%= @chat.name %></h1> | ||
|
||
<ul> | ||
<% @chat_members.each do |member| %> | ||
<li> | ||
<%= member.user.name %> - <%= member.role.capitalize %> | ||
<%= link_to 'Remove', workspace_chat_chat_member_path(@workspace, @chat, member), method: :delete, data: { confirm: 'Are you sure?', turbo_method: :delete }, class: 'btn btn-danger' %> | ||
</li> | ||
<% end %> | ||
</ul> | ||
|
||
<%= link_to 'Add Member', new_workspace_chat_chat_member_path(@workspace, @chat), class: 'btn btn-primary' %> | ||
|
||
<%= link_to 'Back to Chat', workspace_chat_path(@workspace, @chat) %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<h1>Add Member to <%= @chat.name %></h1> | ||
|
||
<%= form_for [@workspace, @chat, @chat_member] do |f| %> | ||
<div class="form-group"> | ||
<%= f.label :user_id, 'User ID' %> | ||
<%= f.number_field :user_id, class: 'form-control' %> | ||
</div> | ||
|
||
<%= f.submit 'Add Member', class: 'btn btn-primary' %> | ||
<% end %> | ||
|
||
<%= link_to 'Back to Chat', workspace_chat_path(@workspace, @chat) %> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<h1>Chats in <%= @workspace.name %></h1> | ||
|
||
<%= link_to 'Create New Chat', new_workspace_chat_path(@workspace), class: 'btn btn-primary' if policy(@workspace).owner? %> | ||
|
||
<ul> | ||
<% @chats.each do |chat| %> | ||
<li> | ||
<%= link_to chat.name, workspace_chat_path(@workspace, chat) %> | ||
<%= "(#{chat.chat_type.capitalize})" %> | ||
</li> | ||
<% end %> | ||
</ul> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<%= form_for [@workspace, @chat] do |f| %> | ||
<div class="form-group"> | ||
<%= f.label :name %> | ||
<%= f.text_field :name, class: 'form-control' %> | ||
</div> | ||
|
||
<div class="form-group"> | ||
<%= f.label :chat_type %> | ||
<%= f.select :chat_type, options_for_select([['Public', 'public'], ['Private', 'private'], ['P2P', 'p2p']]), {}, class: 'form-control' %> | ||
</div> | ||
|
||
<div class="form-group" id="companion-field" style="display: none;"> | ||
<%= label_tag :companion_id, 'Companion User ID' %> | ||
<%= text_field_tag :companion_id, nil, class: 'form-control' %> | ||
</div> | ||
|
||
<%= f.submit 'Create Chat', class: 'btn btn-primary' %> | ||
<% end %> | ||
|
||
<script> | ||
document.addEventListener('turbolinks:load', function() { | ||
const chatTypeField = document.querySelector('select[name="chat[chat_type]"]'); | ||
const companionField = document.getElementById('companion-field'); | ||
|
||
chatTypeField.addEventListener('change', function() { | ||
if (chatTypeField.value === 'p2p') { | ||
companionField.style.display = 'block'; | ||
} else { | ||
companionField.style.display = 'none'; | ||
} | ||
}); | ||
}); | ||
</script> |
Oops, something went wrong.