feat: Display how many conversations are considered for the metric calculation (#4273)
* feat: Display how many conversations are considered for the metric calculation
This commit is contained in:
parent
ba0188aefc
commit
0ba6e772a4
11 changed files with 379 additions and 47 deletions
|
@ -18,10 +18,16 @@ class V2::ReportBuilder
|
||||||
|
|
||||||
# For backward compatible with old report
|
# For backward compatible with old report
|
||||||
def build
|
def build
|
||||||
|
if %w[avg_first_response_time avg_resolution_time].include?(params[:metric])
|
||||||
|
timeseries.each_with_object([]) do |p, arr|
|
||||||
|
arr << { value: p[1], timestamp: p[0].in_time_zone(@timezone).to_i, count: @grouped_values.count[p[0]] }
|
||||||
|
end
|
||||||
|
else
|
||||||
timeseries.each_with_object([]) do |p, arr|
|
timeseries.each_with_object([]) do |p, arr|
|
||||||
arr << { value: p[1], timestamp: p[0].in_time_zone(@timezone).to_i }
|
arr << { value: p[1], timestamp: p[0].in_time_zone(@timezone).to_i }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def summary
|
def summary
|
||||||
{
|
{
|
||||||
|
@ -68,7 +74,7 @@ class V2::ReportBuilder
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_grouped_values(object_scope)
|
def get_grouped_values(object_scope)
|
||||||
object_scope.group_by_period(
|
@grouped_values = object_scope.group_by_period(
|
||||||
params[:group_by] || DEFAULT_GROUP_BY,
|
params[:group_by] || DEFAULT_GROUP_BY,
|
||||||
:created_at,
|
:created_at,
|
||||||
default_value: 0,
|
default_value: 0,
|
||||||
|
|
|
@ -18,6 +18,13 @@
|
||||||
font-size: $font-size-small;
|
font-size: $font-size-small;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
color: $color-heading;
|
color: $color-heading;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-icon {
|
||||||
|
color: var(--b-400);
|
||||||
|
margin-left: var(--space-micro);
|
||||||
}
|
}
|
||||||
|
|
||||||
.metric-wrap {
|
.metric-wrap {
|
||||||
|
|
|
@ -5,7 +5,14 @@
|
||||||
@click="onClick(index)"
|
@click="onClick(index)"
|
||||||
>
|
>
|
||||||
<h3 class="heading">
|
<h3 class="heading">
|
||||||
{{ heading }}
|
<span>{{ heading }}</span>
|
||||||
|
<fluent-icon
|
||||||
|
v-if="infoText"
|
||||||
|
v-tooltip="infoText"
|
||||||
|
size="14"
|
||||||
|
icon="info"
|
||||||
|
class="info-icon"
|
||||||
|
/>
|
||||||
</h3>
|
</h3>
|
||||||
<div class="metric-wrap">
|
<div class="metric-wrap">
|
||||||
<h4 class="metric">
|
<h4 class="metric">
|
||||||
|
@ -22,6 +29,7 @@
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
heading: { type: String, default: '' },
|
heading: { type: String, default: '' },
|
||||||
|
infoText: { type: String, default: '' },
|
||||||
point: { type: [Number, String], default: '' },
|
point: { type: [Number, String], default: '' },
|
||||||
trend: { type: Number, default: null },
|
trend: { type: Number, default: null },
|
||||||
index: { type: Number, default: null },
|
index: { type: Number, default: null },
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Bar } from 'vue-chartjs';
|
||||||
const fontFamily =
|
const fontFamily =
|
||||||
'-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
|
'-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
|
||||||
|
|
||||||
const chartOptions = {
|
const defaultChartOptions = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
legend: {
|
legend: {
|
||||||
|
@ -11,10 +11,14 @@ const chartOptions = {
|
||||||
fontFamily,
|
fontFamily,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
datasets: {
|
||||||
|
bar: {
|
||||||
|
barPercentage: 1.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [
|
xAxes: [
|
||||||
{
|
{
|
||||||
barPercentage: 1.1,
|
|
||||||
ticks: {
|
ticks: {
|
||||||
fontFamily,
|
fontFamily,
|
||||||
},
|
},
|
||||||
|
@ -39,8 +43,20 @@ const chartOptions = {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
extends: Bar,
|
extends: Bar,
|
||||||
props: ['collection'],
|
props: {
|
||||||
|
collection: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
chartOptions: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.renderChart(this.collection, chartOptions);
|
this.renderChart(this.collection, {
|
||||||
|
...defaultChartOptions,
|
||||||
|
...this.chartOptions,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,12 +18,14 @@
|
||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -98,12 +100,14 @@
|
||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -161,12 +165,14 @@
|
||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -224,12 +230,14 @@
|
||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -287,12 +295,14 @@
|
||||||
"DESC": "( Total )"
|
"DESC": "( Total )"
|
||||||
},
|
},
|
||||||
"FIRST_RESPONSE_TIME": {
|
"FIRST_RESPONSE_TIME": {
|
||||||
"NAME": "First response time",
|
"NAME": "First Response Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )"
|
"DESC": "( Avg )",
|
||||||
|
"INFO_TEXT": "Total number of conversations used for computation:"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
|
|
@ -5,6 +5,7 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
accountSummary: 'getAccountSummary',
|
accountSummary: 'getAccountSummary',
|
||||||
|
accountReport: 'getAccountReports',
|
||||||
}),
|
}),
|
||||||
calculateTrend() {
|
calculateTrend() {
|
||||||
return metric_key => {
|
return metric_key => {
|
||||||
|
@ -19,15 +20,32 @@ export default {
|
||||||
},
|
},
|
||||||
displayMetric() {
|
displayMetric() {
|
||||||
return metric_key => {
|
return metric_key => {
|
||||||
if (
|
if (this.isAverageMetricType(metric_key)) {
|
||||||
['avg_first_response_time', 'avg_resolution_time'].includes(
|
|
||||||
metric_key
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return formatTime(this.accountSummary[metric_key]);
|
return formatTime(this.accountSummary[metric_key]);
|
||||||
}
|
}
|
||||||
return this.accountSummary[metric_key];
|
return this.accountSummary[metric_key];
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
displayInfoText() {
|
||||||
|
return metric_key => {
|
||||||
|
if (this.metrics[this.currentSelection].KEY !== metric_key) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (this.isAverageMetricType(metric_key)) {
|
||||||
|
const total = this.accountReport.data
|
||||||
|
.map(item => item.count)
|
||||||
|
.reduce((prev, curr) => prev + curr, 0);
|
||||||
|
return `${this.metrics[this.currentSelection].INFO_TEXT} ${total}`;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
},
|
||||||
|
isAverageMetricType() {
|
||||||
|
return metric_key => {
|
||||||
|
return ['avg_first_response_time', 'avg_resolution_time'].includes(
|
||||||
|
metric_key
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ describe('reportMixin', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
getters = {
|
getters = {
|
||||||
getAccountSummary: () => reportFixtures.summary,
|
getAccountSummary: () => reportFixtures.summary,
|
||||||
|
getAccountReports: () => reportFixtures.report,
|
||||||
};
|
};
|
||||||
store = new Vuex.Store({ getters });
|
store = new Vuex.Store({ getters });
|
||||||
});
|
});
|
||||||
|
@ -38,4 +39,67 @@ describe('reportMixin', () => {
|
||||||
expect(wrapper.vm.calculateTrend('conversations_count')).toEqual(25);
|
expect(wrapper.vm.calculateTrend('conversations_count')).toEqual(25);
|
||||||
expect(wrapper.vm.calculateTrend('resolutions_count')).toEqual(0);
|
expect(wrapper.vm.calculateTrend('resolutions_count')).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('display info text', () => {
|
||||||
|
const Component = {
|
||||||
|
render() {},
|
||||||
|
title: 'TestComponent',
|
||||||
|
mixins: [reportMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentSelection: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
metrics() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
DESC: '( Avg )',
|
||||||
|
INFO_TEXT: 'Total number of conversations used for computation:',
|
||||||
|
KEY: 'avg_first_response_time',
|
||||||
|
NAME: 'First Response Time',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const wrapper = shallowMount(Component, { store, localVue });
|
||||||
|
expect(wrapper.vm.displayInfoText('avg_first_response_time')).toEqual(
|
||||||
|
'Total number of conversations used for computation: 4'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('do not display info text', () => {
|
||||||
|
const Component = {
|
||||||
|
render() {},
|
||||||
|
title: 'TestComponent',
|
||||||
|
mixins: [reportMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentSelection: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
metrics() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
DESC: '( Total )',
|
||||||
|
INFO_TEXT: '',
|
||||||
|
KEY: 'conversation_count',
|
||||||
|
NAME: 'Conversations',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DESC: '( Avg )',
|
||||||
|
INFO_TEXT: 'Total number of conversations used for computation:',
|
||||||
|
KEY: 'avg_first_response_time',
|
||||||
|
NAME: 'First Response Time',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const wrapper = shallowMount(Component, { store, localVue });
|
||||||
|
expect(wrapper.vm.displayInfoText('conversation_count')).toEqual('');
|
||||||
|
expect(wrapper.vm.displayInfoText('incoming_messages_count')).toEqual('');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,4 +15,15 @@ export default {
|
||||||
},
|
},
|
||||||
resolutions_count: 3,
|
resolutions_count: 3,
|
||||||
},
|
},
|
||||||
|
report: {
|
||||||
|
data: [
|
||||||
|
{ value: '0.00', timestamp: 1647541800, count: 0 },
|
||||||
|
{ value: '0.00', timestamp: 1647628200, count: 0 },
|
||||||
|
{ value: '0.00', timestamp: 1647714600, count: 0 },
|
||||||
|
{ value: '0.00', timestamp: 1647801000, count: 0 },
|
||||||
|
{ value: '0.01', timestamp: 1647887400, count: 4 },
|
||||||
|
{ value: '0.00', timestamp: 1647973800, count: 0 },
|
||||||
|
{ value: '0.00', timestamp: 1648060200, count: 0 },
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
:key="metric.NAME"
|
:key="metric.NAME"
|
||||||
:desc="metric.DESC"
|
:desc="metric.DESC"
|
||||||
:heading="metric.NAME"
|
:heading="metric.NAME"
|
||||||
|
:info-text="displayInfoText(metric.KEY)"
|
||||||
:index="index"
|
:index="index"
|
||||||
:on-click="changeSelection"
|
:on-click="changeSelection"
|
||||||
:point="displayMetric(metric.KEY)"
|
:point="displayMetric(metric.KEY)"
|
||||||
|
@ -35,7 +36,11 @@
|
||||||
:message="$t('REPORT.LOADING_CHART')"
|
:message="$t('REPORT.LOADING_CHART')"
|
||||||
/>
|
/>
|
||||||
<div v-else class="chart-container">
|
<div v-else class="chart-container">
|
||||||
<woot-bar v-if="accountReport.data.length" :collection="collection" />
|
<woot-bar
|
||||||
|
v-if="accountReport.data.length"
|
||||||
|
:collection="collection"
|
||||||
|
:chart-options="chartOptions"
|
||||||
|
/>
|
||||||
<span v-else class="empty-state">
|
<span v-else class="empty-state">
|
||||||
{{ $t('REPORT.NO_ENOUGH_DATA') }}
|
{{ $t('REPORT.NO_ENOUGH_DATA') }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -49,7 +54,7 @@ import { mapGetters } from 'vuex';
|
||||||
import fromUnixTime from 'date-fns/fromUnixTime';
|
import fromUnixTime from 'date-fns/fromUnixTime';
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
import ReportFilterSelector from './components/FilterSelector';
|
import ReportFilterSelector from './components/FilterSelector';
|
||||||
import { GROUP_BY_FILTER } from './constants';
|
import { GROUP_BY_FILTER, METRIC_CHART } from './constants';
|
||||||
import reportMixin from '../../../../mixins/reportMixin';
|
import reportMixin from '../../../../mixins/reportMixin';
|
||||||
|
|
||||||
const REPORTS_KEYS = {
|
const REPORTS_KEYS = {
|
||||||
|
@ -108,16 +113,38 @@ export default {
|
||||||
}
|
}
|
||||||
return format(fromUnixTime(element.timestamp), 'dd-MMM-yyyy');
|
return format(fromUnixTime(element.timestamp), 'dd-MMM-yyyy');
|
||||||
});
|
});
|
||||||
const data = this.accountReport.data.map(element => element.value);
|
|
||||||
|
const datasets = METRIC_CHART[
|
||||||
|
this.metrics[this.currentSelection].KEY
|
||||||
|
].datasets.map(dataset => {
|
||||||
|
switch (dataset.type) {
|
||||||
|
case 'bar':
|
||||||
|
return {
|
||||||
|
...dataset,
|
||||||
|
yAxisID: 'y-left',
|
||||||
|
label: this.metrics[this.currentSelection].NAME,
|
||||||
|
data: this.accountReport.data.map(element => element.value),
|
||||||
|
};
|
||||||
|
case 'line':
|
||||||
|
return {
|
||||||
|
...dataset,
|
||||||
|
yAxisID: 'y-right',
|
||||||
|
label: this.metrics[0].NAME,
|
||||||
|
data: this.accountReport.data.map(element => element.count),
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
labels,
|
labels,
|
||||||
datasets: [
|
datasets,
|
||||||
{
|
};
|
||||||
label: this.metrics[this.currentSelection].NAME,
|
|
||||||
backgroundColor: '#1f93ff',
|
|
||||||
data,
|
|
||||||
},
|
},
|
||||||
],
|
chartOptions() {
|
||||||
|
return {
|
||||||
|
scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
metrics() {
|
metrics() {
|
||||||
|
@ -133,6 +160,7 @@ export default {
|
||||||
NAME: this.$t(`REPORT.METRICS.${key}.NAME`),
|
NAME: this.$t(`REPORT.METRICS.${key}.NAME`),
|
||||||
KEY: REPORTS_KEYS[key],
|
KEY: REPORTS_KEYS[key],
|
||||||
DESC: this.$t(`REPORT.METRICS.${key}.DESC`),
|
DESC: this.$t(`REPORT.METRICS.${key}.DESC`),
|
||||||
|
INFO_TEXT: this.$t(`REPORT.METRICS.${key}.INFO_TEXT`),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
:key="metric.NAME"
|
:key="metric.NAME"
|
||||||
:desc="metric.DESC"
|
:desc="metric.DESC"
|
||||||
:heading="metric.NAME"
|
:heading="metric.NAME"
|
||||||
|
:info-text="displayInfoText(metric.KEY)"
|
||||||
:index="index"
|
:index="index"
|
||||||
:on-click="changeSelection"
|
:on-click="changeSelection"
|
||||||
:point="displayMetric(metric.KEY)"
|
:point="displayMetric(metric.KEY)"
|
||||||
|
@ -41,6 +42,7 @@
|
||||||
<woot-bar
|
<woot-bar
|
||||||
v-if="accountReport.data.length && filterItemsList.length"
|
v-if="accountReport.data.length && filterItemsList.length"
|
||||||
:collection="collection"
|
:collection="collection"
|
||||||
|
:chart-options="chartOptions"
|
||||||
/>
|
/>
|
||||||
<span v-else class="empty-state">
|
<span v-else class="empty-state">
|
||||||
{{ $t('REPORT.NO_ENOUGH_DATA') }}
|
{{ $t('REPORT.NO_ENOUGH_DATA') }}
|
||||||
|
@ -55,7 +57,7 @@
|
||||||
import ReportFilters from './ReportFilters';
|
import ReportFilters from './ReportFilters';
|
||||||
import fromUnixTime from 'date-fns/fromUnixTime';
|
import fromUnixTime from 'date-fns/fromUnixTime';
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
import { GROUP_BY_FILTER } from '../constants';
|
import { GROUP_BY_FILTER, METRIC_CHART } from '../constants';
|
||||||
import reportMixin from '../../../../../mixins/reportMixin';
|
import reportMixin from '../../../../../mixins/reportMixin';
|
||||||
|
|
||||||
const REPORTS_KEYS = {
|
const REPORTS_KEYS = {
|
||||||
|
@ -137,16 +139,38 @@ export default {
|
||||||
}
|
}
|
||||||
return format(fromUnixTime(element.timestamp), 'dd-MMM-yyyy');
|
return format(fromUnixTime(element.timestamp), 'dd-MMM-yyyy');
|
||||||
});
|
});
|
||||||
const data = this.accountReport.data.map(element => element.value);
|
|
||||||
|
const datasets = METRIC_CHART[
|
||||||
|
this.metrics[this.currentSelection].KEY
|
||||||
|
].datasets.map(dataset => {
|
||||||
|
switch (dataset.type) {
|
||||||
|
case 'bar':
|
||||||
|
return {
|
||||||
|
...dataset,
|
||||||
|
yAxisID: 'y-left',
|
||||||
|
label: this.metrics[this.currentSelection].NAME,
|
||||||
|
data: this.accountReport.data.map(element => element.value),
|
||||||
|
};
|
||||||
|
case 'line':
|
||||||
|
return {
|
||||||
|
...dataset,
|
||||||
|
yAxisID: 'y-right',
|
||||||
|
label: this.metrics[0].NAME,
|
||||||
|
data: this.accountReport.data.map(element => element.count),
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return dataset;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
labels,
|
labels,
|
||||||
datasets: [
|
datasets,
|
||||||
{
|
};
|
||||||
label: this.metrics[this.currentSelection].NAME,
|
|
||||||
backgroundColor: '#1f93ff',
|
|
||||||
data,
|
|
||||||
},
|
},
|
||||||
],
|
chartOptions() {
|
||||||
|
return {
|
||||||
|
scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
metrics() {
|
metrics() {
|
||||||
|
@ -168,6 +192,7 @@ export default {
|
||||||
NAME: this.$t(`REPORT.METRICS.${key}.NAME`),
|
NAME: this.$t(`REPORT.METRICS.${key}.NAME`),
|
||||||
KEY: REPORTS_KEYS[key],
|
KEY: REPORTS_KEYS[key],
|
||||||
DESC: this.$t(`REPORT.METRICS.${key}.DESC`),
|
DESC: this.$t(`REPORT.METRICS.${key}.DESC`),
|
||||||
|
INFO_TEXT: this.$t(`REPORT.METRICS.${key}.INFO_TEXT`),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,3 +4,142 @@ export const GROUP_BY_FILTER = {
|
||||||
3: { id: 3, period: 'month' },
|
3: { id: 3, period: 'month' },
|
||||||
4: { id: 4, period: 'year' },
|
4: { id: 4, period: 'year' },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const CHART_FONT_FAMILY =
|
||||||
|
'-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
|
||||||
|
|
||||||
|
export const DEFAULT_LINE_CHART = {
|
||||||
|
type: 'line',
|
||||||
|
fill: false,
|
||||||
|
borderColor: '#779BBB',
|
||||||
|
pointBackgroundColor: '#779BBB',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_BAR_CHART = {
|
||||||
|
type: 'bar',
|
||||||
|
backgroundColor: 'rgb(31, 147, 255, 0.5)',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_CHART = {
|
||||||
|
datasets: [DEFAULT_BAR_CHART],
|
||||||
|
scales: {
|
||||||
|
xAxes: [
|
||||||
|
{
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
id: 'y-left',
|
||||||
|
type: 'linear',
|
||||||
|
position: 'left',
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
beginAtZero: true,
|
||||||
|
stepSize: 1,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const METRIC_CHART = {
|
||||||
|
conversations_count: DEFAULT_CHART,
|
||||||
|
incoming_messages_count: DEFAULT_CHART,
|
||||||
|
outgoing_messages_count: DEFAULT_CHART,
|
||||||
|
avg_first_response_time: {
|
||||||
|
datasets: [DEFAULT_BAR_CHART, DEFAULT_LINE_CHART],
|
||||||
|
scales: {
|
||||||
|
xAxes: [
|
||||||
|
{
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
id: 'y-left',
|
||||||
|
type: 'linear',
|
||||||
|
position: 'left',
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
beginAtZero: true,
|
||||||
|
precision: 2,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'y-right',
|
||||||
|
type: 'linear',
|
||||||
|
position: 'right',
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
beginAtZero: true,
|
||||||
|
stepSize: 1,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
avg_resolution_time: {
|
||||||
|
datasets: [DEFAULT_BAR_CHART, DEFAULT_LINE_CHART],
|
||||||
|
scales: {
|
||||||
|
xAxes: [
|
||||||
|
{
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
yAxes: [
|
||||||
|
{
|
||||||
|
id: 'y-left',
|
||||||
|
type: 'linear',
|
||||||
|
position: 'left',
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
beginAtZero: true,
|
||||||
|
precision: 2,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'y-right',
|
||||||
|
type: 'linear',
|
||||||
|
position: 'right',
|
||||||
|
ticks: {
|
||||||
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
|
beginAtZero: true,
|
||||||
|
stepSize: 1,
|
||||||
|
},
|
||||||
|
gridLines: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
resolutions_count: DEFAULT_CHART,
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue