This commit is contained in:
Pranav
2024-02-13 17:32:31 -08:00
parent db30a05b19
commit 2a34ceb66b
6 changed files with 180 additions and 95 deletions
@@ -6,7 +6,7 @@ class SummaryReportsAPI extends ApiClient {
super('summary_reports', { accountScoped: true, apiVersion: 'v2' });
}
getTeamReports({ since, until, businessHours }) {
getTeamReports({ since, until, businessHours } = {}) {
return axios.get(`${this.url}/team`, {
params: {
since,
@@ -16,7 +16,7 @@ class SummaryReportsAPI extends ApiClient {
});
}
getAgentReports({ since, until, businessHours }) {
getAgentReports({ since, until, businessHours } = {}) {
return axios.get(`${this.url}/agents`, {
params: {
since,
@@ -1,7 +1,13 @@
<template>
<div class="overflow-auto">
<metric-card :is-live="false" header="Team wise reports" />
<metric-card :is-live="false" header="Team wise reports">
<metric-card :is-live="false" header="All teams overview">
<team-list-table />
</metric-card>
<metric-card
:is-live="false"
header="Team wise reports"
class="overflow-visible"
>
<woot-reports
key="team-reports"
class="!p-0"
@@ -15,6 +21,7 @@
</template>
<script>
import TeamListTable from './components/AggregateTables/TeamListTable.vue';
import WootReports from './components/WootReports.vue';
import MetricCard from './components/overview/MetricCard.vue';
@@ -22,6 +29,7 @@ export default {
components: {
WootReports,
MetricCard,
TeamListTable,
},
};
</script>
@@ -0,0 +1,152 @@
<template>
<div class="agent-table-container">
<ve-table
max-height="calc(100vh - 21.875rem)"
:fixed-header="true"
:columns="columns"
:table-data="tableData"
/>
</div>
</template>
<script>
import { VeTable } from 'vue-easytable';
import rtlMixin from 'shared/mixins/rtlMixin';
import { mapGetters } from 'vuex';
export default {
name: 'TeamTable',
components: {
VeTable,
},
mixins: [rtlMixin],
computed: {
...mapGetters({
teams: 'teams/getTeams',
teamMetrics: 'summaryReports/getTeamSummaryReports',
}),
tableData() {
return this.teams.map(team => {
const teamMetrics = this.getTeamMetrics(team.id);
return {
name: team.name,
conversationsCount: teamMetrics.open || 0,
avgFirstResponseTime: teamMetrics.open || 0,
avgResolutionTime: teamMetrics.open || 0,
resolutionsCount: teamMetrics.open || 0,
};
});
},
columns() {
return [
{
field: 'agent',
key: 'agent',
title: 'Team',
fixed: 'left',
align: this.isRTLView ? 'right' : 'left',
width: 25,
renderBodyCell: ({ row }) => (
<div class="row-user-block">
<div class="user-block">
<h6 class="title overflow-hidden whitespace-nowrap text-ellipsis">
{row.name}
</h6>
</div>
</div>
),
},
{
field: 'conversationsCount',
key: 'conversationsCount',
title: 'No. of conversations',
align: this.isRTLView ? 'right' : 'left',
width: 20,
},
{
field: 'resolutionsCount',
key: 'resolutionsCount',
title: 'No. of resolved conversations',
align: this.isRTLView ? 'right' : 'left',
width: 20,
},
{
field: 'avgFirstResponseTime',
key: 'avgFirstResponseTime',
title: 'Average first response time',
align: this.isRTLView ? 'right' : 'left',
width: 20,
},
{
field: 'avgResolutionTime',
key: 'avgResolutionTime',
title: 'Average resolution time',
align: this.isRTLView ? 'right' : 'left',
width: 20,
},
];
},
},
mounted() {
this.$store.dispatch('summaryReports/fetchTeamSummaryReports');
},
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>
@@ -27,7 +27,6 @@
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',
@@ -79,17 +78,10 @@ export default {
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">
<h6 class="capitalize title overflow-hidden whitespace-nowrap text-ellipsis">
{row.agent}
</h6>
<span class="sub-title">{row.email}</span>
</div>
</div>
),
+2
View File
@@ -41,6 +41,7 @@ import reports from './modules/reports';
import teamMembers from './modules/teamMembers';
import teams from './modules/teams';
import userNotificationSettings from './modules/userNotificationSettings';
import summaryReports from './modules/summaryReports';
import webhooks from './modules/webhooks';
import draftMessages from './modules/draftMessages';
@@ -106,6 +107,7 @@ export default new Vuex.Store({
reports,
teamMembers,
teams,
summaryReports,
userNotificationSettings,
webhooks,
draftMessages,
@@ -1,18 +1,9 @@
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
import types from '../mutation-types';
import LabelsAPI from '../../api/labels';
import AnalyticsHelper from '../../helper/AnalyticsHelper';
import { LABEL_EVENTS } from '../../helper/AnalyticsHelper/events';
import SummaryReportsAPI from '../../api/summaryReports';
export const state = {
teamSummaryReports: [],
agentSummaryReports: [],
uiFlags: {
isFetching: false,
isFetchingItem: false,
isCreating: false,
isDeleting: false,
},
uiFlags: {},
};
export const getters = {
@@ -22,94 +13,34 @@ export const getters = {
getTeamSummaryReports(_state) {
return _state.teamSummaryReports;
},
getLabelsOnSidebar(_state) {
return _state.records
.filter(record => record.show_on_sidebar)
.sort((a, b) => a.title.localeCompare(b.title));
},
};
export const actions = {
revalidate: async function revalidate({ commit }, { newKey }) {
async fetchTeamSummaryReports({ commit }, params) {
try {
const isExistingKeyValid = await LabelsAPI.validateCacheKey(newKey);
if (!isExistingKeyValid) {
const response = await LabelsAPI.refetchAndCommit(newKey);
commit(types.SET_LABELS, response.data.payload);
}
const response = await SummaryReportsAPI.getTeamReports(params);
commit('setTeamSummaryReport', response.data);
} catch (error) {
// Ignore error
}
},
get: async function getLabels({ commit }) {
commit(types.SET_LABEL_UI_FLAG, { isFetching: true });
async getAgentSummaryReports({ commit }, params) {
try {
const response = await LabelsAPI.get(true);
const sortedLabels = response.data.payload.sort((a, b) =>
a.title.localeCompare(b.title)
);
commit(types.SET_LABELS, sortedLabels);
const response = await SummaryReportsAPI.getAgentReports(params);
commit('setAgentSummayReport', response.data);
} catch (error) {
// Ignore error
} finally {
commit(types.SET_LABEL_UI_FLAG, { isFetching: false });
}
},
create: async function createLabels({ commit }, cannedObj) {
commit(types.SET_LABEL_UI_FLAG, { isCreating: true });
try {
const response = await LabelsAPI.create(cannedObj);
AnalyticsHelper.track(LABEL_EVENTS.CREATE);
commit(types.ADD_LABEL, response.data);
} catch (error) {
const errorMessage = error?.response?.data?.message;
throw new Error(errorMessage);
} finally {
commit(types.SET_LABEL_UI_FLAG, { isCreating: false });
}
},
update: async function updateLabels({ commit }, { id, ...updateObj }) {
commit(types.SET_LABEL_UI_FLAG, { isUpdating: true });
try {
const response = await LabelsAPI.update(id, updateObj);
AnalyticsHelper.track(LABEL_EVENTS.UPDATE);
commit(types.EDIT_LABEL, response.data);
} catch (error) {
throw new Error(error);
} finally {
commit(types.SET_LABEL_UI_FLAG, { isUpdating: false });
}
},
delete: async function deleteLabels({ commit }, id) {
commit(types.SET_LABEL_UI_FLAG, { isDeleting: true });
try {
await LabelsAPI.delete(id);
AnalyticsHelper.track(LABEL_EVENTS.DELETED);
commit(types.DELETE_LABEL, id);
} catch (error) {
throw new Error(error);
} finally {
commit(types.SET_LABEL_UI_FLAG, { isDeleting: false });
}
},
};
export const mutations = {
[types.SET_LABEL_UI_FLAG](_state, data) {
_state.uiFlags = {
..._state.uiFlags,
...data,
};
setTeamSummaryReport(_state, data) {
_state.teamSummaryReports = data;
},
setAgentSummaryReport(_state, data) {
_state.agentSummaryReports = data;
},
[types.SET_LABELS]: MutationHelpers.set,
[types.ADD_LABEL]: MutationHelpers.create,
[types.EDIT_LABEL]: MutationHelpers.update,
[types.DELETE_LABEL]: MutationHelpers.destroy,
};
export default {