Feature: Add/Edit conversation labels (#488)
Co-authored-by: Pranav Raj S <pranavrajs@gmail.com>
This commit is contained in:
committed by
GitHub
parent
77473dc2aa
commit
e61ba95cf7
@@ -1,13 +1,10 @@
|
||||
<template>
|
||||
<div class="contact-conversation--panel">
|
||||
<contact-details-item
|
||||
icon="ion-chatbubbles"
|
||||
:title="$t('CONTACT_PANEL.CONVERSATIONS.TITLE')"
|
||||
/>
|
||||
<contact-details-item :title="$t('CONTACT_PANEL.CONVERSATIONS.TITLE')" />
|
||||
<div v-if="!uiFlags.isFetching">
|
||||
<i v-if="!previousConversations.length">
|
||||
<p v-if="!previousConversations.length" class="no-results">
|
||||
{{ $t('CONTACT_PANEL.CONVERSATIONS.NO_RECORDS_FOUND') }}
|
||||
</i>
|
||||
</p>
|
||||
<div v-else class="contact-conversation--list">
|
||||
<conversation-card
|
||||
v-for="conversation in previousConversations"
|
||||
@@ -78,11 +75,13 @@ export default {
|
||||
@import '~dashboard/assets/scss/mixins';
|
||||
|
||||
.contact-conversation--panel {
|
||||
@include border-normal-top;
|
||||
padding: $space-medium;
|
||||
padding: $space-normal $space-normal $space-normal $space-medium;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.contact-conversation--list {
|
||||
margin-top: -$space-normal;
|
||||
.no-results {
|
||||
margin: 0;
|
||||
color: $color-gray;
|
||||
padding: 0 $space-small;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="conv-details--item">
|
||||
<div class="conv-details--item__label">
|
||||
<i :class="icon" class="conv-details--item__icon"></i>
|
||||
<h4 class="conv-details--item__label">
|
||||
<i v-if="icon" :class="icon" class="conv-details--item__icon"></i>
|
||||
{{ title }}
|
||||
</div>
|
||||
</h4>
|
||||
<div v-if="value" class="conv-details--item__value">
|
||||
{{ value }}
|
||||
</div>
|
||||
@@ -14,7 +14,7 @@
|
||||
export default {
|
||||
props: {
|
||||
title: { type: String, required: true },
|
||||
icon: { type: String, required: true },
|
||||
icon: { type: String, default: '' },
|
||||
value: { type: [String, Number], default: '' },
|
||||
},
|
||||
};
|
||||
@@ -25,23 +25,25 @@ export default {
|
||||
@import '~dashboard/assets/scss/mixins';
|
||||
|
||||
.conv-details--item {
|
||||
padding-bottom: $space-normal;
|
||||
padding-bottom: $space-medium;
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.conv-details--item__icon {
|
||||
padding-right: $space-micro;
|
||||
padding-right: $space-smaller;
|
||||
}
|
||||
|
||||
.conv-details--item__label {
|
||||
font-weight: $font-weight-medium;
|
||||
margin-bottom: $space-micro;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.conv-details--item__value {
|
||||
word-break: break-all;
|
||||
margin-top: $space-small;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -48,6 +48,12 @@
|
||||
{{ contact.additional_attributes.description }}
|
||||
</div>
|
||||
</div>
|
||||
<conversation-labels :conversation-id="conversationId" />
|
||||
<contact-conversations
|
||||
v-if="contact.id"
|
||||
:contact-id="contact.id"
|
||||
:conversation-id="conversationId"
|
||||
/>
|
||||
<div v-if="browser" class="conversation--details">
|
||||
<contact-details-item
|
||||
v-if="browser.browser_name"
|
||||
@@ -74,13 +80,6 @@
|
||||
icon="ion-clock"
|
||||
/>
|
||||
</div>
|
||||
<contact-conversations
|
||||
v-if="contact.id"
|
||||
:contact-id="contact.id"
|
||||
:conversation-id="conversationId"
|
||||
/>
|
||||
|
||||
<conversation-labels :conversation-id="conversationId" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -164,15 +163,13 @@ export default {
|
||||
@include border-normal-left;
|
||||
font-size: $font-size-small;
|
||||
overflow-y: auto;
|
||||
background: $color-white;
|
||||
background: white;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.contact--profile {
|
||||
width: 100%;
|
||||
padding: $space-normal $space-medium $zero;
|
||||
padding: $space-medium $space-normal 0 $space-medium;
|
||||
align-items: center;
|
||||
|
||||
.user-thumbnail-box {
|
||||
margin-right: $space-normal;
|
||||
}
|
||||
@@ -191,9 +188,10 @@ export default {
|
||||
|
||||
.contact--name {
|
||||
@include text-ellipsis;
|
||||
text-transform: capitalize;
|
||||
|
||||
font-weight: $font-weight-bold;
|
||||
font-size: $font-size-default;
|
||||
font-size: $font-size-medium;
|
||||
}
|
||||
|
||||
.contact--email {
|
||||
@@ -210,8 +208,7 @@ export default {
|
||||
}
|
||||
|
||||
.conversation--details {
|
||||
padding: $space-medium;
|
||||
width: 100%;
|
||||
padding: $space-two $space-normal $space-two $space-medium;
|
||||
}
|
||||
|
||||
.conversation--labels {
|
||||
|
||||
@@ -1,21 +1,42 @@
|
||||
<template>
|
||||
<div class="contact-conversation--panel">
|
||||
<contact-details-item
|
||||
icon="ion-pricetags"
|
||||
:title="$t('CONTACT_PANEL.LABELS.TITLE')"
|
||||
/>
|
||||
<div v-if="!uiFlags.isFetching">
|
||||
<i v-if="!labels.length">
|
||||
{{ $t('CONTACT_PANEL.LABELS.NO_RECORDS_FOUND') }}
|
||||
</i>
|
||||
<div v-else class="contact-conversation--list">
|
||||
<span
|
||||
v-for="label in labels"
|
||||
:key="label"
|
||||
class="conversation--label label primary"
|
||||
>
|
||||
{{ label }}
|
||||
</span>
|
||||
<div
|
||||
class="contact-conversation--panel sidebar-labels-wrap"
|
||||
:class="hasEditedClass"
|
||||
>
|
||||
<div v-if="!conversationUiFlags.isFetching" class="wrap">
|
||||
<div class="contact-conversation--list">
|
||||
<label class="select-tags">
|
||||
{{ $t('CONTACT_PANEL.LABELS.TITLE') }}
|
||||
<multiselect
|
||||
v-model="selectedLabels"
|
||||
:options="savedLabels"
|
||||
:tag-placeholder="$t('CONTACT_PANEL.LABELS.TAG_PLACEHOLDER')"
|
||||
:placeholder="$t('CONTACT_PANEL.LABELS.PLACEHOLDER')"
|
||||
:multiple="true"
|
||||
:taggable="true"
|
||||
hide-selected
|
||||
:show-labels="false"
|
||||
@tag="addLabel"
|
||||
/>
|
||||
</label>
|
||||
<div class="row align-middle align-justify">
|
||||
<span v-if="labelUiFlags.isError" class="error">{{
|
||||
$t('CONTACT_PANEL.LABELS.UPDATE_ERROR')
|
||||
}}</span>
|
||||
<button
|
||||
v-if="hasEdited"
|
||||
type="button"
|
||||
class="button nice tiny"
|
||||
@click="onUpdateLabels"
|
||||
>
|
||||
<spinner v-if="labelUiFlags.isUpdating" size="tiny" />
|
||||
{{
|
||||
labelUiFlags.isUpdating
|
||||
? 'saving...'
|
||||
: $t('CONTACT_PANEL.LABELS.UPDATE_BUTTON')
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<spinner v-else></spinner>
|
||||
@@ -24,12 +45,10 @@
|
||||
|
||||
<script>
|
||||
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: {
|
||||
ContactDetailsItem,
|
||||
Spinner,
|
||||
},
|
||||
props: {
|
||||
@@ -38,25 +57,64 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isSearching: false,
|
||||
selectedLabels: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
labels() {
|
||||
return this.$store.getters['conversationLabels/getConversationLabels'](
|
||||
this.conversationId
|
||||
hasEdited() {
|
||||
if (this.selectedLabels.length !== this.savedLabels.length) {
|
||||
return true;
|
||||
}
|
||||
const isSame = this.selectedLabels.every(label =>
|
||||
this.savedLabels.includes(label)
|
||||
);
|
||||
return !isSame;
|
||||
},
|
||||
savedLabels() {
|
||||
const saved = this.$store.getters[
|
||||
'conversationLabels/getConversationLabels'
|
||||
](this.conversationId);
|
||||
return saved;
|
||||
},
|
||||
hasEditedClass() {
|
||||
return this.hasEdited ? 'has-edited' : '';
|
||||
},
|
||||
...mapGetters({
|
||||
uiFlags: 'contactConversations/getUIFlags',
|
||||
conversationUiFlags: 'contactConversations/getUIFlags',
|
||||
labelUiFlags: 'conversationLabels/getUIFlags',
|
||||
}),
|
||||
},
|
||||
watch: {
|
||||
conversationId(newConversationId, prevConversationId) {
|
||||
if (newConversationId && newConversationId !== prevConversationId) {
|
||||
this.$store.dispatch('conversationLabels/get', newConversationId);
|
||||
this.fetchLabels(newConversationId);
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('conversationLabels/get', this.conversationId);
|
||||
const { conversationId } = this;
|
||||
this.fetchLabels(conversationId);
|
||||
},
|
||||
methods: {
|
||||
addLabel(label) {
|
||||
this.selectedLabels = [...this.selectedLabels, label];
|
||||
},
|
||||
onUpdateLabels() {
|
||||
this.$store.dispatch('conversationLabels/update', {
|
||||
conversationId: this.conversationId,
|
||||
labels: this.selectedLabels,
|
||||
});
|
||||
},
|
||||
async fetchLabels(conversationId) {
|
||||
try {
|
||||
await this.$store.dispatch('conversationLabels/get', conversationId);
|
||||
this.selectedLabels = [...this.savedLabels];
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (error) {}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -66,12 +124,7 @@ export default {
|
||||
@import '~dashboard/assets/scss/mixins';
|
||||
|
||||
.contact-conversation--panel {
|
||||
@include border-normal-top;
|
||||
padding: $space-medium;
|
||||
}
|
||||
|
||||
.contact-conversation--list {
|
||||
margin-top: -$space-normal;
|
||||
padding: $space-normal $space-normal $space-normal $space-medium;
|
||||
}
|
||||
|
||||
.conversation--label {
|
||||
@@ -80,4 +133,38 @@ export default {
|
||||
font-size: $font-size-small;
|
||||
padding: $space-smaller;
|
||||
}
|
||||
.wrap {
|
||||
margin-top: $space-slab;
|
||||
}
|
||||
|
||||
.select-tags {
|
||||
margin-top: $space-small;
|
||||
.multiselect {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
transition: $transition-ease-in;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
margin-top: $space-small;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.no-results-wrap {
|
||||
padding: 0 $space-small;
|
||||
}
|
||||
.no-results {
|
||||
margin: $space-normal 0 0 0;
|
||||
color: $color-gray;
|
||||
font-weight: $font-weight-normal;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: $alert-color;
|
||||
font-size: $font-size-mini;
|
||||
font-weight: $font-weight-medium;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user