Feature: Improve label experience (#975)

Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
Pranav Raj S
2020-06-25 21:04:03 +05:30
committed by GitHub
parent 8b61452d56
commit 97ad39713b
56 changed files with 1712 additions and 284 deletions

View File

@@ -3,7 +3,7 @@
<div class="chat-list__top">
<h1 class="page-title">
<woot-sidemenu-icon />
{{ inbox.name || $t('CHAT_LIST.TAB_HEADING') }}
{{ pageTitle }}
</h1>
<chat-filter @statusFilterChange="updateStatusType" />
</div>
@@ -15,14 +15,15 @@
@chatTabChange="updateAssigneeTab"
/>
<p v-if="!chatListLoading && !getChatsForTab().length" class="content-box">
<p v-if="!chatListLoading && !conversationList.length" class="content-box">
{{ $t('CHAT_LIST.LIST.404') }}
</p>
<div class="conversations-list">
<conversation-card
v-for="chat in getChatsForTab()"
v-for="chat in conversationList"
:key="chat.id"
:active-label="label"
:chat="chat"
/>
@@ -40,7 +41,7 @@
<p
v-if="
getChatsForTab().length &&
conversationList.length &&
hasCurrentPageEndReached &&
!chatListLoading
"
@@ -72,7 +73,16 @@ export default {
ChatFilter,
},
mixins: [timeMixin, conversationMixin],
props: ['conversationInbox'],
props: {
conversationInbox: {
type: [String, Number],
default: 0,
},
label: {
type: String,
default: '',
},
},
data() {
return {
activeAssigneeTab: wootConstants.ASSIGNEE_TYPE.ME,
@@ -119,18 +129,51 @@ export default {
assigneeType: this.activeAssigneeTab,
status: this.activeStatus,
page: this.currentPage + 1,
labels: this.label ? [this.label] : undefined,
};
},
pageTitle() {
if (this.inbox.name) {
return this.inbox.name;
}
if (this.label) {
return `#${this.label}`;
}
return this.$t('CHAT_LIST.TAB_HEADING');
},
conversationList() {
let conversationList = [];
if (this.activeAssigneeTab === 'me') {
conversationList = this.mineChatsList.slice();
} else if (this.activeAssigneeTab === 'unassigned') {
conversationList = this.unAssignedChatsList.slice();
} else {
conversationList = this.allChatList.slice();
}
if (!this.label) {
return conversationList;
}
return conversationList.filter(conversation => {
const labels = this.$store.getters[
'conversationLabels/getConversationLabels'
](conversation.id);
return labels.includes(this.label);
});
},
},
watch: {
conversationInbox() {
this.resetAndFetchData();
},
label() {
this.resetAndFetchData();
},
},
mounted() {
this.$store.dispatch('setChatFilter', this.activeStatus);
this.resetAndFetchData();
this.$store.dispatch('agents/get');
bus.$on('fetch_conversation_stats', () => {
this.$store.dispatch('conversationStats/get', this.conversationFilters);
@@ -159,17 +202,6 @@ export default {
this.resetAndFetchData();
}
},
getChatsForTab() {
let copyList = [];
if (this.activeAssigneeTab === 'me') {
copyList = this.mineChatsList.slice();
} else if (this.activeAssigneeTab === 'unassigned') {
copyList = this.unAssignedChatsList.slice();
} else {
copyList = this.allChatList.slice();
}
return copyList;
},
},
};
</script>

View File

@@ -6,6 +6,7 @@ import Code from './Code';
import ColorPicker from './widgets/ColorPicker';
import DeleteModal from './widgets/modal/DeleteModal.vue';
import Input from './widgets/forms/Input.vue';
import Label from './widgets/Label.vue';
import LoadingState from './widgets/LoadingState';
import Modal from './Modal';
import ModalHeader from './ModalHeader';
@@ -25,6 +26,7 @@ const WootUIKit = {
DeleteModal,
Input,
LoadingState,
Label,
Modal,
ModalHeader,
ReportStatsCard,

View File

@@ -18,6 +18,11 @@
:key="inboxSection.toState"
:menu-item="inboxSection"
/>
<sidebar-item
v-if="shouldShowInboxes"
:key="labelSection.toState"
:menu-item="labelSection"
/>
</transition-group>
</div>
@@ -125,6 +130,7 @@ export default {
inboxes: 'inboxes/getInboxes',
accountId: 'getCurrentAccountId',
currentRole: 'getCurrentRole',
accountLabels: 'labels/getLabelsOnSidebar',
}),
sidemenuItems() {
return getSidebarItems(this.accountId);
@@ -170,6 +176,25 @@ export default {
})),
};
},
labelSection() {
return {
icon: 'ion-pound',
label: 'LABELS',
hasSubMenu: true,
key: 'label',
cssClass: 'menu-title align-justify',
toState: frontendURL(`accounts/${this.accountId}/settings/labels`),
toStateName: 'labels_list',
children: this.accountLabels.map(label => ({
id: label.id,
label: label.title,
color: label.color,
toState: frontendURL(
`accounts/${this.accountId}/label/${label.title}`
),
})),
};
},
dashboardPath() {
return frontendURL(`accounts/${this.accountId}/dashboard`);
},

View File

@@ -36,7 +36,13 @@
v-if="computedInboxClass(child)"
class="inbox-icon"
:class="computedInboxClass(child)"
></i>
/>
<span
v-if="child.color"
class="label-color--display"
:style="{ backgroundColor: child.color }"
/>
{{ child.label }}
</div>
</a>
@@ -126,8 +132,22 @@ export default {
};
</script>
<style lang="scss" scoped>
@import '~dashboard/assets/scss/variables';
.sub-menu-title {
display: flex;
justify-content: space-between;
}
.wrap {
display: flex;
align-items: center;
}
.label-color--display {
border-radius: $space-smaller;
height: $space-normal;
margin-right: $space-small;
width: $space-normal;
}
</style>

View File

@@ -0,0 +1,91 @@
<template>
<div
:class="labelClass"
:style="{ background: bgColor, color: textColor }"
:title="description"
>
<span v-if="!href">{{ title }}</span>
<a v-else :href="href" :style="{ color: textColor }">{{ title }}</a>
<i v-if="showIcon" class="label--icon" :class="icon" @click="onClick" />
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
required: true,
},
description: {
type: String,
default: '',
},
href: {
type: String,
default: '',
},
bgColor: {
type: String,
default: '#1f93ff',
},
small: {
type: Boolean,
default: false,
},
showIcon: {
type: Boolean,
default: false,
},
icon: {
type: String,
default: 'ion-close',
},
},
computed: {
textColor() {
const color = this.bgColor.replace('#', '');
const r = parseInt(color.slice(0, 2), 16);
const g = parseInt(color.slice(2, 4), 16);
const b = parseInt(color.slice(4, 6), 16);
// http://stackoverflow.com/a/3943023/112731
return r * 0.299 + g * 0.587 + b * 0.114 > 186 ? '#000000' : '#FFFFFF';
},
labelClass() {
return `label ${this.small ? 'small' : ''}`;
},
},
methods: {
onClick() {
this.$emit('click', this.title);
},
},
};
</script>
<style scoped lang="scss">
@import '~dashboard/assets/scss/variables';
.label {
display: inline-block;
font-size: $font-size-small;
line-height: 1;
margin: $space-micro;
&.small {
font-size: $font-size-mini;
}
a {
&:hover {
text-decoration: underline;
}
}
}
.label--icon {
cursor: pointer;
font-size: $font-size-micro;
line-height: 1.5;
margin-left: $space-smaller;
}
</style>

View File

@@ -57,6 +57,10 @@ export default {
mixins: [timeMixin, conversationMixin],
props: {
activeLabel: {
type: String,
default: '',
},
chat: {
type: Object,
default: () => {},
@@ -116,7 +120,12 @@ export default {
methods: {
cardClick(chat) {
const { activeInbox } = this;
const path = conversationUrl(this.accountId, activeInbox, chat.id);
const path = conversationUrl({
accountId: this.accountId,
activeInbox,
id: chat.id,
label: this.activeLabel,
});
router.push({ path: frontendURL(path) });
},
inboxName(inboxId) {