Skip to content

Commit 8b38e28

Browse files
committed
dix
1 parent 2929e30 commit 8b38e28

File tree

18 files changed

+421
-209
lines changed

18 files changed

+421
-209
lines changed

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ gem 'chartkick'
5656
gem 'groupdate'
5757
gem 'redis'
5858
gem 'geocoder'
59+
gem 'image_processing', '~> 1.2'
60+
5961

6062
group :development, :test do
6163
gem "dotenv-rails"

Gemfile.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,9 @@ GEM
178178
activesupport (>= 7)
179179
i18n (1.14.6)
180180
concurrent-ruby (~> 1.0)
181+
image_processing (1.14.0)
182+
mini_magick (>= 4.9.5, < 6)
183+
ruby-vips (>= 2.0.17, < 3)
181184
importmap-rails (2.1.0)
182185
actionpack (>= 6.0.0)
183186
activesupport (>= 6.0.0)
@@ -213,6 +216,9 @@ GEM
213216
net-smtp
214217
marcel (1.0.4)
215218
matrix (0.4.2)
219+
mini_magick (5.2.0)
220+
benchmark
221+
logger
216222
mini_mime (1.1.5)
217223
minitest (5.25.4)
218224
msgpack (1.7.5)
@@ -355,6 +361,9 @@ GEM
355361
rubocop-performance
356362
rubocop-rails
357363
ruby-progressbar (1.13.0)
364+
ruby-vips (2.2.3)
365+
ffi (~> 1.12)
366+
logger
358367
rubyzip (2.4.1)
359368
sassc (2.4.0)
360369
ffi (~> 1.9)
@@ -476,6 +485,7 @@ DEPENDENCIES
476485
font-awesome-sass (~> 6.1)
477486
geocoder
478487
groupdate
488+
image_processing (~> 1.2)
479489
importmap-rails
480490
jbuilder
481491
kamal

app/assets/stylesheets/components/_chat.scss

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@
2929
}
3030
/* Style pour le champ de saisie façon bulle iPhone */
3131
#message_input_container {
32-
margin-top: 10px;
32+
//margin-top: 10px;
33+
width: 100%;
3334
}
3435
#message_content {
36+
/* Retirez width: 100%; si vous l'aviez */
37+
flex: 1;
3538
width: 100%;
3639
padding: 12px 16px;
3740
border: 1px solid #ccc;
@@ -40,6 +43,7 @@
4043
box-sizing: border-box;
4144
outline: none;
4245
}
46+
4347
#message_content:focus {
4448
border-color: #007aff;
4549
}
@@ -63,3 +67,45 @@
6367
.chat-project .message-container.self .message-bubble {
6468
background-color: #6f42c1; /* violet */
6569
}
70+
.document-thumbnail img {
71+
border: 1px solid #ddd;
72+
border-radius: 5px;
73+
padding: 2px;
74+
background: #fff;
75+
}
76+
.message-documents {
77+
margin-top: 5px;
78+
}
79+
.msg_form {
80+
display: flex;
81+
flex-direction: row;
82+
justify-content: flex-start;
83+
align-items: center;
84+
padding: 10px;
85+
background-color: #f8f9fa;
86+
border: 1px solid #ccc;
87+
border-radius: 0 0 16px 16px;
88+
gap: 12px;
89+
}
90+
.btn-plus,
91+
.btn-mic {
92+
background: none;
93+
border: 1px solid grey;
94+
color: grey; /* Couleur texte blanche */
95+
font-size: 24px; /* Taille du + */
96+
width: 40px;
97+
height: 40px;
98+
border-radius: 50%;
99+
display: flex;
100+
align-items: center;
101+
justify-content: center;
102+
cursor: pointer;
103+
margin: 0 5px;
104+
background-color: white;
105+
}
106+
107+
/* Lorsque vous survolez le bouton, vous pouvez ajouter un léger hover */
108+
.btn-plus:hover,
109+
.btn-mic:hover {
110+
background-color: #f8f9fa;
111+
}

app/assets/stylesheets/components/_page_content.scss

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,25 @@ ul {
7373
padding: 10px 0;
7474
font-size: 14px;
7575
font-weight: 100;
76+
border: none;
7677
}
7778
.btn-lat-menu:hover {
78-
scale: 1.05;
79+
//scale: 1.07;
80+
color: #718DA9;
81+
border: none;
82+
}
83+
.btn-lat-menu.active {
84+
//transform: scale(1.07);
85+
color: #718DA9;
86+
transition: transform 0.3s ease;
87+
box-shadow: none;
88+
outline: none;
89+
border: none;
7990
}
80-
.btn:focus {
91+
a:focus {
8192
box-shadow: none;
8293
outline: none;
94+
border: none;
8395
}
8496
.nav-lateral-menu-footer {
8597
position: absolute;

app/channels/communication_channel.rb

Lines changed: 61 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,75 @@ def subscribed
77
end
88
end
99

10-
def speak(data)
11-
messageable = params[:messageable_type].constantize.find(params[:messageable_id])
10+
# Méthode de classe pour diffuser un message existant
11+
def self.broadcast_message(message)
12+
payload = {
13+
message: message.content,
14+
user: message.user.email,
15+
full_name: message.full_name,
16+
sent_at: message.created_at.strftime("%d/%m à %H:%M"),
17+
document_urls: if message.documents.attached?
18+
message.documents.map do |doc|
19+
if doc.blob.content_type.start_with?('image')
20+
{
21+
thumbnail_url: Rails.application.routes.url_helpers.url_for(
22+
doc.variant(resize_to_limit: [100, 100]).processed
23+
),
24+
original_url: Rails.application.routes.url_helpers.url_for(doc),
25+
is_image: true
26+
}
27+
else
28+
{
29+
thumbnail_url: nil,
30+
original_url: Rails.application.routes.url_helpers.url_for(doc),
31+
is_image: false
32+
}
33+
end
34+
end
35+
else
36+
[]
37+
end
38+
}
1239

13-
# Déterminer le nom complet en fonction du rôle de l'utilisateur connecté
14-
full_name =
15-
if connection.current_user.role == 'employee'
16-
employee_record = ::Employee.find_by(user_id: connection.current_user.id)
17-
employee_record ? "#{employee_record.firstname} #{employee_record.lastname}" : connection.current_user.email
18-
elsif connection.current_user.role == 'customer'
19-
client_record = ::Client.find_by(email: connection.current_user.email)
20-
client_record ? "#{client_record.firstname} #{client_record.lastname}" : connection.current_user.email
21-
elsif connection.current_user.role == 'admin'
22-
employee_record = ::Employee.find_by(email: connection.current_user.email)
23-
employee_record ? "#{employee_record.firstname} #{employee_record.lastname}" : connection.current_user.email
24-
else
25-
connection.current_user.name rescue connection.current_user.email
26-
end
40+
Rails.logger.info "CommunicationChannel.broadcast_message => Payload: #{payload.inspect}"
2741

28-
# Crée le message en incluant le full_name
42+
# Diffuser sur le canal
43+
channel_name = "#{message.messageable_type.downcase}_#{message.messageable_id}_channel"
44+
ActionCable.server.broadcast(channel_name, payload)
45+
end
46+
47+
# Méthode speak pour gérer le cas "perform('speak', { message: ... })" côté client
48+
def speak(data)
49+
messageable = params[:messageable_type].constantize.find(params[:messageable_id])
50+
full_name = determine_full_name(connection.current_user)
51+
# Créer le message (uniquement texte, par exemple)
2952
message = Message.create!(
3053
content: data['message'],
3154
user: connection.current_user,
3255
messageable: messageable,
3356
full_name: full_name
3457
)
35-
Rails.logger.info "Message sauvegardé : #{message.inspect}"
3658

37-
payload = {
38-
message: message.content,
39-
user: connection.current_user.email,
40-
full_name: message.full_name, # On utilise ici la valeur persistée
41-
sent_at: message.created_at.strftime("%d/%m à %H:%M")
42-
}
43-
ActionCable.server.broadcast("#{params[:messageable_type].downcase}_#{params[:messageable_id]}_channel", payload)
59+
Rails.logger.info "Message créé via speak => #{message.inspect}"
60+
# Diffuser via la méthode de classe
61+
self.class.broadcast_message(message)
62+
end
63+
64+
private
65+
66+
def determine_full_name(user)
67+
case user.role
68+
when 'employee'
69+
emp = ::Employee.find_by(user_id: user.id)
70+
emp ? "#{emp.firstname} #{emp.lastname}" : user.email
71+
when 'customer'
72+
cli = ::Client.find_by(email: user.email)
73+
cli ? "#{cli.firstname} #{cli.lastname}" : user.email
74+
when 'admin'
75+
emp = ::Employee.find_by(email: user.email)
76+
emp ? "#{emp.firstname} #{emp.lastname}" : user.email
77+
else
78+
user.name rescue user.email
79+
end
4480
end
4581
end
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
class MessagesController < ApplicationController
2+
before_action :authenticate_user!
3+
4+
def create
5+
messageable = params[:messageable_type].constantize.find(params[:messageable_id])
6+
7+
# Créer le message
8+
message = Message.new(
9+
content: params[:message][:content],
10+
user: current_user,
11+
messageable: messageable,
12+
full_name: determine_full_name(current_user)
13+
)
14+
15+
# Attacher les documents si présents
16+
if params[:message][:documents].present?
17+
params[:message][:documents].each do |doc|
18+
message.documents.attach(doc)
19+
end
20+
end
21+
22+
if message.save
23+
# Au lieu de diffuser ici un payload
24+
# on appelle la méthode de classe du channel
25+
CommunicationChannel.broadcast_message(message)
26+
27+
render json: { status: 'ok' }
28+
else
29+
render json: { status: 'error', errors: message.errors.full_messages }, status: :unprocessable_entity
30+
end
31+
end
32+
33+
private
34+
35+
def determine_full_name(user)
36+
if user.role == 'employee'
37+
employee_record = ::Employee.find_by(user_id: user.id)
38+
employee_record ? "#{employee_record.firstname} #{employee_record.lastname}" : user.email
39+
elsif user.role == 'customer'
40+
client_record = ::Client.find_by(email: user.email)
41+
client_record ? "#{client_record.firstname} #{client_record.lastname}" : user.email
42+
elsif user.role == 'admin'
43+
employee_record = ::Employee.find_by(email: user.email)
44+
employee_record ? "#{employee_record.firstname} #{employee_record.lastname}" : user.email
45+
else
46+
user.name rescue user.email
47+
end
48+
end
49+
end

app/javascript/application.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import "./global_expenses_chart";
1111
import "./channels/consumer";
1212
import "./channels/chat";
1313
import "./expenseCategory";
14+
import "./menu";
1415
//import "./interactiveCard";
1516

1617
import "@rails/actioncable"

0 commit comments

Comments
 (0)