feat: Use display_name instead of name of the agent (#1097)
* feat: Use display_name instead of name of the agent
This commit is contained in:
parent
f30c8943d9
commit
2b1d445003
21 changed files with 80 additions and 41 deletions
|
@ -16,6 +16,14 @@ class Api::V1::ProfilesController < Api::BaseController
|
|||
end
|
||||
|
||||
def profile_params
|
||||
params.require(:profile).permit(:email, :name, :password, :password_confirmation, :avatar, :availability)
|
||||
params.require(:profile).permit(
|
||||
:email,
|
||||
:name,
|
||||
:display_name,
|
||||
:password,
|
||||
:password_confirmation,
|
||||
:avatar,
|
||||
:availability
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -118,7 +118,12 @@ export default {
|
|||
return axios.post(urlData.url, { email });
|
||||
},
|
||||
|
||||
profileUpdate({ password, password_confirmation, ...profileAttributes }) {
|
||||
profileUpdate({
|
||||
password,
|
||||
password_confirmation,
|
||||
displayName,
|
||||
...profileAttributes
|
||||
}) {
|
||||
const formData = new FormData();
|
||||
Object.keys(profileAttributes).forEach(key => {
|
||||
const value = profileAttributes[key];
|
||||
|
@ -126,6 +131,7 @@ export default {
|
|||
formData.append(`profile[${key}]`, value);
|
||||
}
|
||||
});
|
||||
formData.append('profile[display_name]', displayName || '');
|
||||
if (password && password_confirmation) {
|
||||
formData.append('profile[password]', password);
|
||||
formData.append('profile[password_confirmation]', password_confirmation);
|
||||
|
|
|
@ -58,12 +58,12 @@
|
|||
<div class="current-user" @click.prevent="showOptions()">
|
||||
<thumbnail
|
||||
:src="currentUser.avatar_url"
|
||||
:username="currentUser.name"
|
||||
:username="currentUserAvailableName"
|
||||
:status="currentUser.availability_status"
|
||||
/>
|
||||
<div class="current-user--data">
|
||||
<h3 class="current-user--name">
|
||||
{{ currentUser.name }}
|
||||
{{ currentUserAvailableName }}
|
||||
</h3>
|
||||
<h5 class="current-user--role">
|
||||
{{ currentRole }}
|
||||
|
@ -202,6 +202,10 @@ export default {
|
|||
uiFlags: 'agents/getUIFlags',
|
||||
accountLabels: 'labels/getLabelsOnSidebar',
|
||||
}),
|
||||
currentUserAvailableName() {
|
||||
const { available_name: availableName } = this.currentUser;
|
||||
return availableName;
|
||||
},
|
||||
showChangeAccountOption() {
|
||||
if (this.globalConfig.createNewAccountFromDashboard) {
|
||||
return true;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<multiselect
|
||||
v-model="currentChat.meta.assignee"
|
||||
:options="agentList"
|
||||
label="name"
|
||||
label="available_name"
|
||||
:allow-empty="true"
|
||||
deselect-label="Remove"
|
||||
placeholder="Select Agent"
|
||||
|
@ -95,7 +95,7 @@ export default {
|
|||
return [
|
||||
{
|
||||
confirmed: true,
|
||||
name: 'None',
|
||||
available_name: 'None',
|
||||
id: 0,
|
||||
role: 'agent',
|
||||
account_id: 0,
|
||||
|
|
|
@ -95,10 +95,13 @@ export default {
|
|||
: false;
|
||||
},
|
||||
sentByMessage() {
|
||||
return this.data.message_type === 1 &&
|
||||
!this.isHovered &&
|
||||
this.data.sender !== undefined
|
||||
? { content: `Sent by: ${this.data.sender.name}`, classes: 'top' }
|
||||
const { sender } = this.data;
|
||||
|
||||
return this.data.message_type === 1 && !this.isHovered && sender
|
||||
? {
|
||||
content: `Sent by: ${sender.available_name || sender.name}`,
|
||||
classes: 'top',
|
||||
}
|
||||
: false;
|
||||
},
|
||||
wrapClass() {
|
||||
|
|
|
@ -44,9 +44,14 @@
|
|||
"LABEL": "Profile Image"
|
||||
},
|
||||
"NAME": {
|
||||
"LABEL": "Your name",
|
||||
"ERROR": "Please enter a valid name",
|
||||
"PLACEHOLDER": "Please enter your name, this would be displayed in conversations"
|
||||
"LABEL": "Your full name",
|
||||
"ERROR": "Please enter a valid full name",
|
||||
"PLACEHOLDER": "Please enter your full name"
|
||||
},
|
||||
"DISPLAY_NAME": {
|
||||
"LABEL": "Display name",
|
||||
"ERROR": "Please enter a valid display name",
|
||||
"PLACEHOLDER": "Please enter a display name, this would be displayed in conversations"
|
||||
},
|
||||
"AVAILABILITY": {
|
||||
"LABEL": "Availability",
|
||||
|
|
|
@ -291,16 +291,9 @@ export default {
|
|||
inboxId: this.currentInboxId,
|
||||
});
|
||||
const {
|
||||
data: { payload },
|
||||
data: { payload: inboxMembers },
|
||||
} = response;
|
||||
payload.forEach(el => {
|
||||
const [item] = this.agentList.filter(
|
||||
agent => agent.id === el.user_id
|
||||
);
|
||||
if (item) {
|
||||
this.selectedAgents.push(item);
|
||||
}
|
||||
});
|
||||
this.selectedAgents = inboxMembers;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,17 @@
|
|||
{{ $t('PROFILE_SETTINGS.FORM.NAME.ERROR') }}
|
||||
</span>
|
||||
</label>
|
||||
<label :class="{ error: $v.displayName.$error }">
|
||||
{{ $t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.LABEL') }}
|
||||
<input
|
||||
v-model="displayName"
|
||||
type="text"
|
||||
:placeholder="
|
||||
$t('PROFILE_SETTINGS.FORM.DISPLAY_NAME.PLACEHOLDER')
|
||||
"
|
||||
@input="$v.displayName.$touch"
|
||||
/>
|
||||
</label>
|
||||
<label :class="{ error: $v.email.$error }">
|
||||
{{ $t('PROFILE_SETTINGS.FORM.EMAIL.LABEL') }}
|
||||
<input
|
||||
|
@ -130,6 +141,7 @@ export default {
|
|||
avatarFile: '',
|
||||
avatarUrl: '',
|
||||
name: '',
|
||||
displayName: '',
|
||||
email: '',
|
||||
password: '',
|
||||
passwordConfirmation: '',
|
||||
|
@ -141,6 +153,7 @@ export default {
|
|||
name: {
|
||||
required,
|
||||
},
|
||||
displayName: {},
|
||||
email: {
|
||||
required,
|
||||
email,
|
||||
|
@ -188,6 +201,7 @@ export default {
|
|||
this.email = this.currentUser.email;
|
||||
this.avatarUrl = this.currentUser.avatar_url;
|
||||
this.availability = this.currentUser.availability_status;
|
||||
this.displayName = this.currentUser.display_name;
|
||||
},
|
||||
async updateUser() {
|
||||
this.$v.$touch();
|
||||
|
@ -203,6 +217,7 @@ export default {
|
|||
email: this.email,
|
||||
avatar: this.avatarFile,
|
||||
password: this.password,
|
||||
displayName: this.displayName,
|
||||
availability: this.availability,
|
||||
password_confirmation: this.passwordConfirmation,
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@ const getters = {
|
|||
getMineChats(_state) {
|
||||
const currentUserID = authAPI.getCurrentUser().id;
|
||||
return _state.allConversations.filter(chat =>
|
||||
chat.meta.assignee === null
|
||||
!chat.meta.assignee
|
||||
? false
|
||||
: chat.status === _state.chatStatusFilter &&
|
||||
chat.meta.assignee.id === currentUserID
|
||||
|
@ -29,8 +29,7 @@ const getters = {
|
|||
},
|
||||
getUnAssignedChats(_state) {
|
||||
return _state.allConversations.filter(
|
||||
chat =>
|
||||
chat.meta.assignee === null && chat.status === _state.chatStatusFilter
|
||||
chat => !chat.meta.assignee && chat.status === _state.chatStatusFilter
|
||||
);
|
||||
},
|
||||
getAllStatusChats(_state) {
|
||||
|
|
|
@ -56,7 +56,7 @@ class ConversationReplyMailer < ApplicationMailer
|
|||
|
||||
def reply_email
|
||||
if inbound_email_enabled?
|
||||
"#{@agent.name} <reply+#{@conversation.uuid}@#{current_domain}>"
|
||||
"#{@agent.available_name} <reply+#{@conversation.uuid}@#{current_domain}>"
|
||||
else
|
||||
@agent&.email
|
||||
end
|
||||
|
@ -64,9 +64,9 @@ class ConversationReplyMailer < ApplicationMailer
|
|||
|
||||
def from_email
|
||||
if inbound_email_enabled?
|
||||
"#{@agent.name} <#{account_support_email}>"
|
||||
"#{@agent.available_name} <#{account_support_email}>"
|
||||
else
|
||||
"#{@agent.name} <#{ENV.fetch('MAILER_SENDER_EMAIL', 'accounts@chatwoot.com')}>"
|
||||
"#{@agent.available_name} <#{ENV.fetch('MAILER_SENDER_EMAIL', 'accounts@chatwoot.com')}>"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ class Conversation < ApplicationRecord
|
|||
def create_activity
|
||||
return unless Current.user
|
||||
|
||||
user_name = Current.user&.name
|
||||
user_name = Current.user&.available_name
|
||||
|
||||
create_status_change_message(user_name) if saved_change_to_status?
|
||||
create_assignee_change(user_name) if saved_change_to_assignee_id?
|
||||
|
@ -208,7 +208,7 @@ class Conversation < ApplicationRecord
|
|||
end
|
||||
|
||||
def create_assignee_change(user_name)
|
||||
params = { assignee_name: assignee&.name, user_name: user_name }.compact
|
||||
params = { assignee_name: assignee&.available_name, user_name: user_name }.compact
|
||||
key = assignee_id ? 'assigned' : 'removed'
|
||||
content = I18n.t("conversations.activity.assignee.#{key}", **params)
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ class User < ApplicationRecord
|
|||
account_users.find_by(account_id: Current.account.id) if Current.account
|
||||
end
|
||||
|
||||
def display_name
|
||||
def available_name
|
||||
self[:display_name].presence || name
|
||||
end
|
||||
|
||||
|
@ -134,6 +134,7 @@ class User < ApplicationRecord
|
|||
{
|
||||
id: id,
|
||||
name: name,
|
||||
available_name: available_name,
|
||||
avatar_url: avatar_url,
|
||||
type: 'user',
|
||||
availability_status: availability_status
|
||||
|
|
|
@ -25,7 +25,7 @@ class Conversations::EventDataPresenter < SimpleDelegator
|
|||
end
|
||||
|
||||
def push_meta
|
||||
{ sender: contact.push_event_data, assignee: assignee }
|
||||
{ sender: contact.push_event_data, assignee: assignee&.push_event_data }
|
||||
end
|
||||
|
||||
def push_timestamps
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
json.payload do
|
||||
json.array! @agents do |agent|
|
||||
json.user_id agent.id
|
||||
json.name agent.name
|
||||
json.partial! 'api/v1/models/user.json.jbuilder', resource: agent
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,11 @@ json.meta do
|
|||
json.partial! 'api/v1/models/contact.json.jbuilder', resource: conversation.contact
|
||||
end
|
||||
json.channel conversation.inbox.try(:channel_type)
|
||||
json.assignee conversation.assignee
|
||||
if conversation.assignee
|
||||
json.assignee do
|
||||
json.partial! 'api/v1/models/user.json.jbuilder', resource: conversation.assignee
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
json.id conversation.display_id
|
||||
|
|
|
@ -2,6 +2,7 @@ json.account_id resource.account.id
|
|||
json.availability_status resource.availability_status
|
||||
json.confirmed resource.confirmed?
|
||||
json.email resource.email
|
||||
json.available_name resource.available_name
|
||||
json.id resource.id
|
||||
json.name resource.name
|
||||
json.role resource.role
|
||||
|
|
|
@ -3,6 +3,7 @@ json.provider resource.provider
|
|||
json.uid resource.uid
|
||||
json.name resource.name
|
||||
json.display_name resource.display_name
|
||||
json.available_name resource.available_name
|
||||
json.email resource.email
|
||||
json.account_id resource.active_account_user&.account_id
|
||||
json.pubsub_token resource.pubsub_token
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
json.payload do
|
||||
json.array! @inbox_members do |inbox_member|
|
||||
json.id inbox_member.user.id
|
||||
json.name inbox_member.user.name
|
||||
json.name inbox_member.user.available_name
|
||||
json.avatar_url inbox_member.user.avatar_url
|
||||
json.availability_status inbox_member.user.availability_status
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<% @messages.each do |message| %>
|
||||
<tr>
|
||||
<td>
|
||||
<b><%= message.incoming? ? 'You' : message.sender.name %></b>
|
||||
<b><%= message.incoming? ? 'You' : message.sender.available_name %></b>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -108,13 +108,13 @@ RSpec.describe ConversationReplyMailer, type: :mailer do
|
|||
|
||||
it 'sets reply to email to be based on the domain' do
|
||||
reply_to_email = "reply+#{message.conversation.uuid}@#{conversation.account.domain}"
|
||||
reply_to = "#{agent.name} <#{reply_to_email}>"
|
||||
reply_to = "#{agent.available_name} <#{reply_to_email}>"
|
||||
expect(mail['REPLY-TO'].value).to eq(reply_to)
|
||||
expect(mail.reply_to).to eq([reply_to_email])
|
||||
end
|
||||
|
||||
it 'sets the from email to be the support email' do
|
||||
expect(mail['FROM'].value).to eq("#{agent.name} <#{conversation.account.support_email}>")
|
||||
expect(mail['FROM'].value).to eq("#{agent.available_name} <#{conversation.account.support_email}>")
|
||||
expect(mail.from).to eq([conversation.account.support_email])
|
||||
end
|
||||
|
||||
|
|
|
@ -88,8 +88,8 @@ RSpec.describe Conversation, type: :model do
|
|||
|
||||
it 'creates conversation activities' do
|
||||
# create_activity
|
||||
expect(conversation.messages.pluck(:content)).to include("Conversation was marked resolved by #{old_assignee.name}")
|
||||
expect(conversation.messages.pluck(:content)).to include("Assigned to #{new_assignee.name} by #{old_assignee.name}")
|
||||
expect(conversation.messages.pluck(:content)).to include("Conversation was marked resolved by #{old_assignee.available_name}")
|
||||
expect(conversation.messages.pluck(:content)).to include("Assigned to #{new_assignee.available_name} by #{old_assignee.available_name}")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue