chore: Update contact sidebar with accordion (#3002)

This commit is contained in:
Pranav Raj S 2021-09-13 18:08:58 +05:30 committed by GitHub
parent 328edd24de
commit f2e2a0b7ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 147 additions and 129 deletions

View file

@ -1,33 +1,27 @@
<template>
<div>
<h6 class="text-block-title">
<i class="title-icon ion-pricetags" />
{{ $t('CONTACT_PANEL.LABELS.CONTACT.TITLE') }}
</h6>
<div v-on-clickaway="closeDropdownLabel" class="label-wrap">
<add-label @add="toggleLabels" />
<woot-label
v-for="label in savedLabels"
:key="label.id"
:title="label.title"
:description="label.description"
:show-close="true"
:bg-color="label.color"
@click="removeItem"
/>
<div class="dropdown-wrap">
<div
:class="{ 'dropdown-pane--open': showSearchDropdownLabel }"
class="dropdown-pane"
>
<label-dropdown
v-if="showSearchDropdownLabel"
:account-labels="allLabels"
:selected-labels="selectedLabels"
@add="addItem"
@remove="removeItem"
/>
</div>
<div v-on-clickaway="closeDropdownLabel" class="label-wrap">
<add-label @add="toggleLabels" />
<woot-label
v-for="label in savedLabels"
:key="label.id"
:title="label.title"
:description="label.description"
:show-close="true"
:bg-color="label.color"
@click="removeItem"
/>
<div class="dropdown-wrap">
<div
:class="{ 'dropdown-pane--open': showSearchDropdownLabel }"
class="dropdown-pane"
>
<label-dropdown
v-if="showSearchDropdownLabel"
:account-labels="allLabels"
:selected-labels="selectedLabels"
@add="addItem"
@remove="removeItem"
/>
</div>
</div>
</div>
@ -96,7 +90,6 @@ export default {
.label-wrap {
position: relative;
margin-left: var(--space-two);
line-height: var(--space-medium);
.dropdown-wrap {

View file

@ -37,7 +37,12 @@
"MUTED_SUCCESS": "This conversation is muted for 6 hours",
"UNMUTED_SUCCESS": "This conversation is unmuted",
"SEND_TRANSCRIPT": "Send Transcript",
"EDIT_LABEL": "Edit"
"EDIT_LABEL": "Edit",
"SIDEBAR_SECTIONS": {
"CUSTOM_ATTRIBUTES": "Custom Attributes",
"CONTACT_LABELS": "Contact Labels",
"PREVIOUS_CONVERSATIONS": "Previous Conversations"
}
},
"EDIT_CONTACT": {
"BUTTON_LABEL": "Edit Contact",
@ -186,8 +191,8 @@
}
},
"CUSTOM_ATTRIBUTES": {
"TITLE": "Custom Attributes",
"BUTTON": "Add custom attribute",
"NOT_AVAILABLE": "There are no custom attributes available for this contact.",
"ADD": {
"TITLE": "Create custom attribute",
"DESC": "Add custom information to this contact."

View file

@ -11,11 +11,12 @@ describe('uiSettingsMixin', () => {
let store;
beforeEach(() => {
actions = { updateUISettings: jest.fn() };
actions = { updateUISettings: jest.fn(), toggleSidebarUIState: jest.fn() };
getters = {
getUISettings: () => ({
display_rich_content_editor: false,
enter_to_send_enabled: false,
is_ct_labels_open: true,
}),
};
store = new Vuex.Store({ actions, getters });
@ -31,26 +32,70 @@ describe('uiSettingsMixin', () => {
expect(wrapper.vm.uiSettings).toEqual({
display_rich_content_editor: false,
enter_to_send_enabled: false,
is_ct_labels_open: true,
});
});
it('dispatches store actions correctly', () => {
const Component = {
render() {},
title: 'TestComponent',
mixins: [uiSettingsMixin],
};
const wrapper = shallowMount(Component, { store, localVue });
wrapper.vm.updateUISettings({ enter_to_send_enabled: true });
expect(actions.updateUISettings).toHaveBeenCalledWith(
expect.anything(),
{
uiSettings: {
display_rich_content_editor: false,
enter_to_send_enabled: true,
describe('#updateUISettings', () => {
it('dispatches store actions correctly', () => {
const Component = {
render() {},
title: 'TestComponent',
mixins: [uiSettingsMixin],
};
const wrapper = shallowMount(Component, { store, localVue });
wrapper.vm.updateUISettings({ enter_to_send_enabled: true });
expect(actions.updateUISettings).toHaveBeenCalledWith(
expect.anything(),
{
uiSettings: {
display_rich_content_editor: false,
enter_to_send_enabled: true,
is_ct_labels_open: true,
},
},
},
undefined
);
undefined
);
});
});
describe('#toggleSidebarUIState', () => {
it('dispatches store actions correctly', () => {
const Component = {
render() {},
title: 'TestComponent',
mixins: [uiSettingsMixin],
};
const wrapper = shallowMount(Component, { store, localVue });
wrapper.vm.toggleSidebarUIState('is_ct_labels_open');
expect(actions.updateUISettings).toHaveBeenCalledWith(
expect.anything(),
{
uiSettings: {
display_rich_content_editor: false,
enter_to_send_enabled: false,
is_ct_labels_open: false,
},
},
undefined
);
});
});
describe('#isContactSidebarItemOpen', () => {
it('returns correct values', () => {
const Component = {
render() {},
title: 'TestComponent',
mixins: [uiSettingsMixin],
};
const wrapper = shallowMount(Component, { store, localVue });
expect(wrapper.vm.isContactSidebarItemOpen('is_ct_labels_open')).toEqual(
true
);
expect(
wrapper.vm.isContactSidebarItemOpen('is_ct_prev_conv_open')
).toEqual(false);
});
});
});

View file

@ -15,5 +15,12 @@ export default {
},
});
},
isContactSidebarItemOpen(key) {
const { [key]: isOpen } = this.uiSettings;
return !!isOpen;
},
toggleSidebarUIState(key) {
this.updateUISettings({ [key]: !this.isContactSidebarItemOpen(key) });
},
},
};

View file

@ -4,32 +4,54 @@
<i class="ion-android-close close-icon" />
</span>
<contact-info show-new-message :contact="contact" />
<contact-custom-attributes
v-if="hasContactAttributes"
:custom-attributes="contact.custom_attributes"
/>
<contact-label :contact-id="contact.id" class="contact-labels" />
<contact-conversations
v-if="contact.id"
:contact-id="contact.id"
conversation-id=""
/>
<accordion-item
:title="$t('CONTACT_PANEL.SIDEBAR_SECTIONS.CUSTOM_ATTRIBUTES')"
:is-open="isContactSidebarItemOpen('is_ct_custom_attr_open')"
@click="value => toggleSidebarUIState('is_ct_custom_attr_open', value)"
>
<contact-custom-attributes
:custom-attributes="contact.custom_attributes"
/>
</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>
</div>
</template>
<script>
import AccordionItem from 'dashboard/components/Accordion/AccordionItem';
import ContactConversations from 'dashboard/routes/dashboard/conversation/ContactConversations';
import ContactInfo from 'dashboard/routes/dashboard/conversation/contact/ContactInfo';
import ContactCustomAttributes from 'dashboard/routes/dashboard/conversation/ContactCustomAttributes';
import ContactInfo from 'dashboard/routes/dashboard/conversation/contact/ContactInfo';
import ContactLabel from 'dashboard/routes/dashboard/contacts/components/ContactLabels.vue';
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
export default {
components: {
ContactCustomAttributes,
AccordionItem,
ContactConversations,
ContactCustomAttributes,
ContactInfo,
ContactLabel,
},
mixins: [uiSettingsMixin],
props: {
contact: {
type: Object,
@ -64,11 +86,6 @@ export default {
overflow: auto;
position: relative;
border-left: 1px solid var(--color-border);
padding: var(--space-medium) var(--space-two);
.contact-labels {
padding-bottom: var(--space-normal);
}
}
.close-button {

View file

@ -1,11 +1,5 @@
<template>
<div class="contact-conversation--panel">
<contact-details-item
v-if="showTitle"
:title="$t('CONTACT_PANEL.CONVERSATIONS.TITLE')"
icon="ion-chatboxes"
emoji="💬"
/>
<div v-if="!uiFlags.isFetching" class="contact-conversation__wrap">
<div v-if="!previousConversations.length" class="no-label-message">
<span>
@ -28,22 +22,16 @@
</template>
<script>
import ConversationCard from 'dashboard/components/widgets/conversation/ConversationCard.vue';
import ConversationCard from 'dashboard/components/widgets/conversation/ConversationCard';
import { mapGetters } from 'vuex';
import Spinner from 'shared/components/Spinner.vue';
import ContactDetailsItem from './ContactDetailsItem.vue';
import Spinner from 'shared/components/Spinner';
export default {
components: {
ConversationCard,
ContactDetailsItem,
Spinner,
},
props: {
showTitle: {
type: Boolean,
default: true,
},
contactId: {
type: [String, Number],
required: true,

View file

@ -1,11 +1,5 @@
<template>
<div class="custom-attributes--panel">
<contact-details-item
v-if="showTitle"
:title="$t('CUSTOM_ATTRIBUTES.TITLE')"
icon="ion-code"
emoji="📕"
/>
<div
v-for="attribute in listOfAttributes"
:key="attribute"
@ -18,23 +12,17 @@
<span v-html="valueWithLink(customAttributes[attribute])"></span>
</div>
</div>
<p v-if="!listOfAttributes.length">
{{ $t('CUSTOM_ATTRIBUTES.NOT_AVAILABLE') }}
</p>
</div>
</template>
<script>
import ContactDetailsItem from './ContactDetailsItem.vue';
import MessageFormatter from 'shared/helpers/MessageFormatter.js';
export default {
components: {
ContactDetailsItem,
},
props: {
showTitle: {
type: Boolean,
default: true,
},
customAttributes: {
type: Object,
default: () => ({}),

View file

@ -8,7 +8,7 @@
<accordion-item
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_ACTIONS')"
:is-open="isContactSidebarItemOpen('is_conv_actions_open')"
@click="value => onContactItemClick('is_conv_actions_open', value)"
@click="value => toggleSidebarUIState('is_conv_actions_open', value)"
>
<div>
<div class="multiselect-wrap--small">
@ -66,10 +66,7 @@
<contact-details-item
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_LABELS')"
/>
<conversation-labels
:show-title="false"
:conversation-id="conversationId"
/>
<conversation-labels :conversation-id="conversationId" />
</div>
</accordion-item>
</div>
@ -78,7 +75,7 @@
v-if="browser.browser_name"
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_INFO')"
:is-open="isContactSidebarItemOpen('is_conv_details_open')"
@click="value => onContactItemClick('is_conv_details_open', value)"
@click="value => toggleSidebarUIState('is_conv_details_open', value)"
>
<div class="conversation--details">
<contact-details-item
@ -133,10 +130,11 @@
v-if="hasContactAttributes"
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONTACT_ATTRIBUTES')"
:is-open="isContactSidebarItemOpen('is_contact_attributes_open')"
@click="value => onContactItemClick('is_contact_attributes_open', value)"
@click="
value => toggleSidebarUIState('is_contact_attributes_open', value)
"
>
<contact-custom-attributes
:show-title="false"
:custom-attributes="contact.custom_attributes"
/>
</accordion-item>
@ -144,10 +142,9 @@
v-if="contact.id"
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.PREVIOUS_CONVERSATION')"
:is-open="isContactSidebarItemOpen('is_previous_conv_open')"
@click="value => onContactItemClick('is_previous_conv_open', value)"
@click="value => toggleSidebarUIState('is_previous_conv_open', value)"
>
<contact-conversations
:show-title="false"
:contact-id="contact.id"
:conversation-id="conversationId"
/>
@ -335,16 +332,6 @@ export default {
this.getContactDetails();
},
methods: {
onContactItemClick(key) {
this.updateUISettings({ [key]: !this.isContactSidebarItemOpen(key) });
},
isContactSidebarItemOpen(key) {
if (this.currentChat.id) {
const { [key]: isOpen } = this.uiSettings;
return isOpen;
}
return false;
},
onPanelToggle() {
this.onToggle();
},

View file

@ -4,12 +4,6 @@
v-if="!conversationUiFlags.isFetching"
class="contact-conversation--list"
>
<contact-details-item
v-if="showTitle"
:title="$t('CONTACT_PANEL.LABELS.CONVERSATION.TITLE')"
icon="ion-pricetags"
emoji="🏷️"
/>
<div
v-on-clickaway="closeDropdownLabel"
class="label-wrap"
@ -48,7 +42,6 @@
<script>
import { mapGetters } from 'vuex';
import ContactDetailsItem from '../ContactDetailsItem';
import Spinner from 'shared/components/Spinner';
import LabelDropdown from 'shared/components/ui/label/LabelDropdown';
import AddLabel from 'shared/components/ui/dropdown/AddLabel';
@ -56,7 +49,6 @@ import { mixin as clickaway } from 'vue-clickaway';
export default {
components: {
ContactDetailsItem,
Spinner,
LabelDropdown,
AddLabel,
@ -64,10 +56,6 @@ export default {
mixins: [clickaway],
props: {
showTitle: {
type: Boolean,
default: true,
},
conversationId: {
type: Number,
required: true,
@ -89,7 +77,7 @@ export default {
},
...mapGetters({
conversationUiFlags: 'contactConversations/getUIFlags',
conversationUiFlags: 'conversationLabels/getUIFlags',
labelUiFlags: 'conversationLabels/getUIFlags',
accountLabels: 'labels/getLabels',
}),