feat: show email subject in conversation search results (#10843)

# Pull Request Template

## Description

This addresses #10842. It exposes `additional_attributes` in the
conversations search endpoint, uses it in
`SearchResultConversationsList` to pass
`conversation.additional_attributes?.mail_subject` down to
`SearchResultConversationItem`, which in turn displays it.

Fixes #10842

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

I have tested this locally by searching for conversations. See this
screenshot where I searched for "noreply":
![Screenshot from 2025-02-05
11-04-54](https://github.com/user-attachments/assets/689e3e99-c20b-48a7-9c3e-35d45ffeafc1)

I would love to add automated tests but I’m not sure how to do that.

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
This commit is contained in:
Baptiste Fontaine
2025-02-06 06:08:57 +01:00
committed by GitHub
parent d5ecbba71f
commit 2a365bf19e
4 changed files with 50 additions and 17 deletions

View File

@@ -24,6 +24,7 @@
"READ_MORE": "Read more", "READ_MORE": "Read more",
"WROTE": "wrote:", "WROTE": "wrote:",
"FROM": "from", "FROM": "from",
"EMAIL": "email" "EMAIL": "email",
"EMAIL_SUBJECT": "subject"
} }
} }

View File

@@ -35,6 +35,10 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
emailSubject: {
type: String,
default: '',
},
}); });
const navigateTo = computed(() => { const navigateTo = computed(() => {
@@ -49,6 +53,28 @@ const navigateTo = computed(() => {
}); });
const createdAtTime = dynamicTime(props.createdAt); const createdAtTime = dynamicTime(props.createdAt);
const infoItems = computed(() => [
{
label: 'SEARCH.FROM',
value: props.name,
show: !!props.name,
},
{
label: 'SEARCH.EMAIL',
value: props.email,
show: !!props.email,
},
{
label: 'SEARCH.EMAIL_SUBJECT',
value: props.emailSubject,
show: !!props.emailSubject,
},
]);
const visibleInfoItems = computed(() =>
infoItems.value.filter(item => item.show)
);
</script> </script>
<template> <template>
@@ -86,26 +112,18 @@ const createdAtTime = dynamicTime(props.createdAt);
{{ createdAtTime }} {{ createdAtTime }}
</span> </span>
</div> </div>
<div class="flex gap-2"> <div class="flex flex-wrap gap-x-2 gap-y-1.5">
<h5 <h5
v-if="name" v-for="item in visibleInfoItems"
class="m-0 text-sm min-w-0 truncate text-n-slate-12 dark:text-n-slate-12" :key="item.label"
> class="m-0 text-sm min-w-0 text-n-slate-12 dark:text-n-slate-12 truncate"
<span class="text-xs font-norma text-n-slate-11 dark:text-n-slate-11">
{{ $t('SEARCH.FROM') }}:
</span>
{{ name }}
</h5>
<h5
v-if="email"
class="m-0 overflow-hidden text-sm text-n-slate-12 dark:text-n-slate-12 truncate"
> >
<span <span
class="text-xs font-normal text-n-slate-11 dark:text-n-slate-11" class="text-xs font-normal text-n-slate-11 dark:text-n-slate-11"
> >
{{ $t('SEARCH.EMAIL') }}: {{ $t(item.label) }}:
</span> </span>
{{ email }} {{ item.value }}
</h5> </h5>
</div> </div>
<slot /> <slot />

View File

@@ -1,9 +1,10 @@
<script setup> <script setup>
import { defineProps, computed } from 'vue';
import { useMapGetter } from 'dashboard/composables/store.js'; import { useMapGetter } from 'dashboard/composables/store.js';
import SearchResultSection from './SearchResultSection.vue'; import SearchResultSection from './SearchResultSection.vue';
import SearchResultConversationItem from './SearchResultConversationItem.vue'; import SearchResultConversationItem from './SearchResultConversationItem.vue';
defineProps({ const props = defineProps({
conversations: { conversations: {
type: Array, type: Array,
default: () => [], default: () => [],
@@ -23,6 +24,13 @@ defineProps({
}); });
const accountId = useMapGetter('getCurrentAccountId'); const accountId = useMapGetter('getCurrentAccountId');
const conversationsWithSubject = computed(() => {
return props.conversations.map(conversation => ({
...conversation,
mail_subject: conversation.additional_attributes?.mail_subject || '',
}));
});
</script> </script>
<template> <template>
@@ -34,7 +42,10 @@ const accountId = useMapGetter('getCurrentAccountId');
:is-fetching="isFetching" :is-fetching="isFetching"
> >
<ul v-if="conversations.length" class="space-y-1.5 list-none"> <ul v-if="conversations.length" class="space-y-1.5 list-none">
<li v-for="conversation in conversations" :key="conversation.id"> <li
v-for="conversation in conversationsWithSubject"
:key="conversation.id"
>
<SearchResultConversationItem <SearchResultConversationItem
:id="conversation.id" :id="conversation.id"
:name="conversation.contact.name" :name="conversation.contact.name"
@@ -42,6 +53,7 @@ const accountId = useMapGetter('getCurrentAccountId');
:account-id="accountId" :account-id="accountId"
:inbox="conversation.inbox" :inbox="conversation.inbox"
:created-at="conversation.created_at" :created-at="conversation.created_at"
:email-subject="conversation.mail_subject"
/> />
</li> </li>
</ul> </ul>

View File

@@ -16,6 +16,8 @@ json.payload do
json.agent do json.agent do
json.partial! 'agent', formats: [:json], agent: conversation.assignee if conversation.try(:assignee).present? json.partial! 'agent', formats: [:json], agent: conversation.assignee if conversation.try(:assignee).present?
end end
json.additional_attributes conversation.additional_attributes
end end
end end
end end