feat: Complete API binding
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/* global axios */
|
||||
import ApiClient from './ApiClient';
|
||||
|
||||
class SLAReportsAPI extends ApiClient {
|
||||
constructor() {
|
||||
super('applied_slas', { accountScoped: true });
|
||||
}
|
||||
|
||||
get({
|
||||
from,
|
||||
to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
page,
|
||||
} = {}) {
|
||||
return axios.get(this.url, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
page,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
download({
|
||||
from,
|
||||
to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
} = {}) {
|
||||
return axios.get(`${this.url}/download`, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getMetrics({
|
||||
from,
|
||||
to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
} = {}) {
|
||||
// no ratings for metrics
|
||||
return axios.get(`${this.url}/metrics`, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
assigned_agent_id,
|
||||
inbox_id,
|
||||
team_id,
|
||||
sla_policy_id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new SLAReportsAPI();
|
||||
@@ -1,10 +1,20 @@
|
||||
<template>
|
||||
<div class="flex flex-col flex-1 gap-6 p-4 overflow-auto font-inter">
|
||||
<SLAMetrics :hit-rate="`12%`" :no-of-breaches="5" />
|
||||
<SLATable />
|
||||
<SLAMetrics
|
||||
:hit-rate="slaMetrics.hitRate"
|
||||
:no-of-breaches="slaMetrics.numberOfSLABreaches"
|
||||
/>
|
||||
<SLATable
|
||||
:sla-reports="slaReports"
|
||||
:current-page="Number(slaMeta.currentPage)"
|
||||
:total-count="Number(slaMeta.count)"
|
||||
:page-size="3"
|
||||
@page-change="onPageChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import SLAMetrics from './components/SLA/SLAMetrics.vue';
|
||||
import SLATable from './components/SLA/SLATable.vue';
|
||||
export default {
|
||||
@@ -13,5 +23,31 @@ export default {
|
||||
SLAMetrics,
|
||||
SLATable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageNumber: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
slaReports: 'slaReports/getAll',
|
||||
slaMetrics: 'slaReports/getMetrics',
|
||||
slaMeta: 'slaReports/getMeta',
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.$store.dispatch('slaReports/getMetrics');
|
||||
this.fetchSLAReports();
|
||||
},
|
||||
methods: {
|
||||
fetchSLAReports({ pageNumber } = {}) {
|
||||
this.$store.dispatch('slaReports/get', {
|
||||
page: pageNumber || this.pageNumber,
|
||||
});
|
||||
},
|
||||
onPageChange(pageNumber) {
|
||||
this.fetchSLAReports({ pageNumber });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
<script setup>
|
||||
import CardLabels from 'dashboard/components/widgets/conversation/conversationCardComponents/CardLabels.vue';
|
||||
defineProps({
|
||||
slaName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
conversationId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="grid content-center h-16 grid-cols-12 gap-4 px-6 py-0 bg-white border-b border-slate-75 dark:border-slate-800/50 dark:bg-slate-900"
|
||||
>
|
||||
<div
|
||||
class="flex items-center capitalize py-2 px-0 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 text-left rtl:text-right col-span-2"
|
||||
>
|
||||
{{ slaName }}
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-6 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
#{{ conversationId }} with John Doe
|
||||
<card-labels :conversation-id="148" />
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-2 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
Elijah
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-2 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
<woot-button color-scheme="secondary" variant="link">
|
||||
View details
|
||||
</woot-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
+80
-48
@@ -1,60 +1,92 @@
|
||||
<template>
|
||||
<div
|
||||
class="min-w-full border rounded-xl border-slate-75 dark:border-slate-800/50"
|
||||
>
|
||||
<!-- Header -->
|
||||
<div>
|
||||
<div
|
||||
class="grid content-center h-12 grid-cols-12 gap-4 px-6 py-0 border-b bg-slate-25 border-slate-75 dark:border-slate-800 rounded-t-xl dark:bg-slate-900"
|
||||
class="min-w-full border rounded-xl border-slate-75 dark:border-slate-800/50"
|
||||
>
|
||||
<!-- Header -->
|
||||
<div
|
||||
class="flex items-center font-medium capitalize text-xs py-2 px-0 tracking-[10%] text-slate-700 dark:text-slate-100 text-left rtl:text-right col-span-2"
|
||||
class="grid content-center h-12 grid-cols-12 gap-4 px-6 py-0 border-b bg-slate-25 border-slate-75 dark:border-slate-800 rounded-t-xl dark:bg-slate-900"
|
||||
>
|
||||
POLICY BREACHED
|
||||
<div
|
||||
class="flex items-center font-medium capitalize text-xs py-2 px-0 tracking-[10%] text-slate-700 dark:text-slate-100 text-left rtl:text-right col-span-2"
|
||||
>
|
||||
POLICY BREACHED
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-6 px-0 py-2 text-xs font-medium text-left capitalize text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
CONVERSATION
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center px-0 text-xs font-medium text-left capitalize col-span-2py-2 text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
AGENT
|
||||
</div>
|
||||
<div
|
||||
class="col-span-2 px-0 py-2 text-xs font-medium text-left capitalize text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-6 px-0 py-2 text-xs font-medium text-left capitalize text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
CONVERSATION
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center px-0 text-xs font-medium text-left capitalize col-span-2py-2 text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
AGENT
|
||||
</div>
|
||||
<div
|
||||
class="col-span-2 px-0 py-2 text-xs font-medium text-left capitalize text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
<SLA-report-item
|
||||
v-for="sla in slaReports"
|
||||
:key="sla.id"
|
||||
:sla-name="sla.sla_policy.name"
|
||||
:conversation-id="sla.conversation.id"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="grid content-center h-16 grid-cols-12 gap-4 px-6 py-0 bg-white border-b border-slate-75 dark:border-slate-800/50 dark:bg-slate-900"
|
||||
>
|
||||
<div
|
||||
class="flex items-center capitalize py-2 px-0 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 text-left rtl:text-right col-span-2"
|
||||
>
|
||||
Premium SLA
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-6 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
#198 with John Doe
|
||||
<card-labels :conversation-id="148" />
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-2 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
Elijah
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center col-span-2 px-0 py-2 text-sm tracking-[0.5] text-slate-700 dark:text-slate-100 rtl:text-right"
|
||||
>
|
||||
<woot-button color-scheme="secondary" variant="link">
|
||||
View details
|
||||
</woot-button>
|
||||
</div>
|
||||
</div>
|
||||
<table-footer
|
||||
v-if="shouldShowFooter"
|
||||
:current-page="currentPage"
|
||||
:total-count="totalCount"
|
||||
:page-size="pageSize"
|
||||
class="dark:bg-slate-900 sticky bottom-0"
|
||||
@page-change="onPageChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import CardLabels from 'dashboard/components/widgets/conversation/conversationCardComponents/CardLabels.vue';
|
||||
<script>
|
||||
import TableFooter from 'dashboard/components/widgets/TableFooter.vue';
|
||||
import SLAReportItem from './SLAReportItem.vue';
|
||||
export default {
|
||||
name: 'SLATable',
|
||||
components: {
|
||||
SLAReportItem,
|
||||
TableFooter,
|
||||
},
|
||||
props: {
|
||||
slaReports: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
totalCount: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
currentPage: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: 25,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageNo: 1,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
shouldShowFooter() {
|
||||
return this.currentPage === 1
|
||||
? this.totalCount > this.pageSize
|
||||
: this.slaReports.length > 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onPageChange(page) {
|
||||
this.$emit('page-change', page);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -44,6 +44,7 @@ import teams from './modules/teams';
|
||||
import userNotificationSettings from './modules/userNotificationSettings';
|
||||
import webhooks from './modules/webhooks';
|
||||
import draftMessages from './modules/draftMessages';
|
||||
import SLAReports from './modules/SLAReports';
|
||||
|
||||
import LogRocket from 'logrocket';
|
||||
import createPlugin from 'logrocket-vuex';
|
||||
@@ -111,6 +112,7 @@ export default new Vuex.Store({
|
||||
webhooks,
|
||||
draftMessages,
|
||||
sla,
|
||||
slaReports: SLAReports,
|
||||
},
|
||||
plugins,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
|
||||
import types from '../mutation-types';
|
||||
import SLAReportsAPI from '../../api/slaReports';
|
||||
|
||||
export const state = {
|
||||
records: [],
|
||||
metrics: {
|
||||
numberOfSLABreaches: 0,
|
||||
hitRate: '0%',
|
||||
},
|
||||
uiFlags: {
|
||||
isFetching: false,
|
||||
isFetchingMetrics: false,
|
||||
},
|
||||
meta: {
|
||||
count: 0,
|
||||
currentPage: 1,
|
||||
},
|
||||
};
|
||||
|
||||
export const getters = {
|
||||
getAll(_state) {
|
||||
return _state.records;
|
||||
},
|
||||
getMeta(_state) {
|
||||
return _state.meta;
|
||||
},
|
||||
getMetrics(_state) {
|
||||
return _state.metrics;
|
||||
},
|
||||
getUIFlags(_state) {
|
||||
return _state.uiFlags;
|
||||
},
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
get: async function getResponses({ commit }, params) {
|
||||
commit(types.SET_SLA_REPORTS_UI_FLAG, { isFetching: true });
|
||||
try {
|
||||
const response = await SLAReportsAPI.get(params);
|
||||
const { payload, meta } = response.data;
|
||||
|
||||
commit(types.SET_SLA_REPORTS, payload);
|
||||
commit(types.SET_SLA_REPORTS_META, meta);
|
||||
} catch (error) {
|
||||
// Ignore error
|
||||
} finally {
|
||||
commit(types.SET_SLA_REPORTS_UI_FLAG, { isFetching: false });
|
||||
}
|
||||
},
|
||||
getMetrics: async function getMetrics({ commit }, params) {
|
||||
commit(types.SET_SLA_REPORTS_UI_FLAG, { isFetchingMetrics: true });
|
||||
try {
|
||||
const response = await SLAReportsAPI.getMetrics(params);
|
||||
commit(types.SET_SLA_REPORTS_METRICS, response.data);
|
||||
} catch (error) {
|
||||
// Ignore error
|
||||
} finally {
|
||||
commit(types.SET_SLA_REPORTS_UI_FLAG, { isFetchingMetrics: false });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export const mutations = {
|
||||
[types.SET_SLA_REPORTS_UI_FLAG](_state, data) {
|
||||
_state.uiFlags = {
|
||||
..._state.uiFlags,
|
||||
...data,
|
||||
};
|
||||
},
|
||||
|
||||
[types.SET_SLA_REPORTS]: MutationHelpers.set,
|
||||
[types.SET_SLA_REPORTS_METRICS](
|
||||
_state,
|
||||
{ number_of_sla_breaches: numberOfSLABreaches, hit_rate: hitRate }
|
||||
) {
|
||||
_state.metrics = {
|
||||
numberOfSLABreaches,
|
||||
hitRate,
|
||||
};
|
||||
},
|
||||
[types.SET_SLA_REPORTS_META](
|
||||
_state,
|
||||
{ total_applied_slas: totalAppliedSLAs, current_page: currentPage }
|
||||
) {
|
||||
_state.meta = {
|
||||
count: totalAppliedSLAs,
|
||||
currentPage,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations,
|
||||
};
|
||||
@@ -309,4 +309,10 @@ export default {
|
||||
ADD_SLA: 'ADD_SLA',
|
||||
EDIT_SLA: 'EDIT_SLA',
|
||||
DELETE_SLA: 'DELETE_SLA',
|
||||
|
||||
// SLA Reports
|
||||
SET_SLA_REPORTS_UI_FLAG: 'SET_SLA_REPORTS_UI_FLAG',
|
||||
SET_SLA_REPORTS: 'SET_SLA_REPORTS',
|
||||
SET_SLA_REPORTS_METRICS: 'SET_SLA_REPORTS_METRICS',
|
||||
SET_SLA_REPORTS_META: 'SET_SLA_REPORTS_META',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user