feat: expose assignable conversation owners

This commit is contained in:
Sojan Jose
2026-06-26 02:07:41 -07:00
parent 4edf626af2
commit ca9bedfba1
13 changed files with 142 additions and 12 deletions
+4
View File
@@ -15,6 +15,10 @@ class Inboxes extends CacheEnabledApiClient {
return axios.get(`${this.url}/${inboxId}/campaigns`);
}
getAssignableOwners(inboxId) {
return axios.get(`${this.url}/${inboxId}/assignable_owners`);
}
deleteInboxAvatar(inboxId) {
return axios.delete(`${this.url}/${inboxId}/avatar`);
}
@@ -9,6 +9,7 @@ describe('#InboxesAPI', () => {
expect(inboxesAPI).toHaveProperty('create');
expect(inboxesAPI).toHaveProperty('update');
expect(inboxesAPI).toHaveProperty('delete');
expect(inboxesAPI).toHaveProperty('getAssignableOwners');
expect(inboxesAPI).toHaveProperty('getCampaigns');
expect(inboxesAPI).toHaveProperty('getAgentBot');
expect(inboxesAPI).toHaveProperty('setAgentBot');
@@ -37,6 +38,13 @@ describe('#InboxesAPI', () => {
expect(axiosMock.get).toHaveBeenCalledWith('/api/v1/inboxes/2/campaigns');
});
it('#getAssignableOwners', () => {
inboxesAPI.getAssignableOwners(2);
expect(axiosMock.get).toHaveBeenCalledWith(
'/api/v1/inboxes/2/assignable_owners'
);
});
it('#deleteInboxAvatar', () => {
inboxesAPI.deleteInboxAvatar(2);
expect(axiosMock.delete).toHaveBeenCalledWith('/api/v1/inboxes/2/avatar');
@@ -31,7 +31,7 @@ const mockUseMapGetter = (overrides = {}) => {
getSelectedChat: ref({ inbox_id: 1, meta: { assignee: true } }),
getCurrentAccountId: ref(1),
'inboxAssignableAgents/getAssignableAgents': ref(() => allAgentsData),
'agentBots/getBots': ref([]),
'inboxAssignableAgents/getAssignableOwners': ref(() => []),
};
const mergedGetters = { ...defaultGetters, ...overrides };
@@ -78,7 +78,16 @@ describe('useAgentsList', () => {
it('includes agent bots when includeAgentBots is true', () => {
mockUseMapGetter({
'agentBots/getBots': ref([{ id: 1, name: 'Bot', thumbnail: '' }]),
'inboxAssignableAgents/getAssignableOwners': ref(() => [
{ id: 2, name: 'Agent', assignee_type: 'User' },
{
id: 1,
name: 'Bot',
thumbnail: '',
assignee_type: 'AgentBot',
icon: 'i-lucide-bot',
},
]),
});
const { agentsList } = useAgentsList(true, true);
@@ -22,7 +22,9 @@ export function useAgentsList(
const currentChat = useMapGetter('getSelectedChat');
const currentAccountId = useMapGetter('getCurrentAccountId');
const assignable = useMapGetter('inboxAssignableAgents/getAssignableAgents');
const agentBots = useMapGetter('agentBots/getBots');
const assignableOwners = useMapGetter(
'inboxAssignableAgents/getAssignableOwners'
);
const inboxId = computed(() => currentChat.value?.inbox_id);
const isAgentSelected = computed(() => currentChat.value?.meta?.assignee);
@@ -47,18 +49,22 @@ export function useAgentsList(
return inboxId.value ? assignable.value(inboxId.value) : [];
});
const owners = computed(() => {
return includeAgentBots && inboxId.value
? assignableOwners.value(inboxId.value)
: [];
});
/**
* @type {import('vue').ComputedRef<Array>}
*/
const agentsList = computed(() => {
const agents = assignableAgents.value || [];
const bots = includeAgentBots
? agentBots.value.map(bot => ({
...bot,
assignee_type: 'AgentBot',
icon: 'i-lucide-bot',
}))
: [];
const agents = includeAgentBots
? owners.value.filter(owner => owner.assignee_type === 'User')
: assignableAgents.value || [];
const bots = owners.value.filter(
owner => owner.assignee_type === 'AgentBot'
);
const agentsByUpdatedPresence = getAgentsByUpdatedPresence(
agents,
currentUser.value,
@@ -168,7 +168,10 @@ export default {
},
},
mounted() {
this.$store.dispatch('agentBots/get');
this.$store.dispatch(
'inboxAssignableAgents/fetchAssignableOwners',
this.currentChat.inbox_id
);
},
methods: {
onSelfAssign() {
@@ -1,7 +1,9 @@
import AssignableAgentsAPI from '../../api/assignableAgents';
import InboxesAPI from '../../api/inboxes';
const state = {
records: {},
ownerRecords: {},
uiFlags: {
isFetching: false,
},
@@ -10,6 +12,7 @@ const state = {
export const types = {
SET_INBOX_ASSIGNABLE_AGENTS_UI_FLAG: 'SET_INBOX_ASSIGNABLE_AGENTS_UI_FLAG',
SET_INBOX_ASSIGNABLE_AGENTS: 'SET_INBOX_ASSIGNABLE_AGENTS',
SET_INBOX_ASSIGNABLE_OWNERS: 'SET_INBOX_ASSIGNABLE_OWNERS',
};
export const getters = {
@@ -18,6 +21,7 @@ export const getters = {
const verifiedAgents = allAgents.filter(record => record.confirmed);
return verifiedAgents;
},
getAssignableOwners: $state => inboxId => $state.ownerRecords[inboxId] || [],
getUIFlags($state) {
return $state.uiFlags;
},
@@ -40,6 +44,15 @@ export const actions = {
commit(types.SET_INBOX_ASSIGNABLE_AGENTS_UI_FLAG, { isFetching: false });
}
},
async fetchAssignableOwners({ commit }, inboxId) {
const {
data: { payload },
} = await InboxesAPI.getAssignableOwners(inboxId);
commit(types.SET_INBOX_ASSIGNABLE_OWNERS, {
inboxId,
owners: payload,
});
},
};
export const mutations = {
@@ -55,6 +68,12 @@ export const mutations = {
[inboxId]: members,
};
},
[types.SET_INBOX_ASSIGNABLE_OWNERS]: ($state, { inboxId, owners }) => {
$state.ownerRecords = {
...$state.ownerRecords,
[inboxId]: owners,
};
},
};
export default {
@@ -1,12 +1,18 @@
import axios from 'axios';
import InboxesAPI from 'dashboard/api/inboxes';
import { actions, types } from '../../inboxAssignableAgents';
import agentsData from './fixtures';
const commit = vi.fn();
global.axios = axios;
vi.mock('axios');
vi.mock('dashboard/api/inboxes');
describe('#actions', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('#fetch', () => {
it('sends correct actions if API is success', async () => {
axios.get.mockResolvedValue({
@@ -33,4 +39,20 @@ describe('#actions', () => {
]);
});
});
describe('#fetchAssignableOwners', () => {
it('stores assignable owners for the inbox', async () => {
InboxesAPI.getAssignableOwners.mockResolvedValue({
data: { payload: agentsData },
});
await actions.fetchAssignableOwners({ commit }, 1);
expect(InboxesAPI.getAssignableOwners).toHaveBeenCalledWith(1);
expect(commit).toHaveBeenCalledWith(types.SET_INBOX_ASSIGNABLE_OWNERS, {
inboxId: 1,
owners: agentsData,
});
});
});
});
@@ -13,4 +13,16 @@ describe('#mutations', () => {
expect(state.records).toEqual({ 1: agentsData });
});
});
describe('#SET_INBOX_ASSIGNABLE_OWNERS', () => {
it('adds inbox owners to ownerRecords', () => {
const state = { ownerRecords: {} };
mutations[types.SET_INBOX_ASSIGNABLE_OWNERS](state, {
owners: [...agentsData],
inboxId: 1,
});
expect(state.ownerRecords).toEqual({ 1: agentsData });
});
});
});