feat: Update UX for adding label in a conversation (#2243)

This commit is contained in:
Sivin Varghese
2021-05-17 12:00:08 +05:30
committed by GitHub
parent ef2611164d
commit 60177ef418
4 changed files with 103 additions and 76 deletions

View File

@@ -89,6 +89,7 @@ export default {
.label--icon, .label--icon,
.close--icon { .close--icon {
font-size: var(--font-size-micro); font-size: var(--font-size-micro);
cursor: pointer;
} }
&.small .label--icon, &.small .label--icon,

View File

@@ -53,6 +53,7 @@
</multiselect> </multiselect>
</div> </div>
</div> </div>
<conversation-labels :conversation-id="conversationId" />
<div v-if="browser.browser_name" class="conversation--details"> <div v-if="browser.browser_name" class="conversation--details">
<contact-details-item <contact-details-item
v-if="location" v-if="location"
@@ -105,7 +106,6 @@
v-if="hasContactAttributes" v-if="hasContactAttributes"
:custom-attributes="contact.custom_attributes" :custom-attributes="contact.custom_attributes"
/> />
<conversation-labels :conversation-id="conversationId" />
<contact-conversations <contact-conversations
v-if="contact.id" v-if="contact.id"
:contact-id="contact.id" :contact-id="contact.id"
@@ -359,7 +359,7 @@ export default {
} }
.conversation--actions { .conversation--actions {
padding: 0 var(--space-normal) var(--space-small); padding: 0 var(--space-normal) var(--space-smaller);
} }
.multiselect__label { .multiselect__label {

View File

@@ -8,76 +8,91 @@
:title="$t('CONTACT_PANEL.LABELS.TITLE')" :title="$t('CONTACT_PANEL.LABELS.TITLE')"
icon="ion-pricetags" icon="ion-pricetags"
emoji="🏷️" emoji="🏷️"
:show-edit="true"
@edit="onEdit"
/> />
<div class="label-wrap"> <div v-on-clickaway="closeDropdownLabel" class="label-wrap">
<add-label @add="toggleLabels" />
<woot-label <woot-label
v-for="label in activeLabels" v-for="label in activeLabels"
:key="label.id" :key="label.id"
:title="label.title" :title="label.title"
:description="label.description" :description="label.description"
:show-close="true"
:bg-color="label.color" :bg-color="label.color"
@click="removeItem"
/> />
<div v-if="!activeLabels.length" class="no-label-message">
<span>{{ $t('CONTACT_PANEL.LABELS.NO_AVAILABLE_LABELS') }}</span> <div class="dropdown-wrap">
</div> <div
</div> :class="{ 'dropdown-pane--open': showSearchDropdownLabel }"
<add-label-to-conversation class="dropdown-pane"
v-if="isEditing" >
:conversation-id="conversationId" <label-dropdown
v-if="showSearchDropdownLabel"
:account-labels="accountLabels" :account-labels="accountLabels"
:saved-labels="savedLabels" :selected-labels="savedLabels"
:show.sync="isEditing" :conversation-id="conversationId"
:on-close="closeEditModal" @add="addItem"
:update-labels="onUpdateLabels" @remove="removeItem"
/> />
</div> </div>
</div>
</div>
</div>
<spinner v-else></spinner> <spinner v-else></spinner>
</div> </div>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import AddLabelToConversation from './AddLabelToConversation';
import ContactDetailsItem from '../ContactDetailsItem'; import ContactDetailsItem from '../ContactDetailsItem';
import Spinner from 'shared/components/Spinner'; import Spinner from 'shared/components/Spinner';
import LabelDropdown from 'shared/components/ui/label/LabelDropdown';
import AddLabel from 'shared/components/ui/dropdown/AddLabel';
import { mixin as clickaway } from 'vue-clickaway';
export default { export default {
components: { components: {
AddLabelToConversation,
ContactDetailsItem, ContactDetailsItem,
Spinner, Spinner,
LabelDropdown,
AddLabel,
}, },
mixins: [clickaway],
props: { props: {
conversationId: { conversationId: {
type: [String, Number], type: [String, Number],
required: true, required: true,
}, },
}, },
data() { data() {
return { return {
isEditing: false,
selectedLabels: [], selectedLabels: [],
showSearchDropdownLabel: false,
}; };
}, },
computed: { computed: {
savedLabels() { savedLabels() {
return this.$store.getters['conversationLabels/getConversationLabels']( return this.$store.getters['conversationLabels/getConversationLabels'](
this.conversationId this.conversationId
); );
}, },
...mapGetters({ ...mapGetters({
conversationUiFlags: 'contactConversations/getUIFlags', conversationUiFlags: 'contactConversations/getUIFlags',
labelUiFlags: 'conversationLabels/getUIFlags', labelUiFlags: 'conversationLabels/getUIFlags',
accountLabels: 'labels/getLabels', accountLabels: 'labels/getLabels',
}), }),
activeLabels() { activeLabels() {
return this.accountLabels.filter(({ title }) => return this.accountLabels.filter(({ title }) =>
this.savedLabels.includes(title) this.savedLabels.includes(title)
); );
}, },
}, },
watch: { watch: {
conversationId(newConversationId, prevConversationId) { conversationId(newConversationId, prevConversationId) {
if (newConversationId && newConversationId !== prevConversationId) { if (newConversationId && newConversationId !== prevConversationId) {
@@ -85,10 +100,12 @@ export default {
} }
}, },
}, },
mounted() { mounted() {
const { conversationId } = this; const { conversationId } = this;
this.fetchLabels(conversationId); this.fetchLabels(conversationId);
}, },
methods: { methods: {
async onUpdateLabels(selectedLabels) { async onUpdateLabels(selectedLabels) {
try { try {
@@ -100,13 +117,28 @@ export default {
// Ignore error // Ignore error
} }
}, },
onEdit() {
this.isEditing = true; toggleLabels() {
this.showSearchDropdownLabel = !this.showSearchDropdownLabel;
}, },
closeEditModal() {
bus.$emit('fetch_conversation_stats'); addItem(value) {
this.isEditing = false; const result = this.activeLabels.map(item => item.title);
result.push(value.title);
this.onUpdateLabels(result);
}, },
removeItem(value) {
const result = this.activeLabels
.map(label => label.title)
.filter(label => label !== value);
this.onUpdateLabels(result);
},
closeDropdownLabel() {
this.showSearchDropdownLabel = false;
},
async fetchLabels(conversationId) { async fetchLabels(conversationId) {
if (!conversationId) { if (!conversationId) {
return; return;
@@ -122,53 +154,38 @@ export default {
@import '~dashboard/assets/scss/mixins'; @import '~dashboard/assets/scss/mixins';
.contact-conversation--panel { .contact-conversation--panel {
padding: var(--space-medium) var(--space-slab) var(--space-two); padding: var(--space-micro) var(--space-slab) var(--space-one)
var(--space-slab);
} }
.contact-conversation--list .conv-details--item { .contact-conversation--list {
padding-bottom: 0; width: 100%;
}
.conversation--label {
color: $color-white;
margin-right: $space-small;
font-size: $font-size-small;
padding: $space-smaller;
}
.label-wrap {
margin-left: var(--space-medium);
}
.no-label-message {
color: var(--b-500);
}
.select-tags { .label-wrap {
.multiselect { margin-left: var(--space-two);
&:hover { position: relative;
cursor: pointer; line-height: var(--space-medium);
bottom: var(--space-small);
.dropdown-wrap {
display: flex;
position: absolute;
margin-right: var(--space-medium);
top: var(--space-medium);
width: 100%;
left: -1px;
.dropdown-pane {
width: 100%;
box-sizing: border-box;
}
} }
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 { .error {
color: $alert-color; color: var(--r-500);
font-size: $font-size-mini; font-size: var(--font-size-mini);
font-weight: $font-weight-medium; font-weight: var(--font-weight-medium);
} }
</style> </style>

View File

@@ -1,15 +1,14 @@
<template> <template>
<div>
<woot-button <woot-button
variant="hollow" variant="hollow"
size="tiny" size="tiny"
icon="ion-plus-round" icon="ion-plus-round"
color-scheme="secondary" color-scheme="secondary"
class-names="button-wrap"
@click="toggleLabels" @click="toggleLabels"
> >
{{ $t('CONTACT_PANEL.LABELS.MODAL.ADD_BUTTON') }} {{ $t('CONTACT_PANEL.LABELS.MODAL.ADD_BUTTON') }}
</woot-button> </woot-button>
</div>
</template> </template>
<script> <script>
@@ -22,4 +21,14 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped>
.button-wrap {
padding: var(--space-micro) var(--space-small);
display: inline;
line-height: 1.2;
&::v-deep .icon {
font-size: var(--font-size-mini);
}
}
</style>