Skip to content

Commit

Permalink
Merge branch 'EN-7825-variables-in-generic-message'
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolas-entourage committed Dec 16, 2024
2 parents 131000d + ec2e559 commit dc9de20
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 20 deletions.
4 changes: 0 additions & 4 deletions app/helpers/users_helper.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
module UsersHelper
def day_name(day_number)
I18n.t("date.day_names")[day_number.to_i % 7]
end

def users_for_select users
users.map do |user|
["#{user.full_name} (#{user.email})", user.id]
Expand Down
22 changes: 22 additions & 0 deletions app/models/chat_message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,28 @@ def path key
end
end

class << self
def interpolate message:, user:, author: nil
first_name = UserPresenter.format_first_name(user.first_name)

if message.match?(/\{\{\s*interlocutor\s*\}\}/)
author ||= ModerationServices.moderation_area_for_user_with_default(user)&.interlocutor_for_user(user)
end

message
.gsub(/\{\{\s*first_name\s*\}\}/, first_name.to_s)
.gsub(/\{\{\s*email\s*\}\}/, user.email.to_s)
.gsub(/\{\{\s*phone\s*\}\}/, user.phone.to_s)
.gsub(/\{\{\s*city\s*\}\}/, user.city.to_s)
.gsub(/\{\{\s*uuid\s*\}\}/, user.uuid.to_s)
.gsub(/\{\{\s*default_neighborhood\s*\}\}/, user.default_neighborhood&.name.to_s)
.gsub(/\{\{\s*interests\s*\}\}/, user.interest_i18n.sort.join(', '))
.gsub(/\{\{\s*involvements\s*\}\}/, user.involvement_i18n.sort.join(', '))
.gsub(/\{\{\s*availability\s*\}\}/, user.availability_formatted.to_s)
.gsub(/\{\{\s*interlocutor\s*\}\}/, author&.first_name.to_s)
end
end

def active?
status.to_sym == :active
end
Expand Down
9 changes: 9 additions & 0 deletions app/models/concerns/availabilable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,13 @@ def validate_availability_format
end
end

def availability_formatted
availability.map do |day_number, hours|
"#{Availabilable.day_name(day_number)} : #{hours.join(', ')}"
end.join("\n")
end

def self.day_name day_number
I18n.t("date.day_names")[day_number.to_i % 7]
end
end
7 changes: 1 addition & 6 deletions app/models/conversation_message_broadcast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ def find_with_cast id
end

def content_for_user user
content
.gsub("{{first_name}}", user.first_name.to_s)
.gsub("{{email}}", user.email.to_s)
.gsub("{{phone}}", user.phone.to_s)
.gsub("{{city}}", user.city.to_s)
.gsub("{{uuid}}", user.uuid.to_s)
ChatMessage.interpolate(message: content, user: user)
end

def recipients
Expand Down
5 changes: 1 addition & 4 deletions app/services/onboarding/chat_messages_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,8 @@ def self.deliver_welcome_message

next if messages.empty?

first_name = UserPresenter.format_first_name user.first_name

messages.each do |message|
message = message.gsub(/\{\{\s*first_name\s*\}\}/, first_name)
message = message.gsub(/\{\{\s*interlocutor\s*\}\}/, author.first_name) if author.present?
message = ChatMessage.interpolate(message: message, user: user, author: author)

builder = ChatServices::ChatMessageBuilder.new(
user: author,
Expand Down
8 changes: 4 additions & 4 deletions app/views/admin/moderation_areas/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
pour le profil <%= t 'community.entourage.goals_compact.offer_help' %>
<% end %>
<%= f.text_area :welcome_message_1_offer_help, rows: 10, class: "form-control" %>
Utilisez <code>{{first_name}}</code> pour insérer le prénom du destinataire.
<%= render partial: 'common/interpolation_specifications' %>
</div>
</div>

Expand All @@ -76,7 +76,7 @@
si <%= t 'community.entourage.goals_compact.ask_for_help' %>
<% end %>
<%= f.text_area :welcome_message_1_ask_for_help, rows: 10, class: "form-control" %>
Utilisez <code>{{first_name}}</code> pour insérer le prénom du destinataire.
<%= render partial: 'common/interpolation_specifications' %>
</div>
</div>

Expand All @@ -87,7 +87,7 @@
pour le profil <%= t 'community.entourage.goals_compact.organization' %>
<% end %>
<%= f.text_area :welcome_message_1_organization, rows: 10, class: "form-control" %>
Utilisez <code>{{first_name}}</code> pour insérer le prénom du destinataire.
<%= render partial: 'common/interpolation_specifications' %>
</div>
</div>

Expand All @@ -98,7 +98,7 @@
pour le profil <%= t 'community.entourage.goals_compact.goal_not_known' %>
<% end %>
<%= f.text_area :welcome_message_1_goal_not_known, rows: 10, class: "form-control" %>
Utilisez <code>{{first_name}}</code> pour insérer le prénom du destinataire.
<%= render partial: 'common/interpolation_specifications' %>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/user_message_broadcasts/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@

<div class="form-group">
<%= f.label :content %>
<p>Vous pouvez utiliser les variables : {{first_name}}, {{email}}, {{phone}}, {{city}}, {{uuid}}</p>
<%= f.text_area :content, class: "form-control", rows: 5, required: true %>
<p><%= render partial: 'common/interpolation_specifications' %></p>
</div>

<% if @user_message_broadcast.draft? %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/users/_onboarding_fields.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ul>
<% @user.availability.each do |day, slots| %>
<li>
<strong><%= day_name(day) %>:</strong>
<strong><%= Availabilable.day_name(day) %>:</strong>
<%= slots.join(', ') %>
</li>
<% end %>
Expand Down
13 changes: 13 additions & 0 deletions app/views/common/_interpolation_specifications.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Les variables suivantes sont disponibles :
<ul>
<li><code>{{first_name}}</code> : <i>prénom du destinataire</i></li>
<li><code>{{email}}</code> : <i>email du destinataire</i></li>
<li><code>{{phone}}</code> téléphone du destinataire</li>
<li><code>{{city}}</code> : <i>ville du destinataire</i></li>
<li><code>{{uuid}}</code> : <i>uuid du destinataire</i></li>
<li><code>{{default_neighborhood}}</code> : <i>nom du groupe de voisins par défaut du destinataire</i></li>
<li><code>{{interests}}</code> : <i>centres d'intérêt du destinataire</i></li>
<li><code>{{involvements}}</code> : <i>envies d'agir du destinataire</i></li>
<li><code>{{availability}}</code> : <i>disponibilités du destinataire</i></li>
<li><code>{{interlocutor}}</code> : <i>prénom du <b>modérateur</b> lié au destinataire</i></li>
</ul>
173 changes: 173 additions & 0 deletions spec/models/chat_message_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,179 @@
end
end

describe '.interpolate' do
let(:user) { create(:public_user,
first_name: 'John',
email: 'john.doe@example.com',
phone: '+33612345678',
uuid: '123e4567-e89b-12d3-a456-426614174000',
interest_list: 'jeux, cuisine',
involvement_list: 'outings, resources',
availability: {
"1" => ["09:00-12:00", "14:00-18:00"],
"2" => ["10:00-12:00"]
},
address: address,
addresses: [address]
)}

let(:other_user) { create(:public_user) }
let(:author) { create(:public_user, first_name: 'Alice') }

let(:neighborhood) { create(:neighborhood, name: "Groupe de Paris") }
let(:address) { create :address, city: "Paris" }

before do
allow(user).to receive(:default_neighborhood).and_return(neighborhood)
allow(UserPresenter).to receive(:format_first_name).with('John').and_return('John')
end

it 'replaces placeholders in the message' do
message = <<~TEXT
Hello {{ first_name }},
Your email is {{ email }}, and your phone number is {{ phone }}.
You live in {{ city }} and your ID is {{ uuid }}.
Default neighborhood: {{ default_neighborhood }}.
Your interests: {{ interests }}.
Your involvements: {{ involvements }}.
Availability: {{ availability }}.
Interlocutor: {{ interlocutor }}.
TEXT

expected_message = <<~TEXT
Hello John,
Your email is john.doe@example.com, and your phone number is +33612345678.
You live in Paris and your ID is 123e4567-e89b-12d3-a456-426614174000.
Default neighborhood: Groupe de Paris.
Your interests: Cuisine, Jeux.
Your involvements: Apprendre avec des contenus pédagogiques, Participer à des événements de convivialité.
Availability: lundi : 09:00-12:00, 14:00-18:00
mardi : 10:00-12:00.
Interlocutor: Alice.
TEXT

result = ChatMessage.interpolate(message: message, user: user, author: author)
expect(result.strip).to eq(expected_message.strip)
end

it 'replaces placeholders in the message when user has little information' do
message = <<~TEXT
Hello {{ first_name }},
Your email is {{ email }}, and your phone number is {{ phone }}.
You live in {{ city }} and your ID is {{ uuid }}.
Default neighborhood: {{ default_neighborhood }}.
Your interests: {{ interests }}.
Your involvements: {{ involvements }}.
Availability: {{ availability }}.
Interlocutor: {{ interlocutor }}.
TEXT

expected_message = <<~TEXT
Hello John,
Your email is #{other_user.email}, and your phone number is #{other_user.phone}.
You live in and your ID is #{other_user.uuid}.
Default neighborhood: .
Your interests: .
Your involvements: .
Availability: .
Interlocutor: Alice.
TEXT

result = ChatMessage.interpolate(message: message, user: other_user, author: author)
expect(result.strip).to eq(expected_message.strip)
end

it 'handles missing placeholders gracefully when author is nil' do
message = "Hello {{ first_name }}, your interlocutor is {{ interlocutor }}."
expected_message = "Hello John, your interlocutor is ."

allow(ModerationServices).to receive(:moderation_area_for_user_with_default)
.with(user)
.and_return(double(interlocutor_for_user: nil))

result = ChatMessage.interpolate(message: message, user: user, author: nil)
expect(result).to eq(expected_message)
end

it 'handles missing placeholders in the message' do
message = "This message has no placeholders."
expected_message = "This message has no placeholders."

result = ChatMessage.interpolate(message: message, user: user)
expect(result).to eq(expected_message)
end

context 'when the message includes {{interlocutor}}' do
it 'handles a message with multiple placeholders including {{interlocutor}} with no moderation area' do
allow(ModerationServices).to receive(:moderation_area_for_user_with_default)
.with(user)
.and_return(nil)

message = "Hello {{ first_name }}, your interlocutor is {{ interlocutor }}."
expected_message = "Hello John, your interlocutor is ."

result = ChatMessage.interpolate(message: message, user: user, author: nil)
expect(result).to eq(expected_message)
end

it 'handles a message with multiple placeholders including {{interlocutor}} with no moderator' do
allow(ModerationServices).to receive(:moderation_area_for_user_with_default)
.with(user)
.and_return(double(interlocutor_for_user: nil))

message = "Hello {{ first_name }}, your interlocutor is {{ interlocutor }}."
expected_message = "Hello John, your interlocutor is ."

result = ChatMessage.interpolate(message: message, user: user, author: nil)
expect(result).to eq(expected_message)
end

it 'replaces {{interlocutor}} when an author is dynamically determined' do
allow(ModerationServices).to receive(:moderation_area_for_user_with_default)
.with(user)
.and_return(double(interlocutor_for_user: author))

message = "Your interlocutor is {{ interlocutor }}."
expected_message = "Your interlocutor is Alice."

result = ChatMessage.interpolate(message: message, user: user, author: nil)
expect(result).to eq(expected_message)
end

it 'replaces {{interlocutor}} when author is provided manually' do
message = "Your interlocutor is {{ interlocutor }}."
expected_message = "Your interlocutor is Alice."

result = ChatMessage.interpolate(message: message, user: user, author: author)
expect(result).to eq(expected_message)
end

it 'leaves {{interlocutor}} blank when no author and no default interlocutor are available' do
allow(ModerationServices).to receive(:moderation_area_for_user_with_default)
.with(user)
.and_return(double(interlocutor_for_user: nil))

message = "Your interlocutor is {{ interlocutor }}."
expected_message = "Your interlocutor is ."

result = ChatMessage.interpolate(message: message, user: user, author: nil)
expect(result).to eq(expected_message)
end

it 'handles a message with multiple placeholders including {{interlocutor}}' do
allow(ModerationServices).to receive(:moderation_area_for_user_with_default)
.with(user)
.and_return(double(interlocutor_for_user: author))

message = "Hello {{ first_name }}, your interlocutor is {{ interlocutor }}."
expected_message = "Hello John, your interlocutor is Alice."

result = ChatMessage.interpolate(message: message, user: user, author: nil)
expect(result).to eq(expected_message)
end
end
end

describe "custom type" do
let(:entourage) { create :entourage }
let!(:group) { create :entourage, uuid_v2: "uuid-123" }
Expand Down

0 comments on commit dc9de20

Please sign in to comment.