From 0a2fd7b1f4d5cf69d7031b07d2ee6ef4952b9f34 Mon Sep 17 00:00:00 2001 From: Pranav Date: Wed, 19 Feb 2025 14:54:15 -0800 Subject: [PATCH] feat: Allow users to see heatmap for last 30 days (#10848) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Screenshot 2025-02-05 at 6 34 12 PM View heatmaps for last 30 days based on the filter. --- app/helpers/api/v2/accounts/heatmap_helper.rb | 3 +- app/javascript/dashboard/api/reports.js | 4 +- .../dashboard/composables/useLiveRefresh.js | 28 +++++ .../settings/reports/LiveReports.vue | 54 +------- .../settings/reports/components/Heatmap.vue | 14 ++- .../reports/components/HeatmapContainer.vue | 119 ++++++++++++++++++ .../components/overview/MetricCard.vue | 36 +++--- .../dashboard/store/modules/reports.js | 12 +- 8 files changed, 179 insertions(+), 91 deletions(-) create mode 100644 app/javascript/dashboard/composables/useLiveRefresh.js create mode 100644 app/javascript/dashboard/routes/dashboard/settings/reports/components/HeatmapContainer.vue diff --git a/app/helpers/api/v2/accounts/heatmap_helper.rb b/app/helpers/api/v2/accounts/heatmap_helper.rb index 58dade28d..a4977f43a 100644 --- a/app/helpers/api/v2/accounts/heatmap_helper.rb +++ b/app/helpers/api/v2/accounts/heatmap_helper.rb @@ -94,7 +94,8 @@ module Api::V2::Accounts::HeatmapHelper end def since_timestamp(date) - (date - 6.days).to_i.to_s + number_of_days = params[:days_before].present? ? params[:days_before].to_i.days : 6.days + (date - number_of_days).to_i.to_s end def until_timestamp(date) diff --git a/app/javascript/dashboard/api/reports.js b/app/javascript/dashboard/api/reports.js index 52fa7f444..c87dfc82b 100644 --- a/app/javascript/dashboard/api/reports.js +++ b/app/javascript/dashboard/api/reports.js @@ -61,9 +61,9 @@ class ReportsAPI extends ApiClient { }); } - getConversationTrafficCSV() { + getConversationTrafficCSV({ daysBefore = 6 } = {}) { return axios.get(`${this.url}/conversation_traffic`, { - params: { timezone_offset: getTimeOffset() }, + params: { timezone_offset: getTimeOffset(), days_before: daysBefore }, }); } diff --git a/app/javascript/dashboard/composables/useLiveRefresh.js b/app/javascript/dashboard/composables/useLiveRefresh.js new file mode 100644 index 000000000..666e345b8 --- /dev/null +++ b/app/javascript/dashboard/composables/useLiveRefresh.js @@ -0,0 +1,28 @@ +import { ref, onBeforeUnmount } from 'vue'; + +export const useLiveRefresh = (callback, interval = 60000) => { + const timeoutId = ref(null); + + const startRefetching = () => { + timeoutId.value = setTimeout(async () => { + await callback(); + startRefetching(); + }, interval); + }; + + const stopRefetching = () => { + if (timeoutId.value) { + clearTimeout(timeoutId.value); + timeoutId.value = null; + } + }; + + onBeforeUnmount(() => { + stopRefetching(); + }); + + return { + startRefetching, + stopRefetching, + }; +}; diff --git a/app/javascript/dashboard/routes/dashboard/settings/reports/LiveReports.vue b/app/javascript/dashboard/routes/dashboard/settings/reports/LiveReports.vue index 27b2126ea..3e343fd05 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/reports/LiveReports.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/reports/LiveReports.vue @@ -3,13 +3,11 @@ import { mapGetters } from 'vuex'; import AgentTable from './components/overview/AgentTable.vue'; import MetricCard from './components/overview/MetricCard.vue'; import { OVERVIEW_METRICS } from './constants'; -import ReportHeatmap from './components/Heatmap.vue'; import endOfDay from 'date-fns/endOfDay'; import getUnixTime from 'date-fns/getUnixTime'; -import startOfDay from 'date-fns/startOfDay'; -import subDays from 'date-fns/subDays'; import ReportHeader from './components/ReportHeader.vue'; +import HeatmapContainer from './components/HeatmapContainer.vue'; export const FETCH_INTERVAL = 60000; export default { @@ -18,7 +16,7 @@ export default { ReportHeader, AgentTable, MetricCard, - ReportHeatmap, + HeatmapContainer, }, data() { return { @@ -33,7 +31,6 @@ export default { agents: 'agents/getAgents', accountConversationMetric: 'getAccountConversationMetric', agentConversationMetric: 'getAgentConversationMetric', - accountConversationHeatmap: 'getAccountConversationHeatmapData', uiFlags: 'getOverviewUIFlags', }), agentStatusMetrics() { @@ -80,7 +77,6 @@ export default { fetchAllData() { this.fetchAccountConversationMetric(); this.fetchAgentConversationMetric(); - this.fetchHeatmapData(); }, downloadHeatmapData() { let to = endOfDay(new Date()); @@ -89,33 +85,7 @@ export default { to: getUnixTime(to), }); }, - fetchHeatmapData() { - if (this.uiFlags.isFetchingAccountConversationsHeatmap) { - return; - } - // the data for the last 6 days won't ever change, - // so there's no need to fetch it again - // but we can write some logic to check if the data is already there - // if it is there, we can refetch data only for today all over again - // and reconcile it with the rest of the data - // this will reduce the load on the server doing number crunching - let to = endOfDay(new Date()); - let from = startOfDay(subDays(to, 6)); - - if (this.accountConversationHeatmap.length) { - to = endOfDay(new Date()); - from = startOfDay(to); - } - - this.$store.dispatch('fetchAccountConversationHeatmap', { - metric: 'conversations_count', - from: getUnixTime(from), - to: getUnixTime(to), - groupBy: 'hour', - businessHours: false, - }); - }, fetchAccountConversationMetric() { this.$store.dispatch('fetchAccountConversationMetric', { type: 'account', @@ -180,25 +150,7 @@ export default { -
- - - - -
+
[], }, + numberOfRows: { + type: Number, + default: 7, + }, isLoading: { type: Boolean, default: false, @@ -21,11 +25,11 @@ const props = defineProps({ }); const { t } = useI18n(); const processedData = computed(() => { - return groupHeatmapByDay(props.heatData); + return groupHeatmapByDay(props.heatmapData); }); const quantileRange = computed(() => { - const flattendedData = props.heatData.map(data => data.value); + const flattendedData = props.heatmapData.map(data => data.value); return getQuantileIntervals(flattendedData, [0.2, 0.4, 0.6, 0.8, 0.9, 0.99]); }); @@ -95,14 +99,14 @@ function getHeatmapLevelClass(value) {