From c64e2e3bc5e4b6579366e8ae9b0fca19ed3932ae Mon Sep 17 00:00:00 2001 From: "Aswin Dev P.S" Date: Mon, 11 Apr 2022 20:57:22 +0530 Subject: [PATCH] chore: Report improvements (#4392) Co-authored-by: Pranav Raj S --- .../dashboard/i18n/locale/en/report.json | 32 +++++++++----- .../mixins/specs/reportMixin.spec.js | 2 +- .../dashboard/settings/reports/Index.vue | 24 +++++++++- .../reports/components/ReportFilters.vue | 6 +-- .../reports/components/WootReports.vue | 23 +++++++++- .../dashboard/settings/reports/constants.js | 44 +++++-------------- .../dashboard/store/modules/reports.js | 10 ----- package.json | 2 +- yarn.lock | 8 ++-- 9 files changed, 86 insertions(+), 65 deletions(-) diff --git a/app/javascript/dashboard/i18n/locale/en/report.json b/app/javascript/dashboard/i18n/locale/en/report.json index a14704007..1574b1cca 100644 --- a/app/javascript/dashboard/i18n/locale/en/report.json +++ b/app/javascript/dashboard/i18n/locale/en/report.json @@ -20,12 +20,14 @@ "FIRST_RESPONSE_TIME": { "NAME": "First Response Time", "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": { "NAME": "Resolution Time", "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": { "NAME": "Resolution Count", @@ -103,12 +105,14 @@ "FIRST_RESPONSE_TIME": { "NAME": "First Response Time", "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": { "NAME": "Resolution Time", "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": { "NAME": "Resolution Count", @@ -168,12 +172,14 @@ "FIRST_RESPONSE_TIME": { "NAME": "First Response Time", "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": { "NAME": "Resolution Time", "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": { "NAME": "Resolution Count", @@ -233,12 +239,14 @@ "FIRST_RESPONSE_TIME": { "NAME": "First Response Time", "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": { "NAME": "Resolution Time", "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": { "NAME": "Resolution Count", @@ -298,12 +306,14 @@ "FIRST_RESPONSE_TIME": { "NAME": "First Response Time", "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": { "NAME": "Resolution Time", "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": { "NAME": "Resolution Count", @@ -372,4 +382,4 @@ } } } -} \ No newline at end of file +} diff --git a/app/javascript/dashboard/mixins/specs/reportMixin.spec.js b/app/javascript/dashboard/mixins/specs/reportMixin.spec.js index ca1c45751..aa3c451d9 100644 --- a/app/javascript/dashboard/mixins/specs/reportMixin.spec.js +++ b/app/javascript/dashboard/mixins/specs/reportMixin.spec.js @@ -25,7 +25,7 @@ describe('reportMixin', () => { const wrapper = shallowMount(Component, { store, localVue }); expect(wrapper.vm.displayMetric('conversations_count')).toEqual(5); expect(wrapper.vm.displayMetric('avg_first_response_time')).toEqual( - '3 Min' + '3 Min 18 Sec' ); }); diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/Index.vue index f9a9256f4..bc6ac48de 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/reports/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/Index.vue @@ -57,6 +57,7 @@ import format from 'date-fns/format'; import ReportFilterSelector from './components/FilterSelector'; import { GROUP_BY_FILTER, METRIC_CHART } from './constants'; import reportMixin from '../../../../mixins/reportMixin'; +import { formatTime } from '@chatwoot/utils'; const REPORTS_KEYS = { CONVERSATIONS: 'conversations_count', @@ -145,8 +146,22 @@ export default { }; }, 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 { scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales, + tooltips: tooltips, }; }, metrics() { @@ -158,11 +173,18 @@ export default { 'RESOLUTION_TIME', '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 => ({ NAME: this.$t(`REPORT.METRICS.${key}.NAME`), KEY: REPORTS_KEYS[key], 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`, })); }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/ReportFilters.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/ReportFilters.vue index 0bfeae8a1..c0b87e19b 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/ReportFilters.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/ReportFilters.vue @@ -148,9 +148,9 @@
{{ $t('REPORT.BUSINESS_HOURS') }} - - - + + +
diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/components/WootReports.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/components/WootReports.vue index 7a54765b8..6d8b49c62 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/reports/components/WootReports.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/components/WootReports.vue @@ -60,6 +60,7 @@ import fromUnixTime from 'date-fns/fromUnixTime'; import format from 'date-fns/format'; import { GROUP_BY_FILTER, METRIC_CHART } from '../constants'; import reportMixin from '../../../../../mixins/reportMixin'; +import { formatTime } from '@chatwoot/utils'; const REPORTS_KEYS = { CONVERSATIONS: 'conversations_count', @@ -171,8 +172,21 @@ export default { }; }, 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 { scales: METRIC_CHART[this.metrics[this.currentSelection].KEY].scales, + tooltips: tooltips, }; }, metrics() { @@ -190,11 +204,18 @@ export default { 'RESOLUTION_TIME', '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 => ({ NAME: this.$t(`REPORT.METRICS.${key}.NAME`), KEY: REPORTS_KEYS[key], 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`, })); }, }, diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/constants.js b/app/javascript/dashboard/routes/dashboard/settings/reports/constants.js index 91348543e..c44f2bdef 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/reports/constants.js +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/constants.js @@ -1,3 +1,5 @@ +import { formatTime } from '@chatwoot/utils'; + export const GROUP_BY_FILTER = { 1: { id: 1, period: 'day' }, 2: { id: 2, period: 'week' }, @@ -17,7 +19,7 @@ export const DEFAULT_LINE_CHART = { export const DEFAULT_BAR_CHART = { type: 'bar', - backgroundColor: 'rgb(31, 147, 255, 0.5)', + backgroundColor: 'rgb(31, 147, 255)', }; export const DEFAULT_CHART = { @@ -56,7 +58,7 @@ export const METRIC_CHART = { incoming_messages_count: DEFAULT_CHART, outgoing_messages_count: DEFAULT_CHART, avg_first_response_time: { - datasets: [DEFAULT_BAR_CHART, DEFAULT_LINE_CHART], + datasets: [DEFAULT_BAR_CHART], scales: { xAxes: [ { @@ -75,21 +77,9 @@ export const METRIC_CHART = { 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, + callback(value) { + return formatTime(value); + }, }, gridLines: { drawOnChartArea: false, @@ -99,7 +89,7 @@ export const METRIC_CHART = { }, }, avg_resolution_time: { - datasets: [DEFAULT_BAR_CHART, DEFAULT_LINE_CHART], + datasets: [DEFAULT_BAR_CHART], scales: { xAxes: [ { @@ -118,21 +108,9 @@ export const METRIC_CHART = { 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, + callback(value) { + return formatTime(value); + }, }, gridLines: { drawOnChartArea: false, diff --git a/app/javascript/dashboard/store/modules/reports.js b/app/javascript/dashboard/store/modules/reports.js index 67f468add..0b31883bf 100644 --- a/app/javascript/dashboard/store/modules/reports.js +++ b/app/javascript/dashboard/store/modules/reports.js @@ -50,16 +50,6 @@ export const actions = { el => 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.TOGGLE_ACCOUNT_REPORT_LOADING, false); }); diff --git a/package.json b/package.json index 7371322b6..1b55668b3 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "dependencies": { "@braid/vue-formulate": "^2.5.2", "@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", "@rails/actioncable": "6.1.3", "@rails/webpacker": "5.3.0", diff --git a/yarn.lock b/yarn.lock index b4c4e505c..a95d08798 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1111,10 +1111,10 @@ prosemirror-state "^1.3.3" prosemirror-view "^1.17.2" -"@chatwoot/utils@^0.0.5": - version "0.0.5" - resolved "https://registry.npmjs.org/@chatwoot/utils/-/utils-0.0.5.tgz#907cdae747abc17cf2e5c31a378aba66a2f31c6f" - integrity sha512-gTQMpQuYVF5EaF4+xSmaoJKXPtbwDPjNLi5cwg44FaQSfmzFxD0fjDsDUPrxzZfURLsR8eU7Z1ulVKnZdHN4yg== +"@chatwoot/utils@^0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@chatwoot/utils/-/utils-0.0.6.tgz#76d7b17d692b5b656c565b9b714b98e0f2bc1324" + integrity sha512-fCvULfJSFSylDAiGh1cPAX5nQkVsmG5ASGm/E6YBYg8cox/2JU179JFstdtTxrIJg/YeHukcaq85Gc+/16ShPQ== dependencies: date-fns "^2.22.1"