feat: conversation participants (#4145)
Fixes #241 Fixes: chatwoot/product#648 Co-authored-by: Aswin Dev P.S <aswindevps@gmail.com> Co-authored-by: Nithin David Thomas <1277421+nithindavid@users.noreply.github.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
@@ -377,6 +377,9 @@ export default {
|
||||
if (this.conversationType === 'mention') {
|
||||
return this.$t('CHAT_LIST.MENTION_HEADING');
|
||||
}
|
||||
if (this.conversationType === 'participating') {
|
||||
return this.$t('CONVERSATION_PARTICIPANTS.SIDEBAR_MENU_TITLE');
|
||||
}
|
||||
if (this.conversationType === 'unattended') {
|
||||
return this.$t('CHAT_LIST.UNATTENDED_HEADING');
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ const conversations = accountId => ({
|
||||
'conversations_through_team',
|
||||
'conversation_mentions',
|
||||
'conversation_through_mentions',
|
||||
'conversation_participating',
|
||||
'conversation_through_participating',
|
||||
'folder_conversations',
|
||||
'conversations_through_folders',
|
||||
'conversation_unattended',
|
||||
|
||||
@@ -154,6 +154,7 @@ export default {
|
||||
left: var(--space-slab);
|
||||
bottom: var(--space-larger);
|
||||
min-width: 22rem;
|
||||
top: unset;
|
||||
z-index: var(--z-index-low);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -56,6 +56,8 @@ export const conversationUrl = ({
|
||||
url = `accounts/${accountId}/custom_view/${foldersId}/conversations/${id}`;
|
||||
} else if (conversationType === 'mention') {
|
||||
url = `accounts/${accountId}/mentions/conversations/${id}`;
|
||||
} else if (conversationType === 'participating') {
|
||||
url = `accounts/${accountId}/participating/conversations/${id}`;
|
||||
} else if (conversationType === 'unattended') {
|
||||
url = `accounts/${accountId}/unattended/conversations/${id}`;
|
||||
}
|
||||
|
||||
@@ -346,4 +346,5 @@
|
||||
"ERROR_MESSAGE": "Could not merge contacts, try again!"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -255,6 +255,23 @@
|
||||
"CC": "Cc",
|
||||
"SUBJECT": "Subject"
|
||||
},
|
||||
"CONVERSATION_PARTICIPANTS": {
|
||||
"SIDEBAR_MENU_TITLE": "Participating",
|
||||
"SIDEBAR_TITLE": "Conversation participants",
|
||||
"NO_RECORDS_FOUND": "No results found",
|
||||
"ADD_PARTICIPANTS": "Select participants",
|
||||
"REMANING_PARTICIPANTS_TEXT": "+%{count} others",
|
||||
"REMANING_PARTICIPANT_TEXT": "+%{count} other",
|
||||
"TOTAL_PARTICIPANTS_TEXT": "%{count} people are participating.",
|
||||
"TOTAL_PARTICIPANT_TEXT": "%{count} person is participating.",
|
||||
"NO_PARTICIPANTS_TEXT": "No one is participating!.",
|
||||
"WATCH_CONVERSATION": "Join conversation",
|
||||
"YOU_ARE_WATCHING": "You are participating",
|
||||
"API": {
|
||||
"ERROR_MESSAGE": "Could not update, try again!",
|
||||
"SUCCESS_MESSAGE": "Participants updated!"
|
||||
}
|
||||
},
|
||||
"TRANSLATE_MODAL": {
|
||||
"TITLE": "View translated content",
|
||||
"DESC": "You can view the translated content in each langauge.",
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
"conversation_creation": "New conversation",
|
||||
"conversation_assignment": "Conversation Assigned",
|
||||
"assigned_conversation_new_message": "New Message",
|
||||
"participating_conversation_new_message": "New Message",
|
||||
"conversation_mention": "Mention"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -79,7 +79,8 @@
|
||||
"CONVERSATION_ASSIGNMENT": "Send email notifications when a conversation is assigned to me",
|
||||
"CONVERSATION_CREATION": "Send email notifications when a new conversation is created",
|
||||
"CONVERSATION_MENTION": "Send email notifications when you are mentioned in a conversation",
|
||||
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "Send email notifications when a new message is created in an assigned conversation"
|
||||
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "Send email notifications when a new message is created in an assigned conversation",
|
||||
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "Send email notifications when a new message is created in a participating conversation"
|
||||
},
|
||||
"API": {
|
||||
"UPDATE_SUCCESS": "Your notification preferences are updated successfully",
|
||||
@@ -92,6 +93,7 @@
|
||||
"CONVERSATION_CREATION": "Send push notifications when a new conversation is created",
|
||||
"CONVERSATION_MENTION": "Send push notifications when you are mentioned in a conversation",
|
||||
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "Send push notifications when a new message is created in an assigned conversation",
|
||||
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "Send push notifications when a new message is created in a participating conversation",
|
||||
"HAS_ENABLED_PUSH": "You have enabled push for this browser.",
|
||||
"REQUEST_PUSH": "Enable push notifications"
|
||||
},
|
||||
@@ -188,6 +190,7 @@
|
||||
"CONVERSATIONS": "Conversations",
|
||||
"ALL_CONVERSATIONS": "All Conversations",
|
||||
"MENTIONED_CONVERSATIONS": "Mentions",
|
||||
"PARTICIPATING_CONVERSATIONS": "Participating",
|
||||
"UNATTENDED_CONVERSATIONS": "Unattended",
|
||||
"REPORTS": "Reports",
|
||||
"SETTINGS": "Settings",
|
||||
|
||||
@@ -120,6 +120,7 @@ describe('uiSettingsMixin', () => {
|
||||
{ name: 'conversation_info' },
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'previous_conversation' },
|
||||
{ name: 'conversation_participants' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ export const DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER = [
|
||||
{ name: 'conversation_info' },
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'previous_conversation' },
|
||||
{ name: 'conversation_participants' },
|
||||
];
|
||||
export const DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER = [
|
||||
{ name: 'contact_attributes' },
|
||||
|
||||
@@ -39,6 +39,24 @@
|
||||
/>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="element.name === 'conversation_participants'"
|
||||
class="conversation--actions"
|
||||
>
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_PARTICIPANTS.SIDEBAR_TITLE')"
|
||||
:is-open="isContactSidebarItemOpen('is_conv_participants_open')"
|
||||
@click="
|
||||
value =>
|
||||
toggleSidebarUIState('is_conv_participants_open', value)
|
||||
"
|
||||
>
|
||||
<conversation-participant
|
||||
:conversation-id="conversationId"
|
||||
:inbox-id="inboxId"
|
||||
/>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<div v-else-if="element.name === 'conversation_info'">
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_INFO')"
|
||||
@@ -118,6 +136,7 @@ import alertMixin from 'shared/mixins/alertMixin';
|
||||
import AccordionItem from 'dashboard/components/Accordion/AccordionItem';
|
||||
import ContactConversations from './ContactConversations.vue';
|
||||
import ConversationAction from './ConversationAction.vue';
|
||||
import ConversationParticipant from './ConversationParticipant.vue';
|
||||
|
||||
import ContactInfo from './contact/ContactInfo';
|
||||
import ConversationInfo from './ConversationInfo';
|
||||
@@ -136,6 +155,7 @@ export default {
|
||||
CustomAttributes,
|
||||
CustomAttributeSelector,
|
||||
ConversationAction,
|
||||
ConversationParticipant,
|
||||
draggable,
|
||||
MacrosList,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
<template>
|
||||
<div class="watchers-wrap">
|
||||
<div class="watchers--collapsed">
|
||||
<div class="content-wrap">
|
||||
<div>
|
||||
<p v-if="watchersList.length" class="total-watchers message-text">
|
||||
<spinner v-if="watchersUiFlas.isFetching" size="tiny" />
|
||||
{{ totalWatchersText }}
|
||||
</p>
|
||||
<p v-else class="text-muted message-text">
|
||||
{{ $t('CONVERSATION_PARTICIPANTS.NO_PARTICIPANTS_TEXT') }}
|
||||
</p>
|
||||
</div>
|
||||
<woot-button
|
||||
v-tooltip.left="$t('CONVERSATION_PARTICIPANTS.ADD_PARTICIPANTS')"
|
||||
:title="$t('CONVERSATION_PARTICIPANTS.ADD_PARTICIPANTS')"
|
||||
icon="settings"
|
||||
size="tiny"
|
||||
variant="smooth"
|
||||
color-scheme="secondary"
|
||||
@click="onOpenDropdown"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<thumbnail-group
|
||||
:more-thumbnails-text="moreThumbnailsText"
|
||||
:show-more-thumbnails-count="showMoreThumbs"
|
||||
:users-list="thumbnailList"
|
||||
/>
|
||||
<p v-if="isUserWatching" class="text-muted message-text">
|
||||
{{ $t('CONVERSATION_PARTICIPANTS.YOU_ARE_WATCHING') }}
|
||||
</p>
|
||||
<woot-button
|
||||
v-else
|
||||
icon="arrow-right"
|
||||
variant="link"
|
||||
size="small"
|
||||
@click="onSelfAssign"
|
||||
>
|
||||
{{ $t('CONVERSATION_PARTICIPANTS.WATCH_CONVERSATION') }}
|
||||
</woot-button>
|
||||
</div>
|
||||
<div
|
||||
v-on-clickaway="
|
||||
() => {
|
||||
onCloseDropdown();
|
||||
}
|
||||
"
|
||||
:class="{ 'dropdown-pane--open': showDropDown }"
|
||||
class="dropdown-pane"
|
||||
>
|
||||
<div class="dropdown__header">
|
||||
<h4 class="text-block-title text-truncate">
|
||||
{{ $t('CONVERSATION_PARTICIPANTS.ADD_PARTICIPANTS') }}
|
||||
</h4>
|
||||
<woot-button
|
||||
icon="dismiss"
|
||||
size="tiny"
|
||||
color-scheme="secondary"
|
||||
variant="clear"
|
||||
@click="onCloseDropdown"
|
||||
/>
|
||||
</div>
|
||||
<multiselect-dropdown-items
|
||||
:options="agentsList"
|
||||
:selected-items="selectedWatchers"
|
||||
:has-thumbnail="true"
|
||||
@click="onClickItem"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mixin as clickaway } from 'vue-clickaway';
|
||||
import Spinner from 'shared/components/Spinner';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import { mapGetters } from 'vuex';
|
||||
import agentMixin from 'dashboard/mixins/agentMixin';
|
||||
import ThumbnailGroup from 'dashboard/components/widgets/ThumbnailGroup';
|
||||
import MultiselectDropdownItems from 'shared/components/ui/MultiselectDropdownItems';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Spinner,
|
||||
ThumbnailGroup,
|
||||
MultiselectDropdownItems,
|
||||
},
|
||||
mixins: [alertMixin, agentMixin, clickaway],
|
||||
props: {
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
inboxId: {
|
||||
type: Number,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedWatchers: [],
|
||||
showDropDown: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
watchersUiFlas: 'conversationWatchers/getUIFlags',
|
||||
currentUser: 'getCurrentUser',
|
||||
}),
|
||||
watchersFromStore() {
|
||||
return this.$store.getters['conversationWatchers/getByConversationId'](
|
||||
this.conversationId
|
||||
);
|
||||
},
|
||||
watchersList: {
|
||||
get() {
|
||||
return this.selectedWatchers;
|
||||
},
|
||||
set(participants) {
|
||||
this.selectedWatchers = [...participants];
|
||||
const userIds = participants.map(el => el.id);
|
||||
this.updateParticipant(userIds);
|
||||
},
|
||||
},
|
||||
isUserWatching() {
|
||||
return this.selectedWatchers.some(
|
||||
watcher => watcher.id === this.currentUser.id
|
||||
);
|
||||
},
|
||||
thumbnailList() {
|
||||
return this.selectedWatchers.slice(0, 4);
|
||||
},
|
||||
moreAgentCount() {
|
||||
const maxThumbnailCount = 4;
|
||||
return this.watchersList.length - maxThumbnailCount;
|
||||
},
|
||||
moreThumbnailsText() {
|
||||
if (this.moreAgentCount > 1) {
|
||||
return this.$t('CONVERSATION_PARTICIPANTS.REMANING_PARTICIPANTS_TEXT', {
|
||||
count: this.moreAgentCount,
|
||||
});
|
||||
}
|
||||
return this.$t('CONVERSATION_PARTICIPANTS.REMANING_PARTICIPANT_TEXT', {
|
||||
count: 1,
|
||||
});
|
||||
},
|
||||
showMoreThumbs() {
|
||||
return this.moreAgentCount > 0;
|
||||
},
|
||||
totalWatchersText() {
|
||||
if (this.selectedWatchers.length > 1) {
|
||||
return this.$t('CONVERSATION_PARTICIPANTS.TOTAL_PARTICIPANTS_TEXT', {
|
||||
count: this.selectedWatchers.length,
|
||||
});
|
||||
}
|
||||
return this.$t('CONVERSATION_PARTICIPANTS.TOTAL_PARTICIPANT_TEXT', {
|
||||
count: 1,
|
||||
});
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
conversationId() {
|
||||
this.fetchParticipants();
|
||||
},
|
||||
watchersFromStore(participants) {
|
||||
this.selectedWatchers = [...participants];
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.fetchParticipants();
|
||||
this.$store.dispatch('agents/get');
|
||||
},
|
||||
methods: {
|
||||
fetchParticipants() {
|
||||
const conversationId = this.conversationId;
|
||||
this.$store.dispatch('conversationWatchers/show', { conversationId });
|
||||
},
|
||||
async updateParticipant(userIds) {
|
||||
const conversationId = this.conversationId;
|
||||
let alertMessage = this.$t(
|
||||
'CONVERSATION_PARTICIPANTS.API.SUCCESS_MESSAGE'
|
||||
);
|
||||
|
||||
try {
|
||||
await this.$store.dispatch('conversationWatchers/update', {
|
||||
conversationId,
|
||||
userIds,
|
||||
});
|
||||
} catch (error) {
|
||||
alertMessage =
|
||||
error?.message ||
|
||||
this.$t('CONVERSATION_PARTICIPANTS.API.ERROR_MESSAGE');
|
||||
} finally {
|
||||
this.showAlert(alertMessage);
|
||||
}
|
||||
this.fetchParticipants();
|
||||
},
|
||||
onOpenDropdown() {
|
||||
this.showDropDown = true;
|
||||
},
|
||||
onCloseDropdown() {
|
||||
this.showDropDown = false;
|
||||
},
|
||||
onClickItem(agent) {
|
||||
const isAgentSelected = this.watchersList.some(
|
||||
participant => participant.id === agent.id
|
||||
);
|
||||
|
||||
if (isAgentSelected) {
|
||||
const updatedList = this.watchersList.filter(
|
||||
participant => participant.id !== agent.id
|
||||
);
|
||||
|
||||
this.watchersList = [...updatedList];
|
||||
} else {
|
||||
this.watchersList = [...this.watchersList, agent];
|
||||
}
|
||||
},
|
||||
onSelfAssign() {
|
||||
this.watchersList = [...this.selectedWatchers, this.currentUser];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.watchers-wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin-bottom: var(--space-smaller);
|
||||
}
|
||||
|
||||
.watchers--collapsed {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dropdown-pane {
|
||||
box-sizing: border-box;
|
||||
top: var(--space-large);
|
||||
width: 100%;
|
||||
}
|
||||
.dropdown__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: var(--space-smaller);
|
||||
|
||||
.text-block-title {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.message-text {
|
||||
margin: 0;
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
</style>
|
||||
@@ -121,7 +121,6 @@ export default {
|
||||
conversationType: 'mention',
|
||||
}),
|
||||
},
|
||||
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/unattended/conversations'),
|
||||
name: 'conversation_unattended',
|
||||
@@ -141,5 +140,24 @@ export default {
|
||||
conversationType: 'unattended',
|
||||
}),
|
||||
},
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/participating/conversations'),
|
||||
name: 'conversation_participating',
|
||||
roles: ['administrator', 'agent'],
|
||||
component: ConversationView,
|
||||
props: () => ({ conversationType: 'participating' }),
|
||||
},
|
||||
{
|
||||
path: frontendURL(
|
||||
'accounts/:accountId/participating/conversations/:conversationId'
|
||||
),
|
||||
name: 'conversation_through_participating',
|
||||
roles: ['administrator', 'agent'],
|
||||
component: ConversationView,
|
||||
props: route => ({
|
||||
conversationId: route.params.conversationId,
|
||||
conversationType: 'participating',
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -216,6 +216,22 @@
|
||||
}}
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
v-model="selectedEmailFlags"
|
||||
class="notification--checkbox"
|
||||
type="checkbox"
|
||||
value="email_participating_conversation_new_message"
|
||||
@input="handleEmailInput"
|
||||
/>
|
||||
<label for="assigned_conversation_new_message">
|
||||
{{
|
||||
$t(
|
||||
'PROFILE_SETTINGS.FORM.EMAIL_NOTIFICATIONS_SECTION.PARTICIPATING_CONVERSATION_NEW_MESSAGE'
|
||||
)
|
||||
}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -315,6 +331,23 @@
|
||||
}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
v-model="selectedPushFlags"
|
||||
class="notification--checkbox"
|
||||
type="checkbox"
|
||||
value="push_participating_conversation_new_message"
|
||||
@input="handlePushInput"
|
||||
/>
|
||||
<label for="assigned_conversation_new_message">
|
||||
{{
|
||||
$t(
|
||||
'PROFILE_SETTINGS.FORM.PUSH_NOTIFICATIONS_SECTION.PARTICIPATING_CONVERSATION_NEW_MESSAGE'
|
||||
)
|
||||
}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@ export const getters = {
|
||||
|
||||
export const actions = {
|
||||
show: async ({ commit }, { conversationId }) => {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, {
|
||||
isFetching: true,
|
||||
});
|
||||
|
||||
@@ -31,21 +31,21 @@ export const actions = {
|
||||
const response = await ConversationInboxApi.fetchParticipants(
|
||||
conversationId
|
||||
);
|
||||
commit(types.SET_CONVERSATION_WATCHERS, {
|
||||
commit(types.SET_CONVERSATION_PARTICIPANTS, {
|
||||
conversationId,
|
||||
data: response.data,
|
||||
});
|
||||
} catch (error) {
|
||||
throwErrorMessage(error);
|
||||
} finally {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, {
|
||||
isFetching: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
update: async ({ commit }, { conversationId, userIds }) => {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, {
|
||||
isUpdating: true,
|
||||
});
|
||||
|
||||
@@ -54,14 +54,14 @@ export const actions = {
|
||||
conversationId,
|
||||
userIds,
|
||||
});
|
||||
commit(types.SET_CONVERSATION_WATCHERS, {
|
||||
commit(types.SET_CONVERSATION_PARTICIPANTS, {
|
||||
conversationId,
|
||||
data: response.data,
|
||||
});
|
||||
} catch (error) {
|
||||
throwErrorMessage(error);
|
||||
} finally {
|
||||
commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, {
|
||||
commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, {
|
||||
isUpdating: false,
|
||||
});
|
||||
}
|
||||
@@ -69,14 +69,14 @@ export const actions = {
|
||||
};
|
||||
|
||||
export const mutations = {
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG]($state, data) {
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG]($state, data) {
|
||||
$state.uiFlags = {
|
||||
...$state.uiFlags,
|
||||
...data,
|
||||
};
|
||||
},
|
||||
|
||||
[types.SET_CONVERSATION_WATCHERS]($state, { data, conversationId }) {
|
||||
[types.SET_CONVERSATION_PARTICIPANTS]($state, { data, conversationId }) {
|
||||
Vue.set($state.records, conversationId, data);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -91,6 +91,12 @@ const getters = {
|
||||
value => value.id === Number(conversationId)
|
||||
);
|
||||
},
|
||||
getConversationParticipants: _state => {
|
||||
return _state.conversationParticipants;
|
||||
},
|
||||
getConversationLastSeen: _state => {
|
||||
return _state.conversationLastSeen;
|
||||
},
|
||||
};
|
||||
|
||||
export default getters;
|
||||
|
||||
@@ -13,6 +13,8 @@ const state = {
|
||||
currentInbox: null,
|
||||
selectedChatId: null,
|
||||
appliedFilters: [],
|
||||
conversationParticipants: [],
|
||||
conversationLastSeen: null,
|
||||
};
|
||||
|
||||
// mutations
|
||||
|
||||
@@ -12,12 +12,12 @@ describe('#actions', () => {
|
||||
axios.get.mockResolvedValue({ data: { id: 1 } });
|
||||
await actions.show({ commit }, { conversationId: 1 });
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }],
|
||||
[
|
||||
types.SET_CONVERSATION_WATCHERS,
|
||||
types.SET_CONVERSATION_PARTICIPANTS,
|
||||
{ conversationId: 1, data: { id: 1 } },
|
||||
],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: false }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
@@ -26,8 +26,8 @@ describe('#actions', () => {
|
||||
actions.show({ commit }, { conversationId: 1 })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: false }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -40,12 +40,12 @@ describe('#actions', () => {
|
||||
{ conversationId: 2, userIds: [{ id: 2 }] }
|
||||
);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }],
|
||||
[
|
||||
types.SET_CONVERSATION_WATCHERS,
|
||||
types.SET_CONVERSATION_PARTICIPANTS,
|
||||
{ conversationId: 2, data: [{ id: 2 }] },
|
||||
],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: false }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
it('sends correct actions if API is error', async () => {
|
||||
@@ -54,8 +54,8 @@ describe('#actions', () => {
|
||||
actions.update({ commit }, { conversationId: 1, content: 'hi' })
|
||||
).rejects.toThrow(Error);
|
||||
expect(commit.mock.calls).toEqual([
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: false }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }],
|
||||
[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,13 +2,13 @@ import types from '../../../mutation-types';
|
||||
import { mutations } from '../../conversationWatchers';
|
||||
|
||||
describe('#mutations', () => {
|
||||
describe('#SET_CONVERSATION_WATCHERS', () => {
|
||||
describe('#SET_CONVERSATION_PARTICIPANTS', () => {
|
||||
it('sets an individual record', () => {
|
||||
let state = {
|
||||
records: {},
|
||||
};
|
||||
|
||||
mutations[types.SET_CONVERSATION_WATCHERS](state, {
|
||||
mutations[types.SET_CONVERSATION_PARTICIPANTS](state, {
|
||||
data: [],
|
||||
conversationId: 1,
|
||||
});
|
||||
@@ -16,7 +16,7 @@ describe('#mutations', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#SET_CONVERSATION_WATCHERS_UI_FLAG', () => {
|
||||
describe('#SET_CONVERSATION_PARTICIPANTS_UI_FLAG', () => {
|
||||
it('set ui flags', () => {
|
||||
let state = {
|
||||
uiFlags: {
|
||||
@@ -25,7 +25,7 @@ describe('#mutations', () => {
|
||||
},
|
||||
};
|
||||
|
||||
mutations[types.SET_CONVERSATION_WATCHERS_UI_FLAG](state, {
|
||||
mutations[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG](state, {
|
||||
isFetching: false,
|
||||
});
|
||||
expect(state.uiFlags).toEqual({
|
||||
|
||||
6
app/javascript/dashboard/store/mutation-types.js
Executable file → Normal file
6
app/javascript/dashboard/store/mutation-types.js
Executable file → Normal file
@@ -21,6 +21,7 @@ export default {
|
||||
CLEAR_CONTACT_CONVERSATIONS: 'CLEAR_CONTACT_CONVERSATIONS',
|
||||
SET_CONVERSATION_FILTERS: 'SET_CONVERSATION_FILTERS',
|
||||
CLEAR_CONVERSATION_FILTERS: 'CLEAR_CONVERSATION_FILTERS',
|
||||
SET_CONVERSATION_LAST_SEEN: 'SET_CONVERSATION_LAST_SEEN',
|
||||
|
||||
SET_CURRENT_CHAT_WINDOW: 'SET_CURRENT_CHAT_WINDOW',
|
||||
CLEAR_CURRENT_CHAT_WINDOW: 'CLEAR_CURRENT_CHAT_WINDOW',
|
||||
@@ -260,6 +261,7 @@ export default {
|
||||
EDIT_MACRO: 'EDIT_MACRO',
|
||||
DELETE_MACRO: 'DELETE_MACRO',
|
||||
|
||||
SET_CONVERSATION_WATCHERS_UI_FLAG: 'SET_CONVERSATION_WATCHERS_UI_FLAG',
|
||||
SET_CONVERSATION_WATCHERS: 'SET_CONVERSATION_WATCHERS',
|
||||
SET_CONVERSATION_PARTICIPANTS_UI_FLAG:
|
||||
'SET_CONVERSATION_PARTICIPANTS_UI_FLAG',
|
||||
SET_CONVERSATION_PARTICIPANTS: 'SET_CONVERSATION_PARTICIPANTS',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user