chore: Report improvements (#4392)

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
Aswin Dev P.S 2022-04-11 20:57:22 +05:30 committed by GitHub
parent 31cdc63e18
commit c64e2e3bc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 86 additions and 65 deletions

View file

@ -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 @@
} }
} }
} }
} }

View file

@ -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'
); );
}); });

View file

@ -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`,
})); }));
}, },
}, },

View file

@ -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>

View file

@ -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`,
})); }));
}, },
}, },

View file

@ -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,

View file

@ -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);
}); });

View file

@ -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",

View file

@ -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"