chore: Add an option to download CSAT Reports (#4694)
This commit is contained in:
parent
361ffbab82
commit
47f04ee3fe
16 changed files with 189 additions and 28 deletions
|
@ -18,6 +18,17 @@ class CSATReportsAPI extends ApiClient {
|
|||
});
|
||||
}
|
||||
|
||||
download({ from, to, user_ids } = {}) {
|
||||
return axios.get(`${this.url}/download`, {
|
||||
params: {
|
||||
since: from,
|
||||
until: to,
|
||||
sort: '-created_at',
|
||||
user_ids,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getMetrics({ from, to, user_ids } = {}) {
|
||||
return axios.get(`${this.url}/metrics`, {
|
||||
params: { since: from, until: to, user_ids },
|
||||
|
|
|
@ -33,5 +33,23 @@ describe('#Reports API', () => {
|
|||
}
|
||||
);
|
||||
});
|
||||
it('#download', () => {
|
||||
csatReportsAPI.download({
|
||||
from: 1622485800,
|
||||
to: 1623695400,
|
||||
user_ids: 1,
|
||||
});
|
||||
expect(context.axiosMock.get).toHaveBeenCalledWith(
|
||||
'/api/v1/csat_survey_responses/download',
|
||||
{
|
||||
params: {
|
||||
since: 1622485800,
|
||||
until: 1623695400,
|
||||
user_ids: 1,
|
||||
sort: '-created_at',
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import fromUnixTime from 'date-fns/fromUnixTime';
|
||||
import format from 'date-fns/format';
|
||||
|
||||
export const downloadCsvFile = (fileName, fileContent) => {
|
||||
const link = document.createElement('a');
|
||||
link.download = fileName;
|
||||
link.href = `data:text/csv;charset=utf-8,` + encodeURI(fileContent);
|
||||
link.click();
|
||||
};
|
||||
|
||||
export const generateFileName = ({ type, to }) =>
|
||||
`${type}-report-${format(fromUnixTime(to), 'dd-MM-yyyy')}.csv`;
|
|
@ -1,4 +1,4 @@
|
|||
import { downloadCsvFile } from '../downloadCsvFile';
|
||||
import { downloadCsvFile, generateFileName } from '../downloadHelper';
|
||||
|
||||
const fileName = 'test.csv';
|
||||
const fileData = `Agent name,Conversations count,Avg first response time (Minutes),Avg resolution time (Minutes)
|
||||
|
@ -19,3 +19,11 @@ describe('#downloadCsvFile', () => {
|
|||
expect(link.click).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#generateFileName', () => {
|
||||
it('should generate the correct file name', () => {
|
||||
expect(generateFileName({ type: 'csat', to: 1652812199 })).toEqual(
|
||||
'csat-report-17-05-2022.csv'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -354,6 +354,7 @@
|
|||
"CSAT_REPORTS": {
|
||||
"HEADER": "CSAT Reports",
|
||||
"NO_RECORDS": "There are no CSAT survey responses available.",
|
||||
"DOWNLOAD": "Download CSAT Reports",
|
||||
"FILTERS": {
|
||||
"AGENTS": {
|
||||
"PLACEHOLDER": "Choose Agents"
|
||||
|
|
|
@ -3,9 +3,18 @@
|
|||
<report-filter-selector
|
||||
agents-filter
|
||||
:agents-filter-items-list="agentList"
|
||||
:show-business-hours-switch="false"
|
||||
@date-range-change="onDateRangeChange"
|
||||
@agents-filter-change="onAgentsFilterChange"
|
||||
/>
|
||||
<woot-button
|
||||
color-scheme="success"
|
||||
class-names="button--fixed-right-top"
|
||||
icon="arrow-download"
|
||||
@click="downloadReports"
|
||||
>
|
||||
{{ $t('CSAT_REPORTS.DOWNLOAD') }}
|
||||
</woot-button>
|
||||
<csat-metrics />
|
||||
<csat-table :page-index="pageIndex" @page-change="onPageNumberChange" />
|
||||
</div>
|
||||
|
@ -15,6 +24,7 @@ import CsatMetrics from './components/CsatMetrics';
|
|||
import CsatTable from './components/CsatTable';
|
||||
import ReportFilterSelector from './components/FilterSelector';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { generateFileName } from '../../../../helper/downloadHelper';
|
||||
|
||||
export default {
|
||||
name: 'CsatResponses',
|
||||
|
@ -24,7 +34,7 @@ export default {
|
|||
ReportFilterSelector,
|
||||
},
|
||||
data() {
|
||||
return { pageIndex: 1, from: 0, to: 0, user_ids: [] };
|
||||
return { pageIndex: 1, from: 0, to: 0, userIds: [] };
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
|
@ -39,7 +49,7 @@ export default {
|
|||
this.$store.dispatch('csat/getMetrics', {
|
||||
from: this.from,
|
||||
to: this.to,
|
||||
user_ids: this.user_ids,
|
||||
user_ids: this.userIds,
|
||||
});
|
||||
this.getResponses();
|
||||
},
|
||||
|
@ -48,7 +58,7 @@ export default {
|
|||
page: this.pageIndex,
|
||||
from: this.from,
|
||||
to: this.to,
|
||||
user_ids: this.user_ids,
|
||||
user_ids: this.userIds,
|
||||
});
|
||||
},
|
||||
onPageNumberChange(pageIndex) {
|
||||
|
@ -61,9 +71,18 @@ export default {
|
|||
this.getAllData();
|
||||
},
|
||||
onAgentsFilterChange(agents) {
|
||||
this.user_ids = agents.map(el => el.id);
|
||||
this.userIds = agents.map(el => el.id);
|
||||
this.getAllData();
|
||||
},
|
||||
downloadReports() {
|
||||
const type = 'csat';
|
||||
this.$store.dispatch('csat/downloadCSATReports', {
|
||||
from: this.from,
|
||||
to: this.to,
|
||||
user_ids: this.userIds,
|
||||
fileName: generateFileName({ type, to: this.to }),
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -61,7 +61,10 @@
|
|||
@input="handleAgentsFilterSelection"
|
||||
/>
|
||||
</div>
|
||||
<div class="small-12 medium-3 business-hours">
|
||||
<div
|
||||
v-if="showBusinessHoursSwitch"
|
||||
class="small-12 medium-3 business-hours"
|
||||
>
|
||||
<span class="business-hours-text margin-right-small">
|
||||
{{ $t('REPORT.BUSINESS_HOURS') }}
|
||||
</span>
|
||||
|
@ -105,6 +108,10 @@ export default {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
showBusinessHoursSwitch: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -61,6 +61,7 @@ import format from 'date-fns/format';
|
|||
import { GROUP_BY_FILTER, METRIC_CHART } from '../constants';
|
||||
import reportMixin from '../../../../../mixins/reportMixin';
|
||||
import { formatTime } from '@chatwoot/utils';
|
||||
import { generateFileName } from '../../../../../helper/downloadHelper';
|
||||
|
||||
const REPORTS_KEYS = {
|
||||
CONVERSATIONS: 'conversations_count',
|
||||
|
@ -250,26 +251,17 @@ export default {
|
|||
});
|
||||
},
|
||||
downloadReports() {
|
||||
const { from, to } = this;
|
||||
const fileName = `${this.type}-report-${format(
|
||||
fromUnixTime(to),
|
||||
'dd-MM-yyyy'
|
||||
)}.csv`;
|
||||
switch (this.type) {
|
||||
case 'agent':
|
||||
this.$store.dispatch('downloadAgentReports', { from, to, fileName });
|
||||
break;
|
||||
case 'label':
|
||||
this.$store.dispatch('downloadLabelReports', { from, to, fileName });
|
||||
break;
|
||||
case 'inbox':
|
||||
this.$store.dispatch('downloadInboxReports', { from, to, fileName });
|
||||
break;
|
||||
case 'team':
|
||||
this.$store.dispatch('downloadTeamReports', { from, to, fileName });
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
const { from, to, type } = this;
|
||||
const dispatchMethods = {
|
||||
agent: 'downloadAgentReports',
|
||||
label: 'downloadLabelReports',
|
||||
inbox: 'downloadInboxReports',
|
||||
team: 'downloadTeamReports',
|
||||
};
|
||||
if (dispatchMethods[type]) {
|
||||
const fileName = generateFileName({ type, to });
|
||||
const params = { from, to, fileName };
|
||||
this.$store.dispatch(dispatchMethods[type], params);
|
||||
}
|
||||
},
|
||||
changeSelection(index) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
|
||||
import types from '../mutation-types';
|
||||
import CSATReports from '../../api/csatReports';
|
||||
import { downloadCsvFile } from '../../helper/downloadHelper';
|
||||
|
||||
const computeDistribution = (value, total) =>
|
||||
((value * 100) / total).toFixed(2);
|
||||
|
@ -107,6 +108,11 @@ export const actions = {
|
|||
commit(types.SET_CSAT_RESPONSE_UI_FLAG, { isFetchingMetrics: false });
|
||||
}
|
||||
},
|
||||
downloadCSATReports(_, params) {
|
||||
return CSATReports.download(params).then(response => {
|
||||
downloadCsvFile(params.fileName, response.data);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export const mutations = {
|
||||
|
|
|
@ -5,7 +5,7 @@ import * as types from '../mutation-types';
|
|||
import Report from '../../api/reports';
|
||||
import Vue from 'vue';
|
||||
|
||||
import { downloadCsvFile } from '../../helper/downloadCsvFile';
|
||||
import { downloadCsvFile } from '../../helper/downloadHelper';
|
||||
|
||||
const state = {
|
||||
fetchingStatus: false,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue