Added a section for group by teams
This commit is contained in:
@@ -86,20 +86,49 @@
|
||||
"MONTH": "Month",
|
||||
"YEAR": "Year"
|
||||
},
|
||||
"GROUP_BY_DAY_OPTIONS": [{ "id": 1, "groupBy": "Day" }],
|
||||
"GROUP_BY_DAY_OPTIONS": [
|
||||
{
|
||||
"id": 1,
|
||||
"groupBy": "Day"
|
||||
}
|
||||
],
|
||||
"GROUP_BY_WEEK_OPTIONS": [
|
||||
{ "id": 1, "groupBy": "Day" },
|
||||
{ "id": 2, "groupBy": "Week" }
|
||||
{
|
||||
"id": 1,
|
||||
"groupBy": "Day"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"groupBy": "Week"
|
||||
}
|
||||
],
|
||||
"GROUP_BY_MONTH_OPTIONS": [
|
||||
{ "id": 1, "groupBy": "Day" },
|
||||
{ "id": 2, "groupBy": "Week" },
|
||||
{ "id": 3, "groupBy": "Month" }
|
||||
{
|
||||
"id": 1,
|
||||
"groupBy": "Day"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"groupBy": "Week"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"groupBy": "Month"
|
||||
}
|
||||
],
|
||||
"GROUP_BY_YEAR_OPTIONS": [
|
||||
{ "id": 2, "groupBy": "Week" },
|
||||
{ "id": 3, "groupBy": "Month" },
|
||||
{ "id": 4, "groupBy": "Year" }
|
||||
{
|
||||
"id": 2,
|
||||
"groupBy": "Week"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"groupBy": "Month"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"groupBy": "Year"
|
||||
}
|
||||
],
|
||||
"BUSINESS_HOURS": "Business Hours"
|
||||
},
|
||||
@@ -431,6 +460,17 @@
|
||||
"STATUS": "Status"
|
||||
}
|
||||
},
|
||||
"TEAM_CONVERSATIONS": {
|
||||
"HEADER": "Conversations by teams",
|
||||
"LOADING_MESSAGE": "Loading team metrics...",
|
||||
"NO_AGENTS": "There is no data available",
|
||||
"TABLE_HEADER": {
|
||||
"AGENT": "Team",
|
||||
"OPEN": "open",
|
||||
"UNATTENDED": "Unattended",
|
||||
"STATUS": "Status"
|
||||
}
|
||||
},
|
||||
"AGENT_STATUS": {
|
||||
"HEADER": "Agent status",
|
||||
"ONLINE": "Online",
|
||||
|
||||
@@ -65,11 +65,22 @@
|
||||
/>
|
||||
</metric-card>
|
||||
</div>
|
||||
<div class="row">
|
||||
<metric-card :header="$t('OVERVIEW_REPORTS.TEAM_CONVERSATIONS.HEADER')">
|
||||
<team-table
|
||||
:teams="teams"
|
||||
:team-metrics="teamConversationMetric"
|
||||
:page-index="pageIndex"
|
||||
:is-loading="uiFlags.isFetchingTeamConversationMetric"
|
||||
/>
|
||||
</metric-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import AgentTable from './components/overview/AgentTable.vue';
|
||||
import TeamTable from './components/overview/TeamTable.vue';
|
||||
import MetricCard from './components/overview/MetricCard.vue';
|
||||
import { OVERVIEW_METRICS } from './constants';
|
||||
import ReportHeatmap from './components/Heatmap.vue';
|
||||
@@ -82,6 +93,7 @@ import subDays from 'date-fns/subDays';
|
||||
export default {
|
||||
name: 'LiveReports',
|
||||
components: {
|
||||
TeamTable,
|
||||
AgentTable,
|
||||
MetricCard,
|
||||
ReportHeatmap,
|
||||
@@ -95,8 +107,10 @@ export default {
|
||||
...mapGetters({
|
||||
agentStatus: 'agents/getAgentStatus',
|
||||
agents: 'agents/getAgents',
|
||||
teams: 'teams/getTeams',
|
||||
accountConversationMetric: 'getAccountConversationMetric',
|
||||
agentConversationMetric: 'getAgentConversationMetric',
|
||||
teamConversationMetric: 'getTeamConversationMetric',
|
||||
accountConversationHeatmap: 'getAccountConversationHeatmapData',
|
||||
uiFlags: 'getOverviewUIFlags',
|
||||
}),
|
||||
@@ -123,6 +137,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('agents/get');
|
||||
this.$store.dispatch('teams/get');
|
||||
this.fetchAllData();
|
||||
|
||||
bus.$on('fetch_overview_reports', () => {
|
||||
@@ -133,6 +148,7 @@ export default {
|
||||
fetchAllData() {
|
||||
this.$store.dispatch('fetchLiveConversationMetric');
|
||||
this.$store.dispatch('fetchAgentConversationMetric');
|
||||
this.$store.dispatch('fetchTeamConversationMetric');
|
||||
this.fetchHeatmapData();
|
||||
},
|
||||
downloadHeatmapData() {
|
||||
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<div class="agent-table-container">
|
||||
<ve-table
|
||||
max-height="calc(100vh - 21.875rem)"
|
||||
:fixed-header="true"
|
||||
:columns="columns"
|
||||
:table-data="tableData"
|
||||
/>
|
||||
<div v-if="isLoading" class="agents-loader">
|
||||
<spinner />
|
||||
<span>{{
|
||||
$t('OVERVIEW_REPORTS.TEAM_CONVERSATIONS.LOADING_MESSAGE')
|
||||
}}</span>
|
||||
</div>
|
||||
<div v-if="teams.length > 0" class="table-pagination">
|
||||
<ve-pagination
|
||||
:total="teams.length"
|
||||
:page-index="pageIndex"
|
||||
:page-size="25"
|
||||
:page-size-option="[25]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { VeTable, VePagination } from 'vue-easytable';
|
||||
import Spinner from 'shared/components/Spinner.vue';
|
||||
import rtlMixin from 'shared/mixins/rtlMixin';
|
||||
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
||||
|
||||
export default {
|
||||
name: 'TeamTable',
|
||||
components: {
|
||||
Spinner,
|
||||
VeTable,
|
||||
VePagination,
|
||||
},
|
||||
mixins: [rtlMixin],
|
||||
props: {
|
||||
teams: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
teamMetrics: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
pageIndex: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
tableData() {
|
||||
return this.teams.map(team => {
|
||||
const teamMetrics = this.getTeamMetrics(team.id);
|
||||
return {
|
||||
agent: team.name,
|
||||
open: teamMetrics.open || 0,
|
||||
unattended: teamMetrics.unattended || 0,
|
||||
};
|
||||
});
|
||||
},
|
||||
columns() {
|
||||
return [
|
||||
{
|
||||
field: 'agent',
|
||||
key: 'agent',
|
||||
title: this.$t(
|
||||
'OVERVIEW_REPORTS.TEAM_CONVERSATIONS.TABLE_HEADER.AGENT'
|
||||
),
|
||||
fixed: 'left',
|
||||
align: this.isRTLView ? 'right' : 'left',
|
||||
width: 25,
|
||||
renderBodyCell: ({ row }) => (
|
||||
<div class="row-user-block">
|
||||
<Thumbnail
|
||||
src={row.thumbnail}
|
||||
size="32px"
|
||||
username={row.agent}
|
||||
status={row.status}
|
||||
/>
|
||||
<div class="user-block">
|
||||
<h6 class="title overflow-hidden whitespace-nowrap text-ellipsis">
|
||||
{row.agent}
|
||||
</h6>
|
||||
<span class="sub-title">{row.email}</span>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
field: 'open',
|
||||
key: 'open',
|
||||
title: this.$t(
|
||||
'OVERVIEW_REPORTS.TEAM_CONVERSATIONS.TABLE_HEADER.OPEN'
|
||||
),
|
||||
align: this.isRTLView ? 'right' : 'left',
|
||||
width: 10,
|
||||
},
|
||||
{
|
||||
field: 'unattended',
|
||||
key: 'unattended',
|
||||
title: this.$t(
|
||||
'OVERVIEW_REPORTS.TEAM_CONVERSATIONS.TABLE_HEADER.UNATTENDED'
|
||||
),
|
||||
align: this.isRTLView ? 'right' : 'left',
|
||||
width: 10,
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getTeamMetrics(id) {
|
||||
return (
|
||||
this.teamMetrics.find(metrics => metrics.team_id === Number(id)) || {}
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.agent-table-container {
|
||||
@apply flex flex-col flex-1;
|
||||
|
||||
.ve-table {
|
||||
&::v-deep {
|
||||
th.ve-table-header-th {
|
||||
font-size: var(--font-size-mini) !important;
|
||||
padding: var(--space-small) var(--space-two) !important;
|
||||
}
|
||||
|
||||
td.ve-table-body-td {
|
||||
padding: var(--space-one) var(--space-two) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&::v-deep .ve-pagination {
|
||||
@apply bg-transparent dark:bg-transparent;
|
||||
}
|
||||
|
||||
&::v-deep .ve-pagination-select {
|
||||
@apply hidden;
|
||||
}
|
||||
|
||||
.row-user-block {
|
||||
@apply items-center flex text-left;
|
||||
|
||||
.user-block {
|
||||
@apply items-start flex flex-col min-w-0 my-0 mx-2;
|
||||
|
||||
.title {
|
||||
@apply text-sm m-0 leading-[1.2] text-slate-800 dark:text-slate-100;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
@apply text-xs text-slate-600 dark:text-slate-200;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-pagination {
|
||||
@apply mt-4 text-right;
|
||||
}
|
||||
}
|
||||
|
||||
.agents-loader {
|
||||
@apply items-center flex text-base justify-center p-8;
|
||||
}
|
||||
</style>
|
||||
@@ -47,10 +47,12 @@ const state = {
|
||||
isFetchingAccountConversationMetric: false,
|
||||
isFetchingAccountConversationsHeatmap: false,
|
||||
isFetchingAgentConversationMetric: false,
|
||||
isFetchingTeamConversationMetric: false,
|
||||
},
|
||||
accountConversationMetric: {},
|
||||
accountConversationHeatmap: [],
|
||||
agentConversationMetric: [],
|
||||
teamConversationMetric: [],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -70,6 +72,9 @@ const getters = {
|
||||
getAgentConversationMetric(_state) {
|
||||
return _state.overview.agentConversationMetric;
|
||||
},
|
||||
getTeamConversationMetric(_state) {
|
||||
return _state.overview.teamConversationMetric;
|
||||
},
|
||||
getOverviewUIFlags($state) {
|
||||
return $state.overview.uiFlags;
|
||||
},
|
||||
@@ -156,6 +161,21 @@ export const actions = {
|
||||
commit(types.default.TOGGLE_AGENT_CONVERSATION_METRIC_LOADING, false);
|
||||
});
|
||||
},
|
||||
fetchTeamConversationMetric({ commit }) {
|
||||
commit(types.default.TOGGLE_TEAM_CONVERSATION_METRIC_LOADING, true);
|
||||
liveReports
|
||||
.getGroupedConversations({ groupBy: 'team_id' })
|
||||
.then(agentConversationMetric => {
|
||||
commit(
|
||||
types.default.SET_TEAM_CONVERSATION_METRIC,
|
||||
agentConversationMetric.data
|
||||
);
|
||||
commit(types.default.TOGGLE_TEAM_CONVERSATION_METRIC_LOADING, false);
|
||||
})
|
||||
.catch(() => {
|
||||
commit(types.default.TOGGLE_TEAM_CONVERSATION_METRIC_LOADING, false);
|
||||
});
|
||||
},
|
||||
downloadAgentReports(_, reportObj) {
|
||||
return Report.getAgentReports(reportObj)
|
||||
.then(response => {
|
||||
@@ -255,9 +275,15 @@ const mutations = {
|
||||
[types.default.SET_AGENT_CONVERSATION_METRIC](_state, metricData) {
|
||||
_state.overview.agentConversationMetric = metricData;
|
||||
},
|
||||
[types.default.SET_TEAM_CONVERSATION_METRIC](_state, metricData) {
|
||||
_state.overview.teamConversationMetric = metricData;
|
||||
},
|
||||
[types.default.TOGGLE_AGENT_CONVERSATION_METRIC_LOADING](_state, flag) {
|
||||
_state.overview.uiFlags.isFetchingAgentConversationMetric = flag;
|
||||
},
|
||||
[types.default.TOGGLE_TEAM_CONVERSATION_METRIC_LOADING](_state, flag) {
|
||||
_state.overview.uiFlags.isFetchingTeamConversationMetric = flag;
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
@@ -171,8 +171,11 @@ export default {
|
||||
TOGGLE_ACCOUNT_CONVERSATION_METRIC_LOADING:
|
||||
'TOGGLE_ACCOUNT_CONVERSATION_METRIC_LOADING',
|
||||
SET_AGENT_CONVERSATION_METRIC: 'SET_AGENT_CONVERSATION_METRIC',
|
||||
SET_TEAM_CONVERSATION_METRIC: 'SET_TEAM_CONVERSATION_METRIC',
|
||||
TOGGLE_AGENT_CONVERSATION_METRIC_LOADING:
|
||||
'TOGGLE_AGENT_CONVERSATION_METRIC_LOADING',
|
||||
TOGGLE_TEAM_CONVERSATION_METRIC_LOADING:
|
||||
'TOGGLE_TEAM_CONVERSATION_METRIC_LOADING',
|
||||
|
||||
// Conversation Metadata
|
||||
SET_CONVERSATION_METADATA: 'SET_CONVERSATION_METADATA',
|
||||
|
||||
Reference in New Issue
Block a user