feat: Add the option for changing the contact/conversation sidebar items order (#3362)
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import uiSettingsMixin from '../uiSettings';
|
||||
import uiSettingsMixin, {
|
||||
DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
} from '../uiSettings';
|
||||
import Vuex from 'vuex';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
@@ -17,6 +19,8 @@ describe('uiSettingsMixin', () => {
|
||||
display_rich_content_editor: false,
|
||||
enter_to_send_enabled: false,
|
||||
is_ct_labels_open: true,
|
||||
conversation_sidebar_items_order: DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
}),
|
||||
};
|
||||
store = new Vuex.Store({ actions, getters });
|
||||
@@ -33,6 +37,8 @@ describe('uiSettingsMixin', () => {
|
||||
display_rich_content_editor: false,
|
||||
enter_to_send_enabled: false,
|
||||
is_ct_labels_open: true,
|
||||
conversation_sidebar_items_order: DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,6 +58,8 @@ describe('uiSettingsMixin', () => {
|
||||
display_rich_content_editor: false,
|
||||
enter_to_send_enabled: true,
|
||||
is_ct_labels_open: true,
|
||||
conversation_sidebar_items_order: DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
},
|
||||
},
|
||||
undefined
|
||||
@@ -75,6 +83,8 @@ describe('uiSettingsMixin', () => {
|
||||
display_rich_content_editor: false,
|
||||
enter_to_send_enabled: false,
|
||||
is_ct_labels_open: false,
|
||||
conversation_sidebar_items_order: DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER,
|
||||
contact_sidebar_items_order: DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER,
|
||||
},
|
||||
},
|
||||
undefined
|
||||
@@ -98,4 +108,36 @@ describe('uiSettingsMixin', () => {
|
||||
).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#conversationSidebarItemsOrder', () => {
|
||||
it('returns correct values', () => {
|
||||
const Component = {
|
||||
render() {},
|
||||
title: 'TestComponent',
|
||||
mixins: [uiSettingsMixin],
|
||||
};
|
||||
const wrapper = shallowMount(Component, { store, localVue });
|
||||
expect(wrapper.vm.conversationSidebarItemsOrder).toEqual([
|
||||
{ name: 'conversation_info' },
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'previous_conversation' },
|
||||
{ name: 'conversation_actions' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('#contactSidebarItemsOrder', () => {
|
||||
it('returns correct values', () => {
|
||||
const Component = {
|
||||
render() {},
|
||||
title: 'TestComponent',
|
||||
mixins: [uiSettingsMixin],
|
||||
};
|
||||
const wrapper = shallowMount(Component, { store, localVue });
|
||||
expect(wrapper.vm.contactSidebarItemsOrder).toEqual([
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'contact_labels' },
|
||||
{ name: 'previous_conversation' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export const DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER = [
|
||||
{ name: 'conversation_info' },
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'previous_conversation' },
|
||||
{ name: 'conversation_actions' },
|
||||
];
|
||||
export const DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER = [
|
||||
{ name: 'contact_attributes' },
|
||||
{ name: 'contact_labels' },
|
||||
{ name: 'previous_conversation' },
|
||||
];
|
||||
export default {
|
||||
computed: {
|
||||
...mapGetters({
|
||||
uiSettings: 'getUISettings',
|
||||
}),
|
||||
conversationSidebarItemsOrder() {
|
||||
const { conversation_sidebar_items_order: itemsOrder } = this.uiSettings;
|
||||
return itemsOrder || DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER;
|
||||
},
|
||||
contactSidebarItemsOrder() {
|
||||
const { contact_sidebar_items_order: itemsOrder } = this.uiSettings;
|
||||
return itemsOrder || DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateUISettings(uiSettings = {}) {
|
||||
|
||||
@@ -12,42 +12,71 @@
|
||||
:contact="contact"
|
||||
@panel-close="onClose"
|
||||
/>
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONTACT_ATTRIBUTES')"
|
||||
:is-open="isContactSidebarItemOpen('is_ct_custom_attr_open')"
|
||||
compact
|
||||
@click="value => toggleSidebarUIState('is_ct_custom_attr_open', value)"
|
||||
<draggable
|
||||
:list="contactSidebarItems"
|
||||
:disabled="!dragEnabled"
|
||||
class="list-group"
|
||||
ghost-class="ghost"
|
||||
@start="dragging = true"
|
||||
@end="onDragEnd"
|
||||
>
|
||||
<custom-attributes
|
||||
:contact-id="contact.id"
|
||||
attribute-type="contact_attribute"
|
||||
attribute-class="conversation--attribute"
|
||||
:custom-attributes="contact.custom_attributes"
|
||||
class="even"
|
||||
/>
|
||||
<custom-attribute-selector
|
||||
attribute-type="contact_attribute"
|
||||
:contact-id="contact.id"
|
||||
/>
|
||||
</accordion-item>
|
||||
<accordion-item
|
||||
:title="$t('CONTACT_PANEL.SIDEBAR_SECTIONS.CONTACT_LABELS')"
|
||||
:is-open="isContactSidebarItemOpen('is_ct_labels_open')"
|
||||
@click="value => toggleSidebarUIState('is_ct_labels_open', value)"
|
||||
>
|
||||
<contact-label :contact-id="contact.id" class="contact-labels" />
|
||||
</accordion-item>
|
||||
<accordion-item
|
||||
:title="$t('CONTACT_PANEL.SIDEBAR_SECTIONS.PREVIOUS_CONVERSATIONS')"
|
||||
:is-open="isContactSidebarItemOpen('is_ct_prev_conv_open')"
|
||||
@click="value => toggleSidebarUIState('is_ct_prev_conv_open', value)"
|
||||
>
|
||||
<contact-conversations
|
||||
v-if="contact.id"
|
||||
:contact-id="contact.id"
|
||||
conversation-id=""
|
||||
/>
|
||||
</accordion-item>
|
||||
<transition-group>
|
||||
<div
|
||||
v-for="element in contactSidebarItems"
|
||||
:key="element.name"
|
||||
class="list-group-item"
|
||||
>
|
||||
<div v-if="element.name === 'contact_attributes'">
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONTACT_ATTRIBUTES')"
|
||||
:is-open="isContactSidebarItemOpen('is_ct_custom_attr_open')"
|
||||
compact
|
||||
@click="
|
||||
value => toggleSidebarUIState('is_ct_custom_attr_open', value)
|
||||
"
|
||||
>
|
||||
<custom-attributes
|
||||
:contact-id="contact.id"
|
||||
attribute-type="contact_attribute"
|
||||
attribute-class="conversation--attribute"
|
||||
:custom-attributes="contact.custom_attributes"
|
||||
class="even"
|
||||
/>
|
||||
<custom-attribute-selector
|
||||
attribute-type="contact_attribute"
|
||||
:contact-id="contact.id"
|
||||
/>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<div v-if="element.name === 'contact_labels'">
|
||||
<accordion-item
|
||||
:title="$t('CONTACT_PANEL.SIDEBAR_SECTIONS.CONTACT_LABELS')"
|
||||
:is-open="isContactSidebarItemOpen('is_ct_labels_open')"
|
||||
@click="value => toggleSidebarUIState('is_ct_labels_open', value)"
|
||||
>
|
||||
<contact-label :contact-id="contact.id" class="contact-labels" />
|
||||
</accordion-item>
|
||||
</div>
|
||||
<div v-if="element.name === 'previous_conversation'">
|
||||
<accordion-item
|
||||
:title="
|
||||
$t('CONTACT_PANEL.SIDEBAR_SECTIONS.PREVIOUS_CONVERSATIONS')
|
||||
"
|
||||
:is-open="isContactSidebarItemOpen('is_ct_prev_conv_open')"
|
||||
@click="
|
||||
value => toggleSidebarUIState('is_ct_prev_conv_open', value)
|
||||
"
|
||||
>
|
||||
<contact-conversations
|
||||
v-if="contact.id"
|
||||
:contact-id="contact.id"
|
||||
conversation-id=""
|
||||
/>
|
||||
</accordion-item>
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -58,7 +87,7 @@ import ContactInfo from 'dashboard/routes/dashboard/conversation/contact/Contact
|
||||
import ContactLabel from 'dashboard/routes/dashboard/contacts/components/ContactLabels.vue';
|
||||
import CustomAttributes from 'dashboard/routes/dashboard/conversation/customAttributes/CustomAttributes.vue';
|
||||
import CustomAttributeSelector from 'dashboard/routes/dashboard/conversation/customAttributes/CustomAttributeSelector.vue';
|
||||
|
||||
import draggable from 'vuedraggable';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
|
||||
export default {
|
||||
@@ -69,6 +98,7 @@ export default {
|
||||
ContactLabel,
|
||||
CustomAttributes,
|
||||
CustomAttributeSelector,
|
||||
draggable,
|
||||
},
|
||||
mixins: [uiSettingsMixin],
|
||||
props: {
|
||||
@@ -85,12 +115,30 @@ export default {
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dragEnabled: true,
|
||||
contactSidebarItems: [],
|
||||
dragging: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasContactAttributes() {
|
||||
const { custom_attributes: customAttributes } = this.contact;
|
||||
return customAttributes && Object.keys(customAttributes).length;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.contactSidebarItems = this.contactSidebarItemsOrder;
|
||||
},
|
||||
methods: {
|
||||
onDragEnd() {
|
||||
this.dragging = false;
|
||||
this.updateUISettings({
|
||||
contact_sidebar_items_order: this.contactSidebarItems,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -4,118 +4,95 @@
|
||||
<i class="ion-chevron-right" />
|
||||
</span>
|
||||
<contact-info :contact="contact" :channel-type="channelType" />
|
||||
<div class="conversation--actions">
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_ACTIONS')"
|
||||
:is-open="isContactSidebarItemOpen('is_conv_actions_open')"
|
||||
@click="value => toggleSidebarUIState('is_conv_actions_open', value)"
|
||||
>
|
||||
<div>
|
||||
<div class="multiselect-wrap--small">
|
||||
<contact-details-item
|
||||
compact
|
||||
:title="$t('CONVERSATION_SIDEBAR.ASSIGNEE_LABEL')"
|
||||
<draggable
|
||||
:list="conversationSidebarItems"
|
||||
:disabled="!dragEnabled"
|
||||
class="list-group"
|
||||
ghost-class="ghost"
|
||||
@start="dragging = true"
|
||||
@end="onDragEnd"
|
||||
>
|
||||
<transition-group>
|
||||
<div
|
||||
v-for="element in conversationSidebarItems"
|
||||
:key="element.name"
|
||||
class="list-group-item"
|
||||
>
|
||||
<div
|
||||
v-if="element.name === 'conversation_actions'"
|
||||
class="conversation--actions"
|
||||
>
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_ACTIONS')"
|
||||
:is-open="isContactSidebarItemOpen('is_conv_actions_open')"
|
||||
@click="
|
||||
value => toggleSidebarUIState('is_conv_actions_open', value)
|
||||
"
|
||||
>
|
||||
<template v-slot:button>
|
||||
<woot-button
|
||||
v-if="showSelfAssign"
|
||||
icon="ion-arrow-right-c"
|
||||
variant="link"
|
||||
size="small"
|
||||
@click="onSelfAssign"
|
||||
>
|
||||
{{ $t('CONVERSATION_SIDEBAR.SELF_ASSIGN') }}
|
||||
</woot-button>
|
||||
</template>
|
||||
</contact-details-item>
|
||||
<multiselect-dropdown
|
||||
:options="agentsList"
|
||||
:selected-item="assignedAgent"
|
||||
:multiselector-title="$t('AGENT_MGMT.MULTI_SELECTOR.TITLE.AGENT')"
|
||||
:multiselector-placeholder="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.PLACEHOLDER')
|
||||
"
|
||||
:no-search-result="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.NO_RESULTS.AGENT')
|
||||
"
|
||||
:input-placeholder="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.PLACEHOLDER.AGENT')
|
||||
"
|
||||
@click="onClickAssignAgent"
|
||||
/>
|
||||
<conversation-action
|
||||
:conversation-id="conversationId"
|
||||
:inbox-id="inboxId"
|
||||
/>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<div class="multiselect-wrap--small">
|
||||
<contact-details-item
|
||||
<div v-else-if="element.name === 'conversation_info'">
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_INFO')"
|
||||
:is-open="isContactSidebarItemOpen('is_conv_details_open')"
|
||||
compact
|
||||
:title="$t('CONVERSATION_SIDEBAR.TEAM_LABEL')"
|
||||
/>
|
||||
<multiselect-dropdown
|
||||
:options="teamsList"
|
||||
:selected-item="assignedTeam"
|
||||
:multiselector-title="$t('AGENT_MGMT.MULTI_SELECTOR.TITLE.TEAM')"
|
||||
:multiselector-placeholder="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.PLACEHOLDER')
|
||||
@click="
|
||||
value => toggleSidebarUIState('is_conv_details_open', value)
|
||||
"
|
||||
:no-search-result="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.NO_RESULTS.TEAM')
|
||||
"
|
||||
:input-placeholder="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.PLACEHOLDER.TEAM')
|
||||
"
|
||||
@click="onClickAssignTeam"
|
||||
/>
|
||||
>
|
||||
<conversation-info
|
||||
:conversation-attributes="conversationAdditionalAttributes"
|
||||
:contact-attributes="contactAdditionalAttributes"
|
||||
>
|
||||
</conversation-info>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<div v-else-if="element.name === 'contact_attributes'">
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONTACT_ATTRIBUTES')"
|
||||
:is-open="isContactSidebarItemOpen('is_contact_attributes_open')"
|
||||
compact
|
||||
@click="
|
||||
value =>
|
||||
toggleSidebarUIState('is_contact_attributes_open', value)
|
||||
"
|
||||
>
|
||||
<custom-attributes
|
||||
attribute-type="contact_attribute"
|
||||
attribute-class="conversation--attribute"
|
||||
class="even"
|
||||
:contact-id="contact.id"
|
||||
/>
|
||||
<custom-attribute-selector
|
||||
attribute-type="contact_attribute"
|
||||
:contact-id="contact.id"
|
||||
/>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<div v-else-if="element.name === 'previous_conversation'">
|
||||
<accordion-item
|
||||
v-if="contact.id"
|
||||
:title="
|
||||
$t('CONVERSATION_SIDEBAR.ACCORDION.PREVIOUS_CONVERSATION')
|
||||
"
|
||||
:is-open="isContactSidebarItemOpen('is_previous_conv_open')"
|
||||
@click="
|
||||
value => toggleSidebarUIState('is_previous_conv_open', value)
|
||||
"
|
||||
>
|
||||
<contact-conversations
|
||||
:contact-id="contact.id"
|
||||
:conversation-id="conversationId"
|
||||
/>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<contact-details-item
|
||||
compact
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_LABELS')"
|
||||
/>
|
||||
<conversation-labels :conversation-id="conversationId" />
|
||||
</div>
|
||||
</accordion-item>
|
||||
</div>
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_INFO')"
|
||||
:is-open="isContactSidebarItemOpen('is_conv_details_open')"
|
||||
compact
|
||||
@click="value => toggleSidebarUIState('is_conv_details_open', value)"
|
||||
>
|
||||
<conversation-info
|
||||
:conversation-attributes="conversationAdditionalAttributes"
|
||||
:contact-attributes="contactAdditionalAttributes"
|
||||
>
|
||||
</conversation-info>
|
||||
</accordion-item>
|
||||
<accordion-item
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONTACT_ATTRIBUTES')"
|
||||
:is-open="isContactSidebarItemOpen('is_contact_attributes_open')"
|
||||
compact
|
||||
@click="
|
||||
value => toggleSidebarUIState('is_contact_attributes_open', value)
|
||||
"
|
||||
>
|
||||
<custom-attributes
|
||||
attribute-type="contact_attribute"
|
||||
attribute-class="conversation--attribute"
|
||||
class="even"
|
||||
:contact-id="contact.id"
|
||||
/>
|
||||
<custom-attribute-selector
|
||||
attribute-type="contact_attribute"
|
||||
:contact-id="contact.id"
|
||||
/>
|
||||
</accordion-item>
|
||||
|
||||
<accordion-item
|
||||
v-if="contact.id"
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.PREVIOUS_CONVERSATION')"
|
||||
:is-open="isContactSidebarItemOpen('is_previous_conv_open')"
|
||||
@click="value => toggleSidebarUIState('is_previous_conv_open', value)"
|
||||
>
|
||||
<contact-conversations
|
||||
:contact-id="contact.id"
|
||||
:conversation-id="conversationId"
|
||||
/>
|
||||
</accordion-item>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -126,27 +103,25 @@ import agentMixin from '../../../mixins/agentMixin';
|
||||
|
||||
import AccordionItem from 'dashboard/components/Accordion/AccordionItem';
|
||||
import ContactConversations from './ContactConversations.vue';
|
||||
import ContactDetailsItem from './ContactDetailsItem.vue';
|
||||
import ConversationAction from './ConversationAction.vue';
|
||||
|
||||
import ContactInfo from './contact/ContactInfo';
|
||||
import ConversationInfo from './ConversationInfo';
|
||||
import ConversationLabels from './labels/LabelBox.vue';
|
||||
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
|
||||
import CustomAttributes from './customAttributes/CustomAttributes.vue';
|
||||
import CustomAttributeSelector from './customAttributes/CustomAttributeSelector.vue';
|
||||
|
||||
import draggable from 'vuedraggable';
|
||||
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
AccordionItem,
|
||||
ContactConversations,
|
||||
ContactDetailsItem,
|
||||
ContactInfo,
|
||||
ConversationInfo,
|
||||
ConversationLabels,
|
||||
MultiselectDropdown,
|
||||
CustomAttributes,
|
||||
CustomAttributeSelector,
|
||||
ConversationAction,
|
||||
draggable,
|
||||
},
|
||||
mixins: [alertMixin, agentMixin, uiSettingsMixin],
|
||||
props: {
|
||||
@@ -163,6 +138,13 @@ export default {
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dragEnabled: true,
|
||||
conversationSidebarItems: [],
|
||||
dragging: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentChat: 'getSelectedChat',
|
||||
@@ -194,61 +176,6 @@ export default {
|
||||
const { custom_attributes: customAttributes } = this.contact;
|
||||
return customAttributes && Object.keys(customAttributes).length;
|
||||
},
|
||||
teamsList() {
|
||||
if (this.assignedTeam) {
|
||||
return [
|
||||
{
|
||||
id: 0,
|
||||
name: 'None',
|
||||
},
|
||||
...this.teams,
|
||||
];
|
||||
}
|
||||
return this.teams;
|
||||
},
|
||||
assignedAgent: {
|
||||
get() {
|
||||
return this.currentChat.meta.assignee;
|
||||
},
|
||||
set(agent) {
|
||||
const agentId = agent ? agent.id : 0;
|
||||
this.$store.dispatch('setCurrentChatAssignee', agent);
|
||||
this.$store
|
||||
.dispatch('assignAgent', {
|
||||
conversationId: this.currentChat.id,
|
||||
agentId,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_AGENT'));
|
||||
});
|
||||
},
|
||||
},
|
||||
assignedTeam: {
|
||||
get() {
|
||||
return this.currentChat.meta.team;
|
||||
},
|
||||
set(team) {
|
||||
const teamId = team ? team.id : 0;
|
||||
this.$store.dispatch('setCurrentChatTeam', team);
|
||||
this.$store
|
||||
.dispatch('assignTeam', {
|
||||
conversationId: this.currentChat.id,
|
||||
teamId,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_TEAM'));
|
||||
});
|
||||
},
|
||||
},
|
||||
showSelfAssign() {
|
||||
if (!this.assignedAgent) {
|
||||
return true;
|
||||
}
|
||||
if (this.assignedAgent.id !== this.currentUser.id) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
conversationId(newConversationId, prevConversationId) {
|
||||
@@ -261,6 +188,7 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.conversationSidebarItems = this.conversationSidebarItemsOrder;
|
||||
this.getContactDetails();
|
||||
this.$store.dispatch('attributes/get', 0);
|
||||
},
|
||||
@@ -281,43 +209,12 @@ export default {
|
||||
openTranscriptModal() {
|
||||
this.showTranscriptModal = true;
|
||||
},
|
||||
onSelfAssign() {
|
||||
const {
|
||||
account_id,
|
||||
availability_status,
|
||||
available_name,
|
||||
email,
|
||||
id,
|
||||
name,
|
||||
role,
|
||||
avatar_url,
|
||||
} = this.currentUser;
|
||||
const selfAssign = {
|
||||
account_id,
|
||||
availability_status,
|
||||
available_name,
|
||||
email,
|
||||
id,
|
||||
name,
|
||||
role,
|
||||
thumbnail: avatar_url,
|
||||
};
|
||||
this.assignedAgent = selfAssign;
|
||||
},
|
||||
onClickAssignAgent(selectedItem) {
|
||||
if (this.assignedAgent && this.assignedAgent.id === selectedItem.id) {
|
||||
this.assignedAgent = null;
|
||||
} else {
|
||||
this.assignedAgent = selectedItem;
|
||||
}
|
||||
},
|
||||
|
||||
onClickAssignTeam(selectedItemTeam) {
|
||||
if (this.assignedTeam && this.assignedTeam.id === selectedItemTeam.id) {
|
||||
this.assignedTeam = null;
|
||||
} else {
|
||||
this.assignedTeam = selectedItemTeam;
|
||||
}
|
||||
onDragEnd() {
|
||||
this.dragging = false;
|
||||
this.updateUISettings({
|
||||
conversation_sidebar_items_order: this.conversationSidebarItems,
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="multiselect-wrap--small">
|
||||
<contact-details-item
|
||||
compact
|
||||
:title="$t('CONVERSATION_SIDEBAR.ASSIGNEE_LABEL')"
|
||||
>
|
||||
<template v-slot:button>
|
||||
<woot-button
|
||||
v-if="showSelfAssign"
|
||||
icon="ion-arrow-right-c"
|
||||
variant="link"
|
||||
size="small"
|
||||
@click="onSelfAssign"
|
||||
>
|
||||
{{ $t('CONVERSATION_SIDEBAR.SELF_ASSIGN') }}
|
||||
</woot-button>
|
||||
</template>
|
||||
</contact-details-item>
|
||||
<multiselect-dropdown
|
||||
:options="agentsList"
|
||||
:selected-item="assignedAgent"
|
||||
:multiselector-title="$t('AGENT_MGMT.MULTI_SELECTOR.TITLE.AGENT')"
|
||||
:multiselector-placeholder="$t('AGENT_MGMT.MULTI_SELECTOR.PLACEHOLDER')"
|
||||
:no-search-result="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.NO_RESULTS.AGENT')
|
||||
"
|
||||
:input-placeholder="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.PLACEHOLDER.AGENT')
|
||||
"
|
||||
@click="onClickAssignAgent"
|
||||
/>
|
||||
</div>
|
||||
<div class="multiselect-wrap--small">
|
||||
<contact-details-item
|
||||
compact
|
||||
:title="$t('CONVERSATION_SIDEBAR.TEAM_LABEL')"
|
||||
/>
|
||||
<multiselect-dropdown
|
||||
:options="teamsList"
|
||||
:selected-item="assignedTeam"
|
||||
:multiselector-title="$t('AGENT_MGMT.MULTI_SELECTOR.TITLE.TEAM')"
|
||||
:multiselector-placeholder="$t('AGENT_MGMT.MULTI_SELECTOR.PLACEHOLDER')"
|
||||
:no-search-result="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.NO_RESULTS.TEAM')
|
||||
"
|
||||
:input-placeholder="
|
||||
$t('AGENT_MGMT.MULTI_SELECTOR.SEARCH.PLACEHOLDER.TEAM')
|
||||
"
|
||||
@click="onClickAssignTeam"
|
||||
/>
|
||||
</div>
|
||||
<contact-details-item
|
||||
compact
|
||||
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_LABELS')"
|
||||
/>
|
||||
<conversation-labels :conversation-id="conversationId" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import alertMixin from 'shared/mixins/alertMixin';
|
||||
import ContactDetailsItem from './ContactDetailsItem.vue';
|
||||
import MultiselectDropdown from 'shared/components/ui/MultiselectDropdown.vue';
|
||||
import ConversationLabels from './labels/LabelBox.vue';
|
||||
import agentMixin from '../../../mixins/agentMixin';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ContactDetailsItem,
|
||||
MultiselectDropdown,
|
||||
ConversationLabels,
|
||||
},
|
||||
mixins: [agentMixin, alertMixin],
|
||||
props: {
|
||||
conversationId: {
|
||||
type: [Number, String],
|
||||
required: true,
|
||||
},
|
||||
inboxId: {
|
||||
type: Number,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentChat: 'getSelectedChat',
|
||||
teams: 'teams/getTeams',
|
||||
currentUser: 'getCurrentUser',
|
||||
}),
|
||||
teamsList() {
|
||||
if (this.assignedTeam) {
|
||||
return [
|
||||
{
|
||||
id: 0,
|
||||
name: 'None',
|
||||
},
|
||||
...this.teams,
|
||||
];
|
||||
}
|
||||
return this.teams;
|
||||
},
|
||||
assignedAgent: {
|
||||
get() {
|
||||
return this.currentChat.meta.assignee;
|
||||
},
|
||||
set(agent) {
|
||||
const agentId = agent ? agent.id : 0;
|
||||
this.$store.dispatch('setCurrentChatAssignee', agent);
|
||||
this.$store
|
||||
.dispatch('assignAgent', {
|
||||
conversationId: this.currentChat.id,
|
||||
agentId,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_AGENT'));
|
||||
});
|
||||
},
|
||||
},
|
||||
assignedTeam: {
|
||||
get() {
|
||||
return this.currentChat.meta.team;
|
||||
},
|
||||
set(team) {
|
||||
const teamId = team ? team.id : 0;
|
||||
this.$store.dispatch('setCurrentChatTeam', team);
|
||||
this.$store
|
||||
.dispatch('assignTeam', {
|
||||
conversationId: this.currentChat.id,
|
||||
teamId,
|
||||
})
|
||||
.then(() => {
|
||||
this.showAlert(this.$t('CONVERSATION.CHANGE_TEAM'));
|
||||
});
|
||||
},
|
||||
},
|
||||
showSelfAssign() {
|
||||
if (!this.assignedAgent) {
|
||||
return true;
|
||||
}
|
||||
if (this.assignedAgent.id !== this.currentUser.id) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onSelfAssign() {
|
||||
const {
|
||||
account_id,
|
||||
availability_status,
|
||||
available_name,
|
||||
email,
|
||||
id,
|
||||
name,
|
||||
role,
|
||||
avatar_url,
|
||||
} = this.currentUser;
|
||||
const selfAssign = {
|
||||
account_id,
|
||||
availability_status,
|
||||
available_name,
|
||||
email,
|
||||
id,
|
||||
name,
|
||||
role,
|
||||
thumbnail: avatar_url,
|
||||
};
|
||||
this.assignedAgent = selfAssign;
|
||||
},
|
||||
onClickAssignAgent(selectedItem) {
|
||||
if (this.assignedAgent && this.assignedAgent.id === selectedItem.id) {
|
||||
this.assignedAgent = null;
|
||||
} else {
|
||||
this.assignedAgent = selectedItem;
|
||||
}
|
||||
},
|
||||
|
||||
onClickAssignTeam(selectedItemTeam) {
|
||||
if (this.assignedTeam && this.assignedTeam.id === selectedItemTeam.id) {
|
||||
this.assignedTeam = null;
|
||||
} else {
|
||||
this.assignedTeam = selectedItemTeam;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -65,6 +65,7 @@
|
||||
"vue-template-compiler": "2.6.12",
|
||||
"vue-upload-component": "2.8.22",
|
||||
"vue2-datepicker": "^3.9.1",
|
||||
"vuedraggable": "^2.24.3",
|
||||
"vuelidate": "0.7.6",
|
||||
"vuex": "~2.1.1",
|
||||
"vuex-router-sync": "~4.1.2"
|
||||
|
||||
12
yarn.lock
12
yarn.lock
@@ -13540,6 +13540,11 @@ sort-keys@^1.0.0:
|
||||
dependencies:
|
||||
is-plain-obj "^1.0.0"
|
||||
|
||||
sortablejs@1.10.2:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz#6e40364d913f98b85a14f6678f92b5c1221f5290"
|
||||
integrity sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A==
|
||||
|
||||
source-list-map@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
|
||||
@@ -15112,6 +15117,13 @@ vue@2.6.12, vue@^2.6.12:
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"
|
||||
integrity sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==
|
||||
|
||||
vuedraggable@^2.24.3:
|
||||
version "2.24.3"
|
||||
resolved "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.3.tgz#43c93849b746a24ce503e123d5b259c701ba0d19"
|
||||
integrity sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==
|
||||
dependencies:
|
||||
sortablejs "1.10.2"
|
||||
|
||||
vuelidate@0.7.6:
|
||||
version "0.7.6"
|
||||
resolved "https://registry.yarnpkg.com/vuelidate/-/vuelidate-0.7.6.tgz#84100c13b943470660d0416642845cd2a1edf4b2"
|
||||
|
||||
Reference in New Issue
Block a user