+
diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/DisplayPropertiesModal.vue b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/DisplayPropertiesModal.vue
new file mode 100644
index 000000000..27bd44fc3
--- /dev/null
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsHeader/components/DisplayPropertiesModal.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
diff --git a/app/javascript/dashboard/components-next/Contacts/Pages/ContactsList.vue b/app/javascript/dashboard/components-next/Contacts/Pages/ContactsList.vue
index 54a200eab..b9c97a81b 100644
--- a/app/javascript/dashboard/components-next/Contacts/Pages/ContactsList.vue
+++ b/app/javascript/dashboard/components-next/Contacts/Pages/ContactsList.vue
@@ -30,7 +30,6 @@ const route = useRoute();
const uiFlags = useMapGetter('contacts/getUIFlags');
const isUpdating = computed(() => uiFlags.value.isUpdating);
const expandedCardId = ref(null);
-const hoveredAvatarId = ref(null);
const selectedContactId = ref(null);
const composeConversationRef = ref(null);
const confirmDeleteContactDialogRef = ref(null);
@@ -88,18 +87,10 @@ const toggleExpanded = async id => {
const isSelected = id => selectedIdsSet.value.has(id);
-const shouldShowSelection = id => {
- return hoveredAvatarId.value === id || isSelected(id);
-};
-
const handleSelect = (id, value) => {
emit('toggleContact', { id, value });
};
-const handleAvatarHover = (id, isHovered) => {
- hoveredAvatarId.value = isHovered ? id : null;
-};
-
const handleSendMessage = id => {
selectedContactId.value = String(id);
composeConversationRef.value?.toggle();
@@ -124,17 +115,16 @@ const handleDeleteContact = id => {
:thumbnail="contact.thumbnail"
:phone-number="contact.phoneNumber"
:additional-attributes="contact.additionalAttributes"
+ :custom-attributes="contact.customAttributes"
:availability-status="contact.availabilityStatus"
:is-expanded="expandedCardId === contact.id"
:is-updating="isUpdating"
- :selectable="shouldShowSelection(contact.id)"
:is-selected="isSelected(contact.id)"
:labels="contact.labels || []"
@toggle="toggleExpanded(contact.id)"
@update-contact="updateContact"
@show-contact="onClickViewDetails"
@select="value => handleSelect(contact.id, value)"
- @avatar-hover="value => handleAvatarHover(contact.id, value)"
@send-message="handleSendMessage"
@delete-contact="handleDeleteContact"
/>
diff --git a/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardStatusIcon.vue b/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardStatusIcon.vue
index d08d2e5ea..c16372ac5 100644
--- a/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardStatusIcon.vue
+++ b/app/javascript/dashboard/components-next/Conversation/ConversationCard/CardStatusIcon.vue
@@ -37,6 +37,6 @@ const iconName = computed(() => {
delay: { show: 500, hide: 0 },
}"
:icon="iconName"
- class="size-4"
+ class="size-4 flex-shrink-0"
/>
diff --git a/app/javascript/dashboard/components-next/captain/assistant/BulkSelectBar.vue b/app/javascript/dashboard/components-next/captain/assistant/BulkSelectBar.vue
index 7466c3d0b..c6ded1d8d 100644
--- a/app/javascript/dashboard/components-next/captain/assistant/BulkSelectBar.vue
+++ b/app/javascript/dashboard/components-next/captain/assistant/BulkSelectBar.vue
@@ -58,28 +58,37 @@ const bulkCheckboxState = computed({
const animationClasses = computed(() => {
if (props.animationDirection === 'vertical') {
return {
- enterFrom: 'opacity-0 transform -translate-y-4',
- enterTo: 'opacity-100 transform translate-y-0',
+ enterActive: 'transition-all duration-200 ease-out origin-bottom',
+ enterFrom: 'opacity-0 scale-95 translate-y-2',
+ enterTo: 'opacity-100 scale-100 translate-y-0',
+ leaveActive: 'transition-all duration-150 ease-in origin-bottom',
+ leaveFrom: 'opacity-100 scale-100 translate-y-0',
+ leaveTo: 'opacity-0 scale-95 translate-y-2',
};
}
return {
- enterFrom: 'opacity-0 transform ltr:-translate-x-4 rtl:translate-x-4',
- enterTo: 'opacity-100 transform translate-x-0',
+ enterActive: 'transition-all duration-300 ease-out',
+ enterFrom: 'opacity-0 ltr:-translate-x-4 rtl:translate-x-4',
+ enterTo: 'opacity-100 translate-x-0',
+ leaveActive: 'transition-all duration-200 ease-in',
+ leaveFrom: 'opacity-100 translate-x-0',
+ leaveTo: 'opacity-0 ltr:-translate-x-4 rtl:translate-x-4',
};
});
-
@@ -116,5 +125,5 @@ const animationClasses = computed(() => {
-
+
diff --git a/app/javascript/dashboard/components/ChatList.vue b/app/javascript/dashboard/components/ChatList.vue
index 769d39830..2359e1f4a 100644
--- a/app/javascript/dashboard/components/ChatList.vue
+++ b/app/javascript/dashboard/components/ChatList.vue
@@ -466,7 +466,7 @@ watch(conversationFilters, (newVal, oldVal) => {
diff --git a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkAgentActions.vue b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkAgentActions.vue
index 6d8ce34fa..519a77d76 100644
--- a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkAgentActions.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkAgentActions.vue
@@ -113,10 +113,10 @@ const handleToggleDropdown = () => {
@click="handleToggleDropdown"
/>
@@ -130,7 +130,7 @@ const handleToggleDropdown = () => {
:is-loading="isLoading"
show-search
:search-placeholder="t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')"
- class="ltr:-right-10 rtl:-left-10 ltr:2xl:right-0 rtl:2xl:left-0 top-8 w-60 max-h-80 overflow-y-auto"
+ class="ltr:-right-10 rtl:-left-10 ltr:2xl:right-0 rtl:2xl:left-0 bottom-8 w-60 max-h-80 overflow-y-auto"
@action="handleSelectAgent"
>
diff --git a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkLabelActions.vue b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkLabelActions.vue
index 238227c76..afbf1c82e 100644
--- a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkLabelActions.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkLabelActions.vue
@@ -85,7 +85,7 @@ const handleAssign = () => {
ghost
:class="{
'bg-n-alpha-2': showDropdown,
- '[&>span:nth-child(2)]:hidden sm:[&>span:nth-child(2)]:inline w-fit':
+ '[&>span:nth-child(2)]:hidden md:[&>span:nth-child(2)]:inline w-fit':
isTypeContact,
}"
:disabled="disabled"
@@ -93,10 +93,10 @@ const handleAssign = () => {
@click="toggleDropdown()"
/>
@@ -109,11 +109,11 @@ const handleAssign = () => {
:menu-items="labelMenuItems"
show-search
:search-placeholder="t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')"
- class="top-8 w-60 max-h-80 overflow-y-auto"
+ class="bottom-8 w-60 max-h-80 overflow-y-auto"
:class="{
'ltr:-right-[6.5rem] rtl:-left-[6.5rem] ltr:2xl:right-0 rtl:2xl:left-0':
!isTypeContact,
- 'ltr:right-0 rtl:left-0 mt-1': isTypeContact,
+ 'ltr:right-0 rtl:left-0 mb-1': isTypeContact,
}"
@action="item => toggleLabelSelection(item.value)"
>
@@ -138,7 +138,7 @@ const handleAssign = () => {
>
{
@click="toggleDropdown()"
/>
@@ -99,7 +99,7 @@ onMounted(() => {
:menu-items="teamMenuItems"
show-search
:search-placeholder="t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')"
- class="ltr:-right-2 rtl:-left-2 top-8 w-60 max-h-80 overflow-y-auto"
+ class="ltr:-right-2 rtl:-left-2 bottom-8 w-60 max-h-80 overflow-y-auto"
@action="handleSelectTeam"
>
diff --git a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkUpdateActions.vue b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkUpdateActions.vue
index bd9f8ee49..042a304df 100644
--- a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkUpdateActions.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/BulkUpdateActions.vue
@@ -87,10 +87,10 @@ const handleUpdate = item => {
@click="toggleDropdown()"
/>
@@ -101,7 +101,7 @@ const handleUpdate = item => {
{ ignore: [containerRef] },
]"
:menu-items="updateMenuItems"
- class="ltr:-right-[4.5rem] rtl:-left-[4.5rem] ltr:2xl:right-0 rtl:2xl:left-0 top-8 w-36"
+ class="ltr:-right-[4.5rem] rtl:-left-[4.5rem] ltr:2xl:right-0 rtl:2xl:left-0 bottom-8 w-36"
@action="handleUpdate"
/>
diff --git a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/Index.vue b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/Index.vue
index 2f889ca1e..1a4ccde0f 100644
--- a/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/Index.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/conversationBulkActions/Index.vue
@@ -106,68 +106,78 @@ onUnmounted(() => {
-
-
- {{ $t('BULK_ACTION.ALL_CONVERSATIONS_SELECTED_ALERT') }}
-
-
-
-
-
+
diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json
index 2669c96ec..7e5fb2790 100644
--- a/app/javascript/dashboard/i18n/locale/en/contact.json
+++ b/app/javascript/dashboard/i18n/locale/en/contact.json
@@ -388,6 +388,17 @@
"PAGINATION_FOOTER": {
"SHOWING": "Showing {startItem} - {endItem} of {totalItems} contact | Showing {startItem} - {endItem} of {totalItems} contacts"
},
+ "DISPLAY_PROPERTIES": {
+ "TITLE": "Display Properties",
+ "DESCRIPTION": "Select up to three contact attributes to display.",
+ "SELECTED_ATTRIBUTES": "Selected attributes",
+ "OTHER_ATTRIBUTES": "Other attributes",
+ "NO_ATTRIBUTES": "No contact attributes available",
+ "CANCEL": "Cancel",
+ "SAVE": "Save",
+ "YES": "Yes",
+ "NO": "No"
+ },
"FILTER": {
"NAME": "Name",
"EMAIL": "Email",
@@ -471,6 +482,14 @@
"LABELS": {
"ADD_BUTTON": "Add Labels"
},
+ "QUICK_OVERVIEW": {
+ "TITLE": "Quick Overview",
+ "BASIC_INFO": "Basic Info",
+ "LATEST_NOTE": "Note",
+ "LATEST_CONVERSATION": "Message",
+ "NO_NOTES": "No notes available",
+ "NO_CONVERSATIONS": "No previous conversations"
+ },
"SOCIAL_MEDIA": {
"TITLE": "Edit social links",
"FORM": {
@@ -608,7 +627,7 @@
"DESCRIPTION": "Select the labels you want to add to the selected contacts.",
"NO_LABELS_FOUND": "No labels available yet.",
"SELECTED_COUNT": "{count} selected",
- "CLEAR_SELECTION": "Clear selection",
+ "CLEAR_SELECTION": "Clear",
"SELECT_ALL": "Select all ({count})",
"DELETE_CONTACTS": "Delete",
"DELETE_SUCCESS": "Contacts deleted successfully.",
diff --git a/app/javascript/dashboard/routes/dashboard/contacts/components/ContactsBulkActionBar.vue b/app/javascript/dashboard/routes/dashboard/contacts/components/ContactsBulkActionBar.vue
index 0666940e6..5470d1864 100644
--- a/app/javascript/dashboard/routes/dashboard/contacts/components/ContactsBulkActionBar.vue
+++ b/app/javascript/dashboard/routes/dashboard/contacts/components/ContactsBulkActionBar.vue
@@ -80,53 +80,49 @@ const handleAssignLabels = labels => {
-
+
+
diff --git a/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactsIndex.vue b/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactsIndex.vue
index a20a46ab9..0f48d9f12 100644
--- a/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactsIndex.vue
+++ b/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactsIndex.vue
@@ -404,12 +404,14 @@ onMounted(async () => {
pageNumber.value
);
}
+ // Fetch agents list to show assignee previous conversation in contact card (expanded view)
+ await store.dispatch('agents/get');
});
{
{{ emptyStateMessage }}
-
+
$state.records[contactId]
);
- return camelcaseKeys(contacts, { deep: true });
+ return camelcaseKeys(contacts, {
+ deep: true,
+ stopPaths: ['custom_attributes'],
+ });
},
getUIFlags($state) {
return $state.uiFlags;
diff --git a/theme/icons.js b/theme/icons.js
index cc697a813..04db41e89 100644
--- a/theme/icons.js
+++ b/theme/icons.js
@@ -179,6 +179,11 @@ export const icons = {
width: 14,
height: 14,
},
+ overview: {
+ body: ``,
+ width: 16,
+ height: 16,
+ },
/** Conversation Status Starts */
'status-empty': {