chore: Report improvements (#4392)
Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
parent
31cdc63e18
commit
c64e2e3bc5
9 changed files with 86 additions and 65 deletions
|
@ -20,12 +20,14 @@
|
||||||
"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:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )",
|
"DESC": "( Avg )",
|
||||||
"INFO_TEXT": "Total number of conversations used for computation:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -103,12 +105,14 @@
|
||||||
"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:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )",
|
"DESC": "( Avg )",
|
||||||
"INFO_TEXT": "Total number of conversations used for computation:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -168,12 +172,14 @@
|
||||||
"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:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )",
|
"DESC": "( Avg )",
|
||||||
"INFO_TEXT": "Total number of conversations used for computation:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -233,12 +239,14 @@
|
||||||
"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:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )",
|
"DESC": "( Avg )",
|
||||||
"INFO_TEXT": "Total number of conversations used for computation:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -298,12 +306,14 @@
|
||||||
"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:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "First Response Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_TIME": {
|
"RESOLUTION_TIME": {
|
||||||
"NAME": "Resolution Time",
|
"NAME": "Resolution Time",
|
||||||
"DESC": "( Avg )",
|
"DESC": "( Avg )",
|
||||||
"INFO_TEXT": "Total number of conversations used for computation:"
|
"INFO_TEXT": "Total number of conversations used for computation:",
|
||||||
|
"TOOLTIP_TEXT": "Resolution Time is %{metricValue} (based on %{conversationCount} conversations)"
|
||||||
},
|
},
|
||||||
"RESOLUTION_COUNT": {
|
"RESOLUTION_COUNT": {
|
||||||
"NAME": "Resolution Count",
|
"NAME": "Resolution Count",
|
||||||
|
@ -372,4 +382,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ describe('reportMixin', () => {
|
||||||
const wrapper = shallowMount(Component, { store, localVue });
|
const wrapper = shallowMount(Component, { store, localVue });
|
||||||
expect(wrapper.vm.displayMetric('conversations_count')).toEqual(5);
|
expect(wrapper.vm.displayMetric('conversations_count')).toEqual(5);
|
||||||
expect(wrapper.vm.displayMetric('avg_first_response_time')).toEqual(
|
expect(wrapper.vm.displayMetric('avg_first_response_time')).toEqual(
|
||||||
'3 Min'
|
'3 Min 18 Sec'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ import format from 'date-fns/format';
|
||||||
import ReportFilterSelector from './components/FilterSelector';
|
import ReportFilterSelector from './components/FilterSelector';
|
||||||
import { GROUP_BY_FILTER, METRIC_CHART } from './constants';
|
import { GROUP_BY_FILTER, METRIC_CHART } from './constants';
|
||||||
import reportMixin from '../../../../mixins/reportMixin';
|
import reportMixin from '../../../../mixins/reportMixin';
|
||||||
|
import { formatTime } from '@chatwoot/utils';
|
||||||
|
|
||||||
const REPORTS_KEYS = {
|
const REPORTS_KEYS = {
|
||||||
CONVERSATIONS: 'conversations_count',
|
CONVERSATIONS: 'conversations_count',
|
||||||
|
@ -145,8 +146,22 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
chartOptions() {
|
chartOptions() {
|
||||||
|
let tooltips = {};
|
||||||
|
if (this.isAverageMetricType(this.metrics[this.currentSelection].KEY)) {
|
||||||
|
tooltips.callbacks = {
|
||||||
|
label: tooltipItem => {
|
||||||
|
return this.$t(this.metrics[this.currentSelection].TOOLTIP_TEXT, {
|
||||||
|
metricValue: formatTime(tooltipItem.yLabel),
|
||||||
|
conversationCount: this.accountReport.data[tooltipItem.index]
|
||||||
|
.count,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales,
|
scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales,
|
||||||
|
tooltips: tooltips,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
metrics() {
|
metrics() {
|
||||||
|
@ -158,11 +173,18 @@ export default {
|
||||||
'RESOLUTION_TIME',
|
'RESOLUTION_TIME',
|
||||||
'RESOLUTION_COUNT',
|
'RESOLUTION_COUNT',
|
||||||
];
|
];
|
||||||
|
const infoText = {
|
||||||
|
FIRST_RESPONSE_TIME: this.$t(
|
||||||
|
`REPORT.METRICS.FIRST_RESPONSE_TIME.INFO_TEXT`
|
||||||
|
),
|
||||||
|
RESOLUTION_TIME: this.$t(`REPORT.METRICS.RESOLUTION_TIME.INFO_TEXT`),
|
||||||
|
};
|
||||||
return reportKeys.map(key => ({
|
return reportKeys.map(key => ({
|
||||||
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`),
|
INFO_TEXT: infoText[key],
|
||||||
|
TOOLTIP_TEXT: `REPORT.METRICS.${key}.TOOLTIP_TEXT`,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -148,9 +148,9 @@
|
||||||
<div class="small-12 medium-3 business-hours">
|
<div class="small-12 medium-3 business-hours">
|
||||||
<span class="business-hours-text margin-right-small">
|
<span class="business-hours-text margin-right-small">
|
||||||
{{ $t('REPORT.BUSINESS_HOURS') }}
|
{{ $t('REPORT.BUSINESS_HOURS') }}
|
||||||
<span>
|
</span>
|
||||||
<woot-switch v-model="businessHoursSelected" />
|
<span>
|
||||||
</span>
|
<woot-switch v-model="businessHoursSelected" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -60,6 +60,7 @@ import fromUnixTime from 'date-fns/fromUnixTime';
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
import { GROUP_BY_FILTER, METRIC_CHART } from '../constants';
|
import { GROUP_BY_FILTER, METRIC_CHART } from '../constants';
|
||||||
import reportMixin from '../../../../../mixins/reportMixin';
|
import reportMixin from '../../../../../mixins/reportMixin';
|
||||||
|
import { formatTime } from '@chatwoot/utils';
|
||||||
|
|
||||||
const REPORTS_KEYS = {
|
const REPORTS_KEYS = {
|
||||||
CONVERSATIONS: 'conversations_count',
|
CONVERSATIONS: 'conversations_count',
|
||||||
|
@ -171,8 +172,21 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
chartOptions() {
|
chartOptions() {
|
||||||
|
let tooltips = {};
|
||||||
|
if (this.isAverageMetricType(this.metrics[this.currentSelection].KEY)) {
|
||||||
|
tooltips.callbacks = {
|
||||||
|
label: tooltipItem => {
|
||||||
|
return this.$t(this.metrics[this.currentSelection].TOOLTIP_TEXT, {
|
||||||
|
metricValue: formatTime(tooltipItem.yLabel),
|
||||||
|
conversationCount: this.accountReport.data[tooltipItem.index]
|
||||||
|
.count,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales,
|
scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales,
|
||||||
|
tooltips: tooltips,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
metrics() {
|
metrics() {
|
||||||
|
@ -190,11 +204,18 @@ export default {
|
||||||
'RESOLUTION_TIME',
|
'RESOLUTION_TIME',
|
||||||
'RESOLUTION_COUNT',
|
'RESOLUTION_COUNT',
|
||||||
];
|
];
|
||||||
|
const infoText = {
|
||||||
|
FIRST_RESPONSE_TIME: this.$t(
|
||||||
|
`REPORT.METRICS.FIRST_RESPONSE_TIME.INFO_TEXT`
|
||||||
|
),
|
||||||
|
RESOLUTION_TIME: this.$t(`REPORT.METRICS.RESOLUTION_TIME.INFO_TEXT`),
|
||||||
|
};
|
||||||
return reportKeys.map(key => ({
|
return reportKeys.map(key => ({
|
||||||
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`),
|
INFO_TEXT: infoText[key],
|
||||||
|
TOOLTIP_TEXT: `REPORT.METRICS.${key}.TOOLTIP_TEXT`,
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { formatTime } from '@chatwoot/utils';
|
||||||
|
|
||||||
export const GROUP_BY_FILTER = {
|
export const GROUP_BY_FILTER = {
|
||||||
1: { id: 1, period: 'day' },
|
1: { id: 1, period: 'day' },
|
||||||
2: { id: 2, period: 'week' },
|
2: { id: 2, period: 'week' },
|
||||||
|
@ -17,7 +19,7 @@ export const DEFAULT_LINE_CHART = {
|
||||||
|
|
||||||
export const DEFAULT_BAR_CHART = {
|
export const DEFAULT_BAR_CHART = {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
backgroundColor: 'rgb(31, 147, 255, 0.5)',
|
backgroundColor: 'rgb(31, 147, 255)',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_CHART = {
|
export const DEFAULT_CHART = {
|
||||||
|
@ -56,7 +58,7 @@ export const METRIC_CHART = {
|
||||||
incoming_messages_count: DEFAULT_CHART,
|
incoming_messages_count: DEFAULT_CHART,
|
||||||
outgoing_messages_count: DEFAULT_CHART,
|
outgoing_messages_count: DEFAULT_CHART,
|
||||||
avg_first_response_time: {
|
avg_first_response_time: {
|
||||||
datasets: [DEFAULT_BAR_CHART, DEFAULT_LINE_CHART],
|
datasets: [DEFAULT_BAR_CHART],
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [
|
xAxes: [
|
||||||
{
|
{
|
||||||
|
@ -75,21 +77,9 @@ export const METRIC_CHART = {
|
||||||
position: 'left',
|
position: 'left',
|
||||||
ticks: {
|
ticks: {
|
||||||
fontFamily: CHART_FONT_FAMILY,
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
beginAtZero: true,
|
callback(value) {
|
||||||
precision: 2,
|
return formatTime(value);
|
||||||
},
|
},
|
||||||
gridLines: {
|
|
||||||
drawOnChartArea: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'y-right',
|
|
||||||
type: 'linear',
|
|
||||||
position: 'right',
|
|
||||||
ticks: {
|
|
||||||
fontFamily: CHART_FONT_FAMILY,
|
|
||||||
beginAtZero: true,
|
|
||||||
stepSize: 1,
|
|
||||||
},
|
},
|
||||||
gridLines: {
|
gridLines: {
|
||||||
drawOnChartArea: false,
|
drawOnChartArea: false,
|
||||||
|
@ -99,7 +89,7 @@ export const METRIC_CHART = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
avg_resolution_time: {
|
avg_resolution_time: {
|
||||||
datasets: [DEFAULT_BAR_CHART, DEFAULT_LINE_CHART],
|
datasets: [DEFAULT_BAR_CHART],
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [
|
xAxes: [
|
||||||
{
|
{
|
||||||
|
@ -118,21 +108,9 @@ export const METRIC_CHART = {
|
||||||
position: 'left',
|
position: 'left',
|
||||||
ticks: {
|
ticks: {
|
||||||
fontFamily: CHART_FONT_FAMILY,
|
fontFamily: CHART_FONT_FAMILY,
|
||||||
beginAtZero: true,
|
callback(value) {
|
||||||
precision: 2,
|
return formatTime(value);
|
||||||
},
|
},
|
||||||
gridLines: {
|
|
||||||
drawOnChartArea: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'y-right',
|
|
||||||
type: 'linear',
|
|
||||||
position: 'right',
|
|
||||||
ticks: {
|
|
||||||
fontFamily: CHART_FONT_FAMILY,
|
|
||||||
beginAtZero: true,
|
|
||||||
stepSize: 1,
|
|
||||||
},
|
},
|
||||||
gridLines: {
|
gridLines: {
|
||||||
drawOnChartArea: false,
|
drawOnChartArea: false,
|
||||||
|
|
|
@ -50,16 +50,6 @@ export const actions = {
|
||||||
el =>
|
el =>
|
||||||
reportObj.to - el.timestamp > 0 && el.timestamp - reportObj.from >= 0
|
reportObj.to - el.timestamp > 0 && el.timestamp - reportObj.from >= 0
|
||||||
);
|
);
|
||||||
if (
|
|
||||||
reportObj.metric === 'avg_first_response_time' ||
|
|
||||||
reportObj.metric === 'avg_resolution_time'
|
|
||||||
) {
|
|
||||||
data = data.map(element => {
|
|
||||||
/* eslint-disable operator-assignment */
|
|
||||||
element.value = (element.value / 3600).toFixed(2);
|
|
||||||
return element;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
commit(types.default.SET_ACCOUNT_REPORTS, data);
|
commit(types.default.SET_ACCOUNT_REPORTS, data);
|
||||||
commit(types.default.TOGGLE_ACCOUNT_REPORT_LOADING, false);
|
commit(types.default.TOGGLE_ACCOUNT_REPORT_LOADING, false);
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braid/vue-formulate": "^2.5.2",
|
"@braid/vue-formulate": "^2.5.2",
|
||||||
"@chatwoot/prosemirror-schema": "https://github.com/chatwoot/prosemirror-schema.git#7e8acadd10d7b932c0dc0bd0a18f804434f83517",
|
"@chatwoot/prosemirror-schema": "https://github.com/chatwoot/prosemirror-schema.git#7e8acadd10d7b932c0dc0bd0a18f804434f83517",
|
||||||
"@chatwoot/utils": "^0.0.5",
|
"@chatwoot/utils": "^0.0.6",
|
||||||
"@hcaptcha/vue-hcaptcha": "^0.3.2",
|
"@hcaptcha/vue-hcaptcha": "^0.3.2",
|
||||||
"@rails/actioncable": "6.1.3",
|
"@rails/actioncable": "6.1.3",
|
||||||
"@rails/webpacker": "5.3.0",
|
"@rails/webpacker": "5.3.0",
|
||||||
|
|
|
@ -1111,10 +1111,10 @@
|
||||||
prosemirror-state "^1.3.3"
|
prosemirror-state "^1.3.3"
|
||||||
prosemirror-view "^1.17.2"
|
prosemirror-view "^1.17.2"
|
||||||
|
|
||||||
"@chatwoot/utils@^0.0.5":
|
"@chatwoot/utils@^0.0.6":
|
||||||
version "0.0.5"
|
version "0.0.6"
|
||||||
resolved "https://registry.npmjs.org/@chatwoot/utils/-/utils-0.0.5.tgz#907cdae747abc17cf2e5c31a378aba66a2f31c6f"
|
resolved "https://registry.yarnpkg.com/@chatwoot/utils/-/utils-0.0.6.tgz#76d7b17d692b5b656c565b9b714b98e0f2bc1324"
|
||||||
integrity sha512-gTQMpQuYVF5EaF4+xSmaoJKXPtbwDPjNLi5cwg44FaQSfmzFxD0fjDsDUPrxzZfURLsR8eU7Z1ulVKnZdHN4yg==
|
integrity sha512-fCvULfJSFSylDAiGh1cPAX5nQkVsmG5ASGm/E6YBYg8cox/2JU179JFstdtTxrIJg/YeHukcaq85Gc+/16ShPQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
date-fns "^2.22.1"
|
date-fns "^2.22.1"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue