enhancement: Show agent availability status in conversation assignee select list (#2122)
* show agent status on conversation assignation * add agent status in contact sidebar * availability status badge component * review fixes * review fixes * chore: Fixes issue with status badge (#2136) * add empty case in agent list * Chore: Availability badge shape issue. #2140 Co-authored-by: Nithin David <webofnithin@gmail.com> Co-authored-by: Sojan <sojan@pepalo.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
parent
5c843b8a51
commit
fdbc32f7c2
4 changed files with 75 additions and 27 deletions
|
@ -1,10 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
<div class="status-view">
|
<div class="status-view">
|
||||||
<div
|
<availability-status-badge :status="currentUserAvailabilityStatus" />
|
||||||
:class="`status-badge status-badge__${currentUserAvailabilityStatus}`"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="status-view--title">
|
<div class="status-view--title">
|
||||||
{{ availabilityDisplayLabel }}
|
{{ availabilityDisplayLabel }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,7 +25,7 @@
|
||||||
:disabled="status.disabled"
|
:disabled="status.disabled"
|
||||||
@click="changeAvailabilityStatus(status.value)"
|
@click="changeAvailabilityStatus(status.value)"
|
||||||
>
|
>
|
||||||
<span :class="`status-badge status-badge__${status.value}`" />
|
<availability-status-badge :status="status.value" />
|
||||||
{{ status.label }}
|
{{ status.label }}
|
||||||
</button>
|
</button>
|
||||||
</woot-dropdown-item>
|
</woot-dropdown-item>
|
||||||
|
@ -48,6 +45,7 @@ import { mapGetters } from 'vuex';
|
||||||
import { mixin as clickaway } from 'vue-clickaway';
|
import { mixin as clickaway } from 'vue-clickaway';
|
||||||
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
|
||||||
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
|
||||||
|
import AvailabilityStatusBadge from '../widgets/conversation/AvailabilityStatusBadge';
|
||||||
|
|
||||||
const AVAILABILITY_STATUS_KEYS = ['online', 'busy', 'offline'];
|
const AVAILABILITY_STATUS_KEYS = ['online', 'busy', 'offline'];
|
||||||
|
|
||||||
|
@ -55,6 +53,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
WootDropdownMenu,
|
WootDropdownMenu,
|
||||||
WootDropdownItem,
|
WootDropdownItem,
|
||||||
|
AvailabilityStatusBadge,
|
||||||
},
|
},
|
||||||
|
|
||||||
mixins: [clickaway],
|
mixins: [clickaway],
|
||||||
|
@ -147,26 +146,6 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-badge {
|
|
||||||
width: var(--space-one);
|
|
||||||
height: var(--space-one);
|
|
||||||
margin-right: var(--space-micro);
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
&__online {
|
|
||||||
background: var(--g-400);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__offline {
|
|
||||||
background: var(--b-600);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__busy {
|
|
||||||
background: var(--y-700);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-change {
|
.status-change {
|
||||||
.dropdown-pane {
|
.dropdown-pane {
|
||||||
top: -132px;
|
top: -132px;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<div :class="`status-badge status-badge__${status}`" />
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
status: { type: String, default: '' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~dashboard/assets/scss/variables';
|
||||||
|
.status-badge {
|
||||||
|
width: var(--space-one);
|
||||||
|
height: var(--space-one);
|
||||||
|
margin-right: var(--space-micro);
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 50%;
|
||||||
|
&__online {
|
||||||
|
background: var(--g-400);
|
||||||
|
}
|
||||||
|
&__offline {
|
||||||
|
background: var(--b-600);
|
||||||
|
}
|
||||||
|
&__busy {
|
||||||
|
background: var(--y-700);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -46,6 +46,14 @@
|
||||||
@select="assignAgent"
|
@select="assignAgent"
|
||||||
@remove="removeAgent"
|
@remove="removeAgent"
|
||||||
>
|
>
|
||||||
|
<template slot="option" slot-scope="props">
|
||||||
|
<div class="option__desc">
|
||||||
|
<availability-status-badge
|
||||||
|
:status="props.option.availability_status"
|
||||||
|
/>
|
||||||
|
<span class="option__title">{{ props.option.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<span slot="noResult">{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}</span>
|
<span slot="noResult">{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}</span>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,11 +65,13 @@
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import MoreActions from './MoreActions';
|
import MoreActions from './MoreActions';
|
||||||
import Thumbnail from '../Thumbnail';
|
import Thumbnail from '../Thumbnail';
|
||||||
|
import AvailabilityStatusBadge from '../conversation/AvailabilityStatusBadge';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
MoreActions,
|
MoreActions,
|
||||||
Thumbnail,
|
Thumbnail,
|
||||||
|
AvailabilityStatusBadge,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
@ -126,7 +136,6 @@ export default {
|
||||||
bus.$emit('newToastMessage', this.$t('CONVERSATION.CHANGE_AGENT'));
|
bus.$emit('newToastMessage', this.$t('CONVERSATION.CHANGE_AGENT'));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeAgent() {},
|
removeAgent() {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -142,4 +151,17 @@ export default {
|
||||||
.conv-header {
|
.conv-header {
|
||||||
flex: 0 0 var(--space-jumbo);
|
flex: 0 0 var(--space-jumbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.option__desc {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option__desc {
|
||||||
|
&::v-deep .status-badge {
|
||||||
|
margin-right: var(--space-small);
|
||||||
|
min-width: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -22,7 +22,17 @@
|
||||||
selected-label=""
|
selected-label=""
|
||||||
:placeholder="$t('CONVERSATION_SIDEBAR.SELECT.PLACEHOLDER')"
|
:placeholder="$t('CONVERSATION_SIDEBAR.SELECT.PLACEHOLDER')"
|
||||||
:allow-empty="true"
|
:allow-empty="true"
|
||||||
|
>
|
||||||
|
<template slot="option" slot-scope="props">
|
||||||
|
<div class="option__desc">
|
||||||
|
<availability-status-badge
|
||||||
|
:status="props.option.availability_status"
|
||||||
/>
|
/>
|
||||||
|
<span class="option__title">{{ props.option.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span slot="noResult">{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}</span>
|
||||||
|
</multiselect>
|
||||||
</div>
|
</div>
|
||||||
<div class="multiselect-wrap--small">
|
<div class="multiselect-wrap--small">
|
||||||
<label class="multiselect__label">
|
<label class="multiselect__label">
|
||||||
|
@ -39,6 +49,7 @@
|
||||||
:placeholder="$t('CONVERSATION_SIDEBAR.SELECT.PLACEHOLDER')"
|
:placeholder="$t('CONVERSATION_SIDEBAR.SELECT.PLACEHOLDER')"
|
||||||
:allow-empty="true"
|
:allow-empty="true"
|
||||||
/>
|
/>
|
||||||
|
<span slot="noResult">{{ $t('AGENT_MGMT.SEARCH.NO_RESULTS') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="browser.browser_name" class="conversation--details">
|
<div v-if="browser.browser_name" class="conversation--details">
|
||||||
|
@ -111,6 +122,8 @@ import ContactDetailsItem from './ContactDetailsItem.vue';
|
||||||
import ContactInfo from './contact/ContactInfo';
|
import ContactInfo from './contact/ContactInfo';
|
||||||
import ConversationLabels from './labels/LabelBox.vue';
|
import ConversationLabels from './labels/LabelBox.vue';
|
||||||
import ContactCustomAttributes from './ContactCustomAttributes';
|
import ContactCustomAttributes from './ContactCustomAttributes';
|
||||||
|
import AvailabilityStatusBadge from 'dashboard/components/widgets/conversation/AvailabilityStatusBadge.vue';
|
||||||
|
|
||||||
import flag from 'country-code-emoji';
|
import flag from 'country-code-emoji';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -120,6 +133,7 @@ export default {
|
||||||
ContactDetailsItem,
|
ContactDetailsItem,
|
||||||
ContactInfo,
|
ContactInfo,
|
||||||
ConversationLabels,
|
ConversationLabels,
|
||||||
|
AvailabilityStatusBadge,
|
||||||
},
|
},
|
||||||
mixins: [alertMixin],
|
mixins: [alertMixin],
|
||||||
props: {
|
props: {
|
||||||
|
@ -350,4 +364,8 @@ export default {
|
||||||
.multiselect__label {
|
.multiselect__label {
|
||||||
margin-bottom: var(--space-smaller);
|
margin-bottom: var(--space-smaller);
|
||||||
}
|
}
|
||||||
|
.option__desc {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue