diff --git a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactMerge.vue b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactMerge.vue
index 65cbfafe2..2a0e79931 100644
--- a/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactMerge.vue
+++ b/app/javascript/dashboard/components-next/Contacts/ContactsSidebar/ContactMerge.vue
@@ -20,7 +20,7 @@ const props = defineProps({
},
});
-const emit = defineEmits(['goToContactsList']);
+const emit = defineEmits(['goToContactsList', 'resetTab']);
const { t } = useI18n();
const store = useStore();
@@ -74,6 +74,9 @@ const onContactSearch = debounce(
);
const resetState = () => {
+ if (state.primaryContactId === null) {
+ emit('resetTab');
+ }
state.primaryContactId = null;
searchResults.value = [];
isSearching.value = false;
diff --git a/app/javascript/dashboard/components-next/Contacts/Pages/ContactDetails.vue b/app/javascript/dashboard/components-next/Contacts/Pages/ContactDetails.vue
index 3f92df408..d46ffd850 100644
--- a/app/javascript/dashboard/components-next/Contacts/Pages/ContactDetails.vue
+++ b/app/javascript/dashboard/components-next/Contacts/Pages/ContactDetails.vue
@@ -130,15 +130,28 @@ const handleAvatarDelete = async () => {
{{ selectedContact?.name }}
-
- {{ $t('CONTACTS_LAYOUT.DETAILS.CREATED_AT', { date: createdAt }) }}
- •
- {{
- $t('CONTACTS_LAYOUT.DETAILS.LAST_ACTIVITY', {
- date: lastActivityAt,
- })
- }}
-
+
+
+
+ {{ selectedContact?.identifier }}
+
+
+
+ {{ $t('CONTACTS_LAYOUT.DETAILS.CREATED_AT', { date: createdAt }) }}
+ •
+ {{
+ $t('CONTACTS_LAYOUT.DETAILS.LAST_ACTIVITY', {
+ date: lastActivityAt,
+ })
+ }}
+
+
diff --git a/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js b/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js
index 119552f61..ef3d0e88d 100644
--- a/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js
+++ b/app/javascript/dashboard/components-next/NewConversation/helpers/composeConversationHelper.js
@@ -1,12 +1,8 @@
import { INBOX_TYPES } from 'dashboard/helper/inbox';
+import { getInboxIconByType } from 'dashboard/helper/inbox';
import camelcaseKeys from 'camelcase-keys';
import ContactAPI from 'dashboard/api/contacts';
-export const convertChannelTypeToLabel = channelType => {
- const [, type] = channelType.split('::');
- return type ? type.charAt(0).toUpperCase() + type.slice(1) : channelType;
-};
-
export const generateLabelForContactableInboxesList = ({
name,
email,
@@ -22,7 +18,7 @@ export const generateLabelForContactableInboxesList = ({
) {
return `${name} (${phoneNumber})`;
}
- return `${name} (${convertChannelTypeToLabel(channelType)})`;
+ return name;
};
export const buildContactableInboxesList = contactInboxes => {
@@ -30,6 +26,7 @@ export const buildContactableInboxesList = contactInboxes => {
return contactInboxes.map(
({ name, id, email, channelType, phoneNumber, ...rest }) => ({
id,
+ icon: getInboxIconByType(channelType, phoneNumber, 'line'),
label: generateLabelForContactableInboxesList({
name,
email,
diff --git a/app/javascript/dashboard/components-next/NewConversation/helpers/specs/composeConversationHelper.spec.js b/app/javascript/dashboard/components-next/NewConversation/helpers/specs/composeConversationHelper.spec.js
index dcfa3b051..ca30235d1 100644
--- a/app/javascript/dashboard/components-next/NewConversation/helpers/specs/composeConversationHelper.spec.js
+++ b/app/javascript/dashboard/components-next/NewConversation/helpers/specs/composeConversationHelper.spec.js
@@ -6,19 +6,6 @@ import * as helpers from '../composeConversationHelper';
vi.mock('dashboard/api/contacts');
describe('composeConversationHelper', () => {
- describe('convertChannelTypeToLabel', () => {
- it('converts channel type with namespace to capitalized label', () => {
- expect(helpers.convertChannelTypeToLabel('Channel::Email')).toBe('Email');
- expect(helpers.convertChannelTypeToLabel('Channel::Whatsapp')).toBe(
- 'Whatsapp'
- );
- });
-
- it('returns original value if no namespace found', () => {
- expect(helpers.convertChannelTypeToLabel('email')).toBe('email');
- });
- });
-
describe('generateLabelForContactableInboxesList', () => {
const contact = {
name: 'John Doe',
@@ -59,7 +46,7 @@ describe('composeConversationHelper', () => {
...contact,
channelType: 'Channel::Api',
})
- ).toBe('John Doe (Api)');
+ ).toBe('John Doe');
});
});
@@ -83,6 +70,7 @@ describe('composeConversationHelper', () => {
const result = helpers.buildContactableInboxesList(inboxes);
expect(result[0]).toMatchObject({
id: 1,
+ icon: 'i-ri-mail-line',
label: 'Email Inbox (support@example.com)',
action: 'inbox',
value: 1,
diff --git a/app/javascript/dashboard/components/layout/config/sidebarItems/contacts.js b/app/javascript/dashboard/components/layout/config/sidebarItems/contacts.js
index 3cef2237b..e4150d47d 100644
--- a/app/javascript/dashboard/components/layout/config/sidebarItems/contacts.js
+++ b/app/javascript/dashboard/components/layout/config/sidebarItems/contacts.js
@@ -15,7 +15,7 @@ const contacts = accountId => ({
icon: 'contact-card-group',
label: 'ALL_CONTACTS',
hasSubMenu: false,
- toState: frontendURL(`accounts/${accountId}/contacts`),
+ toState: frontendURL(`accounts/${accountId}/contacts?page=1`),
toStateName: 'contacts_dashboard_index',
},
],
diff --git a/app/javascript/dashboard/components/layout/sidebarComponents/Secondary.vue b/app/javascript/dashboard/components/layout/sidebarComponents/Secondary.vue
index efe89d4c6..c36b6f611 100644
--- a/app/javascript/dashboard/components/layout/sidebarComponents/Secondary.vue
+++ b/app/javascript/dashboard/components/layout/sidebarComponents/Secondary.vue
@@ -134,7 +134,7 @@ export default {
icon: 'number-symbol',
label: 'TAGGED_WITH',
hasSubMenu: true,
- key: 'label',
+ key: 'labels',
newLink: this.showNewLink(FEATURE_FLAGS.TEAM_MANAGEMENT),
newLinkTag: 'NEW_LABEL',
toState: frontendURL(`accounts/${this.accountId}/settings/labels`),
@@ -147,7 +147,7 @@ export default {
color: label.color,
truncateLabel: true,
toState: frontendURL(
- `accounts/${this.accountId}/labels/${label.title}/contacts`
+ `accounts/${this.accountId}/contacts/labels/${label.title}`
),
})),
};
@@ -194,7 +194,7 @@ export default {
icon: 'folder',
label: 'CUSTOM_VIEWS_SEGMENTS',
hasSubMenu: true,
- key: 'custom_view',
+ key: 'segments',
children: this.customViews
.filter(view => view.filter_type === 'contact')
.map(view => ({
@@ -202,7 +202,7 @@ export default {
label: view.name,
truncateLabel: true,
toState: frontendURL(
- `accounts/${this.accountId}/contacts/custom_view/${view.id}`
+ `accounts/${this.accountId}/contacts/segments/${view.id}`
),
})),
};
@@ -247,7 +247,7 @@ export default {
{
switch (type) {
@@ -110,15 +110,16 @@ export const getInboxClassByType = (type, phoneNumber) => {
}
};
-export const getInboxIconByType = (type, phoneNumber) => {
+export const getInboxIconByType = (type, phoneNumber, variant = 'fill') => {
// Special case for Twilio (whatsapp and sms)
if (type === INBOX_TYPES.TWILIO) {
return phoneNumber?.startsWith('whatsapp')
- ? 'i-ri-whatsapp-fill'
- : 'i-ri-chat-1-fill';
+ ? `i-ri-whatsapp-${variant}`
+ : `i-ri-chat-1-${variant}`;
}
- return INBOX_ICON_MAP[type] ?? DEFAULT_ICON;
+ const baseIcon = INBOX_ICON_MAP[type] ?? DEFAULT_ICON;
+ return `${baseIcon}-${variant}`;
};
export const getInboxWarningIconClass = (type, reauthorizationRequired) => {
diff --git a/app/javascript/dashboard/helper/specs/inbox.spec.js b/app/javascript/dashboard/helper/specs/inbox.spec.js
index 621c131f2..0d5625603 100644
--- a/app/javascript/dashboard/helper/specs/inbox.spec.js
+++ b/app/javascript/dashboard/helper/specs/inbox.spec.js
@@ -41,70 +41,112 @@ describe('#Inbox Helpers', () => {
});
describe('getInboxIconByType', () => {
- it('returns correct icon for web widget', () => {
- expect(getInboxIconByType(INBOX_TYPES.WEB)).toBe('i-ri-global-fill');
+ describe('fill variant (default)', () => {
+ it('returns correct icon for web widget', () => {
+ expect(getInboxIconByType(INBOX_TYPES.WEB)).toBe('i-ri-global-fill');
+ });
+
+ it('returns correct icon for Facebook', () => {
+ expect(getInboxIconByType(INBOX_TYPES.FB)).toBe('i-ri-messenger-fill');
+ });
+
+ it('returns correct icon for Twitter', () => {
+ expect(getInboxIconByType(INBOX_TYPES.TWITTER)).toBe(
+ 'i-ri-twitter-x-fill'
+ );
+ });
+
+ it('returns correct icon for WhatsApp', () => {
+ expect(getInboxIconByType(INBOX_TYPES.WHATSAPP)).toBe(
+ 'i-ri-whatsapp-fill'
+ );
+ });
+
+ it('returns correct icon for API', () => {
+ expect(getInboxIconByType(INBOX_TYPES.API)).toBe('i-ri-cloudy-fill');
+ });
+
+ it('returns correct icon for Email', () => {
+ expect(getInboxIconByType(INBOX_TYPES.EMAIL)).toBe('i-ri-mail-fill');
+ });
+
+ it('returns correct icon for Telegram', () => {
+ expect(getInboxIconByType(INBOX_TYPES.TELEGRAM)).toBe(
+ 'i-ri-telegram-fill'
+ );
+ });
+
+ it('returns correct icon for Line', () => {
+ expect(getInboxIconByType(INBOX_TYPES.LINE)).toBe('i-ri-line-fill');
+ });
+
+ it('returns default icon for unknown type', () => {
+ expect(getInboxIconByType('UNKNOWN_TYPE')).toBe('i-ri-chat-1-fill');
+ });
+
+ it('returns default icon for undefined type', () => {
+ expect(getInboxIconByType(undefined)).toBe('i-ri-chat-1-fill');
+ });
});
- it('returns correct icon for Facebook', () => {
- expect(getInboxIconByType(INBOX_TYPES.FB)).toBe('i-ri-messenger-fill');
- });
+ describe('line variant', () => {
+ it('returns correct line icon for web widget', () => {
+ expect(getInboxIconByType(INBOX_TYPES.WEB, null, 'line')).toBe(
+ 'i-ri-global-line'
+ );
+ });
- it('returns correct icon for Twitter', () => {
- expect(getInboxIconByType(INBOX_TYPES.TWITTER)).toBe(
- 'i-ri-twitter-x-fill'
- );
+ it('returns correct line icon for Facebook', () => {
+ expect(getInboxIconByType(INBOX_TYPES.FB, null, 'line')).toBe(
+ 'i-ri-messenger-line'
+ );
+ });
+
+ it('returns correct line icon for unknown type', () => {
+ expect(getInboxIconByType('UNKNOWN_TYPE', null, 'line')).toBe(
+ 'i-ri-chat-1-line'
+ );
+ });
});
describe('Twilio cases', () => {
- it('returns WhatsApp icon for Twilio WhatsApp number', () => {
- expect(
- getInboxIconByType(INBOX_TYPES.TWILIO, 'whatsapp:+1234567890')
- ).toBe('i-ri-whatsapp-fill');
+ describe('fill variant', () => {
+ it('returns WhatsApp icon for Twilio WhatsApp number', () => {
+ expect(
+ getInboxIconByType(INBOX_TYPES.TWILIO, 'whatsapp:+1234567890')
+ ).toBe('i-ri-whatsapp-fill');
+ });
+
+ it('returns SMS icon for regular Twilio number', () => {
+ expect(getInboxIconByType(INBOX_TYPES.TWILIO, '+1234567890')).toBe(
+ 'i-ri-chat-1-fill'
+ );
+ });
+
+ it('returns SMS icon when phone number is undefined', () => {
+ expect(getInboxIconByType(INBOX_TYPES.TWILIO, undefined)).toBe(
+ 'i-ri-chat-1-fill'
+ );
+ });
});
- it('returns SMS icon for regular Twilio number', () => {
- expect(getInboxIconByType(INBOX_TYPES.TWILIO, '+1234567890')).toBe(
- 'i-ri-chat-1-fill'
- );
+ describe('line variant', () => {
+ it('returns WhatsApp line icon for Twilio WhatsApp number', () => {
+ expect(
+ getInboxIconByType(
+ INBOX_TYPES.TWILIO,
+ 'whatsapp:+1234567890',
+ 'line'
+ )
+ ).toBe('i-ri-whatsapp-line');
+ });
+
+ it('returns SMS line icon for regular Twilio number', () => {
+ expect(
+ getInboxIconByType(INBOX_TYPES.TWILIO, '+1234567890', 'line')
+ ).toBe('i-ri-chat-1-line');
+ });
});
-
- it('returns SMS icon when phone number is undefined', () => {
- expect(getInboxIconByType(INBOX_TYPES.TWILIO, undefined)).toBe(
- 'i-ri-chat-1-fill'
- );
- });
- });
-
- it('returns correct icon for WhatsApp', () => {
- expect(getInboxIconByType(INBOX_TYPES.WHATSAPP)).toBe(
- 'i-ri-whatsapp-fill'
- );
- });
-
- it('returns correct icon for API', () => {
- expect(getInboxIconByType(INBOX_TYPES.API)).toBe('i-ri-cloudy-fill');
- });
-
- it('returns correct icon for Email', () => {
- expect(getInboxIconByType(INBOX_TYPES.EMAIL)).toBe('i-ri-mail-fill');
- });
-
- it('returns correct icon for Telegram', () => {
- expect(getInboxIconByType(INBOX_TYPES.TELEGRAM)).toBe(
- 'i-ri-telegram-fill'
- );
- });
-
- it('returns correct icon for Line', () => {
- expect(getInboxIconByType(INBOX_TYPES.LINE)).toBe('i-ri-line-fill');
- });
-
- it('returns default icon for unknown type', () => {
- expect(getInboxIconByType('UNKNOWN_TYPE')).toBe('i-ri-chat-1-fill');
- });
-
- it('returns default icon for undefined type', () => {
- expect(getInboxIconByType(undefined)).toBe('i-ri-chat-1-fill');
});
});
diff --git a/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactManageView.vue b/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactManageView.vue
index d22048a37..8b07646e0 100644
--- a/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactManageView.vue
+++ b/app/javascript/dashboard/routes/dashboard/contacts/pages/ContactManageView.vue
@@ -145,6 +145,7 @@ onMounted(() => {
ref="contactMergeRef"
:selected-contact="selectedContact"
@go-to-contacts-list="goToContactsList"
+ @reset-tab="handleTabChange(CONTACT_TABS_OPTIONS[0])"
/>