fix: Fix issues with contact routes in old navigation sidebar (#10547)

This commit is contained in:
Sivin Varghese
2024-12-06 12:16:57 +05:30
committed by GitHub
parent 3fd585f40b
commit afb3e3e649
9 changed files with 149 additions and 104 deletions

View File

@@ -20,7 +20,7 @@ const props = defineProps({
}, },
}); });
const emit = defineEmits(['goToContactsList']); const emit = defineEmits(['goToContactsList', 'resetTab']);
const { t } = useI18n(); const { t } = useI18n();
const store = useStore(); const store = useStore();
@@ -74,6 +74,9 @@ const onContactSearch = debounce(
); );
const resetState = () => { const resetState = () => {
if (state.primaryContactId === null) {
emit('resetTab');
}
state.primaryContactId = null; state.primaryContactId = null;
searchResults.value = []; searchResults.value = [];
isSearching.value = false; isSearching.value = false;

View File

@@ -130,7 +130,19 @@ const handleAvatarDelete = async () => {
<h3 class="text-base font-medium text-n-slate-12"> <h3 class="text-base font-medium text-n-slate-12">
{{ selectedContact?.name }} {{ selectedContact?.name }}
</h3> </h3>
<span class="text-sm text-n-slate-11"> <div class="flex flex-col gap-1.5">
<span
v-if="selectedContact?.identifier"
class="inline-flex items-center gap-1 text-sm text-n-slate-11"
>
<span class="i-ph-user-gear text-n-slate-10 size-4" />
{{ selectedContact?.identifier }}
</span>
<span class="inline-flex items-center gap-1 text-sm text-n-slate-11">
<span
v-if="selectedContact?.identifier"
class="i-ph-activity text-n-slate-10 size-4"
/>
{{ $t('CONTACTS_LAYOUT.DETAILS.CREATED_AT', { date: createdAt }) }} {{ $t('CONTACTS_LAYOUT.DETAILS.CREATED_AT', { date: createdAt }) }}
{{ {{
@@ -140,6 +152,7 @@ const handleAvatarDelete = async () => {
}} }}
</span> </span>
</div> </div>
</div>
<ContactLabels :contact-id="selectedContact?.id" /> <ContactLabels :contact-id="selectedContact?.id" />
</div> </div>
<div class="flex flex-col items-start gap-6"> <div class="flex flex-col items-start gap-6">

View File

@@ -1,12 +1,8 @@
import { INBOX_TYPES } from 'dashboard/helper/inbox'; import { INBOX_TYPES } from 'dashboard/helper/inbox';
import { getInboxIconByType } from 'dashboard/helper/inbox';
import camelcaseKeys from 'camelcase-keys'; import camelcaseKeys from 'camelcase-keys';
import ContactAPI from 'dashboard/api/contacts'; 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 = ({ export const generateLabelForContactableInboxesList = ({
name, name,
email, email,
@@ -22,7 +18,7 @@ export const generateLabelForContactableInboxesList = ({
) { ) {
return `${name} (${phoneNumber})`; return `${name} (${phoneNumber})`;
} }
return `${name} (${convertChannelTypeToLabel(channelType)})`; return name;
}; };
export const buildContactableInboxesList = contactInboxes => { export const buildContactableInboxesList = contactInboxes => {
@@ -30,6 +26,7 @@ export const buildContactableInboxesList = contactInboxes => {
return contactInboxes.map( return contactInboxes.map(
({ name, id, email, channelType, phoneNumber, ...rest }) => ({ ({ name, id, email, channelType, phoneNumber, ...rest }) => ({
id, id,
icon: getInboxIconByType(channelType, phoneNumber, 'line'),
label: generateLabelForContactableInboxesList({ label: generateLabelForContactableInboxesList({
name, name,
email, email,

View File

@@ -6,19 +6,6 @@ import * as helpers from '../composeConversationHelper';
vi.mock('dashboard/api/contacts'); vi.mock('dashboard/api/contacts');
describe('composeConversationHelper', () => { 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', () => { describe('generateLabelForContactableInboxesList', () => {
const contact = { const contact = {
name: 'John Doe', name: 'John Doe',
@@ -59,7 +46,7 @@ describe('composeConversationHelper', () => {
...contact, ...contact,
channelType: 'Channel::Api', channelType: 'Channel::Api',
}) })
).toBe('John Doe (Api)'); ).toBe('John Doe');
}); });
}); });
@@ -83,6 +70,7 @@ describe('composeConversationHelper', () => {
const result = helpers.buildContactableInboxesList(inboxes); const result = helpers.buildContactableInboxesList(inboxes);
expect(result[0]).toMatchObject({ expect(result[0]).toMatchObject({
id: 1, id: 1,
icon: 'i-ri-mail-line',
label: 'Email Inbox (support@example.com)', label: 'Email Inbox (support@example.com)',
action: 'inbox', action: 'inbox',
value: 1, value: 1,

View File

@@ -15,7 +15,7 @@ const contacts = accountId => ({
icon: 'contact-card-group', icon: 'contact-card-group',
label: 'ALL_CONTACTS', label: 'ALL_CONTACTS',
hasSubMenu: false, hasSubMenu: false,
toState: frontendURL(`accounts/${accountId}/contacts`), toState: frontendURL(`accounts/${accountId}/contacts?page=1`),
toStateName: 'contacts_dashboard_index', toStateName: 'contacts_dashboard_index',
}, },
], ],

View File

@@ -134,7 +134,7 @@ export default {
icon: 'number-symbol', icon: 'number-symbol',
label: 'TAGGED_WITH', label: 'TAGGED_WITH',
hasSubMenu: true, hasSubMenu: true,
key: 'label', key: 'labels',
newLink: this.showNewLink(FEATURE_FLAGS.TEAM_MANAGEMENT), newLink: this.showNewLink(FEATURE_FLAGS.TEAM_MANAGEMENT),
newLinkTag: 'NEW_LABEL', newLinkTag: 'NEW_LABEL',
toState: frontendURL(`accounts/${this.accountId}/settings/labels`), toState: frontendURL(`accounts/${this.accountId}/settings/labels`),
@@ -147,7 +147,7 @@ export default {
color: label.color, color: label.color,
truncateLabel: true, truncateLabel: true,
toState: frontendURL( toState: frontendURL(
`accounts/${this.accountId}/labels/${label.title}/contacts` `accounts/${this.accountId}/contacts/labels/${label.title}`
), ),
})), })),
}; };
@@ -194,7 +194,7 @@ export default {
icon: 'folder', icon: 'folder',
label: 'CUSTOM_VIEWS_SEGMENTS', label: 'CUSTOM_VIEWS_SEGMENTS',
hasSubMenu: true, hasSubMenu: true,
key: 'custom_view', key: 'segments',
children: this.customViews children: this.customViews
.filter(view => view.filter_type === 'contact') .filter(view => view.filter_type === 'contact')
.map(view => ({ .map(view => ({
@@ -202,7 +202,7 @@ export default {
label: view.name, label: view.name,
truncateLabel: true, truncateLabel: true,
toState: frontendURL( toState: frontendURL(
`accounts/${this.accountId}/contacts/custom_view/${view.id}` `accounts/${this.accountId}/contacts/segments/${view.id}`
), ),
})), })),
}; };
@@ -247,7 +247,7 @@ export default {
<transition-group <transition-group
name="menu-list" name="menu-list"
tag="ul" tag="ul"
class="pt-2 reset-base list-none" class="pt-2 list-none reset-base"
> >
<SecondaryNavItem <SecondaryNavItem
v-for="menuItem in accessibleMenuItems" v-for="menuItem in accessibleMenuItems"

View File

@@ -12,17 +12,17 @@ export const INBOX_TYPES = {
}; };
const INBOX_ICON_MAP = { const INBOX_ICON_MAP = {
[INBOX_TYPES.WEB]: 'i-ri-global-fill', [INBOX_TYPES.WEB]: 'i-ri-global',
[INBOX_TYPES.FB]: 'i-ri-messenger-fill', [INBOX_TYPES.FB]: 'i-ri-messenger',
[INBOX_TYPES.TWITTER]: 'i-ri-twitter-x-fill', [INBOX_TYPES.TWITTER]: 'i-ri-twitter-x',
[INBOX_TYPES.WHATSAPP]: 'i-ri-whatsapp-fill', [INBOX_TYPES.WHATSAPP]: 'i-ri-whatsapp',
[INBOX_TYPES.API]: 'i-ri-cloudy-fill', [INBOX_TYPES.API]: 'i-ri-cloudy',
[INBOX_TYPES.EMAIL]: 'i-ri-mail-fill', [INBOX_TYPES.EMAIL]: 'i-ri-mail',
[INBOX_TYPES.TELEGRAM]: 'i-ri-telegram-fill', [INBOX_TYPES.TELEGRAM]: 'i-ri-telegram',
[INBOX_TYPES.LINE]: 'i-ri-line-fill', [INBOX_TYPES.LINE]: 'i-ri-line',
}; };
const DEFAULT_ICON = 'i-ri-chat-1-fill'; const DEFAULT_ICON = 'i-ri-chat-1';
export const getInboxSource = (type, phoneNumber, inbox) => { export const getInboxSource = (type, phoneNumber, inbox) => {
switch (type) { 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) // Special case for Twilio (whatsapp and sms)
if (type === INBOX_TYPES.TWILIO) { if (type === INBOX_TYPES.TWILIO) {
return phoneNumber?.startsWith('whatsapp') return phoneNumber?.startsWith('whatsapp')
? 'i-ri-whatsapp-fill' ? `i-ri-whatsapp-${variant}`
: 'i-ri-chat-1-fill'; : `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) => { export const getInboxWarningIconClass = (type, reauthorizationRequired) => {

View File

@@ -41,6 +41,7 @@ describe('#Inbox Helpers', () => {
}); });
describe('getInboxIconByType', () => { describe('getInboxIconByType', () => {
describe('fill variant (default)', () => {
it('returns correct icon for web widget', () => { it('returns correct icon for web widget', () => {
expect(getInboxIconByType(INBOX_TYPES.WEB)).toBe('i-ri-global-fill'); expect(getInboxIconByType(INBOX_TYPES.WEB)).toBe('i-ri-global-fill');
}); });
@@ -55,26 +56,6 @@ describe('#Inbox Helpers', () => {
); );
}); });
describe('Twilio cases', () => {
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 correct icon for WhatsApp', () => { it('returns correct icon for WhatsApp', () => {
expect(getInboxIconByType(INBOX_TYPES.WHATSAPP)).toBe( expect(getInboxIconByType(INBOX_TYPES.WHATSAPP)).toBe(
'i-ri-whatsapp-fill' 'i-ri-whatsapp-fill'
@@ -108,6 +89,67 @@ describe('#Inbox Helpers', () => {
}); });
}); });
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 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', () => {
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'
);
});
});
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');
});
});
});
});
describe('getInboxWarningIconClass', () => { describe('getInboxWarningIconClass', () => {
it('should return correct class for warning', () => { it('should return correct class for warning', () => {
expect(getInboxWarningIconClass('Channel::FacebookPage', true)).toEqual( expect(getInboxWarningIconClass('Channel::FacebookPage', true)).toEqual(

View File

@@ -145,6 +145,7 @@ onMounted(() => {
ref="contactMergeRef" ref="contactMergeRef"
:selected-contact="selectedContact" :selected-contact="selectedContact"
@go-to-contacts-list="goToContactsList" @go-to-contacts-list="goToContactsList"
@reset-tab="handleTabChange(CONTACT_TABS_OPTIONS[0])"
/> />
</template> </template>
</template> </template>