Merge branch 'develop' into report-rewrite

This commit is contained in:
Pranav
2024-03-28 16:00:01 -07:00
1120 changed files with 20061 additions and 6509 deletions
@@ -1,4 +1,4 @@
import { applyInboxPageFilters, sortComparator } from './helpers';
import { sortComparator } from './helpers';
export const getters = {
getNotifications($state) {
@@ -6,14 +6,14 @@ export const getters = {
},
getFilteredNotifications: $state => filters => {
const sortOrder = filters.sortOrder === 'desc' ? 'newest' : 'oldest';
const filteredNotifications = Object.values($state.records).filter(
notification => applyInboxPageFilters(notification, filters)
);
const sortedNotifications = filteredNotifications.sort((a, b) =>
sortComparator(a, b, sortOrder)
const sortedNotifications = Object.values($state.records).sort((n1, n2) =>
sortComparator(n1, n2, sortOrder)
);
return sortedNotifications;
},
getNotificationById: $state => id => {
return $state.records[id] || {};
},
getUIFlags($state) {
return $state.uiFlags;
},
@@ -1,31 +1,3 @@
export const filterByStatus = (snoozedUntil, filterStatus) =>
filterStatus === 'snoozed' ? !!snoozedUntil : !snoozedUntil;
export const filterByType = (readAt, filterType) =>
filterType === 'read' ? !!readAt : !readAt;
export const filterByTypeAndStatus = (
readAt,
snoozedUntil,
filterType,
filterStatus
) => {
const shouldFilterByStatus = filterByStatus(snoozedUntil, filterStatus);
const shouldFilterByType = filterByType(readAt, filterType);
return shouldFilterByStatus && shouldFilterByType;
};
export const applyInboxPageFilters = (notification, filters) => {
const { status, type } = filters;
const { read_at: readAt, snoozed_until: snoozedUntil } = notification;
if (status && type)
return filterByTypeAndStatus(readAt, snoozedUntil, type, status);
if (status && !type) return filterByStatus(snoozedUntil, status);
if (!status && type) return filterByType(readAt, type);
return true;
};
const INBOX_SORT_OPTIONS = {
newest: 'desc',
oldest: 'asc',
@@ -17,6 +17,8 @@ const state = {
avg_first_response_time: false,
avg_resolution_time: false,
resolutions_count: false,
bot_resolutions_count: false,
bot_handoffs_count: false,
reply_time: false,
},
data: {
@@ -26,6 +28,8 @@ const state = {
avg_first_response_time: [],
avg_resolution_time: [],
resolutions_count: [],
bot_resolutions_count: [],
bot_handoffs_count: [],
reply_time: [],
},
},
@@ -37,6 +41,13 @@ const state = {
outgoing_messages_count: 0,
reply_time: 0,
resolutions_count: 0,
bot_resolutions_count: 0,
bot_handoffs_count: 0,
previous: {},
},
botSummary: {
bot_resolutions_count: 0,
bot_handoffs_count: 0,
previous: {},
},
overview: {
@@ -60,6 +71,9 @@ const getters = {
getAccountSummary(_state) {
return _state.accountSummary;
},
getBotSummary(_state) {
return _state.botSummary;
},
getAccountConversationMetric(_state) {
return _state.overview.accountConversationMetric;
},
@@ -123,6 +137,20 @@ export const actions = {
commit(types.default.TOGGLE_ACCOUNT_REPORT_LOADING, false);
});
},
fetchBotSummary({ commit }, reportObj) {
Report.getBotSummary({
from: reportObj.from,
to: reportObj.to,
groupBy: reportObj.groupBy,
businessHours: reportObj.businessHours,
})
.then(botSummary => {
commit(types.default.SET_BOT_SUMMARY, botSummary.data);
})
.catch(() => {
commit(types.default.TOGGLE_ACCOUNT_REPORT_LOADING, false);
});
},
fetchLiveConversationMetric({ commit }, params = {}) {
commit(types.default.TOGGLE_ACCOUNT_CONVERSATION_METRIC_LOADING, true);
liveReports
@@ -258,6 +286,9 @@ const mutations = {
[types.default.SET_ACCOUNT_SUMMARY](_state, summaryData) {
_state.accountSummary = summaryData;
},
[types.default.SET_BOT_SUMMARY](_state, summaryData) {
_state.botSummary = summaryData;
},
[types.default.SET_ACCOUNT_CONVERSATION_METRIC](_state, metricData) {
_state.overview.accountConversationMetric = metricData;
},
@@ -0,0 +1,86 @@
import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
import types from '../mutation-types';
import SlaAPI from '../../api/sla';
import AnalyticsHelper from '../../helper/AnalyticsHelper';
import { SLA_EVENTS } from '../../helper/AnalyticsHelper/events';
import { throwErrorMessage } from '../utils/api';
export const state = {
records: [],
uiFlags: {
isFetching: false,
isFetchingItem: false,
isCreating: false,
isDeleting: false,
},
};
export const getters = {
getSLA(_state) {
return _state.records;
},
getUIFlags(_state) {
return _state.uiFlags;
},
};
export const actions = {
get: async function get({ commit }) {
commit(types.SET_SLA_UI_FLAG, { isFetching: true });
try {
const response = await SlaAPI.get();
commit(types.SET_SLA, response.data.payload);
} catch (error) {
// Ignore error
} finally {
commit(types.SET_SLA_UI_FLAG, { isFetching: false });
}
},
create: async function create({ commit }, slaObj) {
commit(types.SET_SLA_UI_FLAG, { isCreating: true });
try {
const response = await SlaAPI.create(slaObj);
AnalyticsHelper.track(SLA_EVENTS.CREATE);
commit(types.ADD_SLA, response.data.payload);
} catch (error) {
throwErrorMessage(error);
} finally {
commit(types.SET_SLA_UI_FLAG, { isCreating: false });
}
},
delete: async function deleteSla({ commit }, id) {
commit(types.SET_SLA_UI_FLAG, { isDeleting: true });
try {
await SlaAPI.delete(id);
AnalyticsHelper.track(SLA_EVENTS.DELETED);
commit(types.DELETE_SLA, id);
} catch (error) {
throwErrorMessage(error);
} finally {
commit(types.SET_SLA_UI_FLAG, { isDeleting: false });
}
},
};
export const mutations = {
[types.SET_SLA_UI_FLAG](_state, data) {
_state.uiFlags = {
..._state.uiFlags,
...data,
};
},
[types.SET_SLA]: MutationHelpers.set,
[types.ADD_SLA]: MutationHelpers.create,
[types.DELETE_SLA]: MutationHelpers.destroy,
};
export default {
namespaced: true,
state,
getters,
actions,
mutations,
};
@@ -34,6 +34,8 @@ describe('#getters', () => {
sortOrder: 'desc',
};
expect(getters.getFilteredNotifications(state)(filters)).toEqual([
{ id: 1, read_at: '2024-02-07T11:42:39.988Z', snoozed_until: null },
{ id: 2, read_at: null, snoozed_until: null },
{
id: 3,
read_at: '2024-02-07T11:42:39.988Z',
@@ -42,6 +44,16 @@ describe('#getters', () => {
]);
});
it('getNotificationById', () => {
const state = {
records: {
1: { id: 1 },
},
};
expect(getters.getNotificationById(state)(1)).toEqual({ id: 1 });
expect(getters.getNotificationById(state)(2)).toEqual({});
});
it('getUIFlags', () => {
const state = {
uiFlags: {
@@ -1,10 +1,4 @@
import {
filterByStatus,
filterByType,
filterByTypeAndStatus,
applyInboxPageFilters,
sortComparator,
} from '../../notifications/helpers';
import { sortComparator } from '../../notifications/helpers';
const notifications = [
{
@@ -45,126 +39,6 @@ const notifications = [
},
];
describe('#filterByStatus', () => {
it('returns the notifications with snoozed status', () => {
const filters = { status: 'snoozed' };
notifications.forEach(notification => {
expect(
filterByStatus(notification.snoozed_until, filters.status)
).toEqual(notification.snoozed_until !== null);
});
});
it('returns true if the notification is snoozed', () => {
const filters = { status: 'snoozed' };
expect(
filterByStatus(notifications[3].snoozed_until, filters.status)
).toEqual(true);
});
it('returns false if the notification is not snoozed', () => {
const filters = { status: 'snoozed' };
expect(
filterByStatus(notifications[2].snoozed_until, filters.status)
).toEqual(false);
});
});
describe('#filterByType', () => {
it('returns the notifications with read status', () => {
const filters = { type: 'read' };
notifications.forEach(notification => {
expect(filterByType(notification.read_at, filters.type)).toEqual(
notification.read_at !== null
);
});
});
it('returns true if the notification is read', () => {
const filters = { type: 'read' };
expect(filterByType(notifications[0].read_at, filters.type)).toEqual(true);
});
it('returns false if the notification is not read', () => {
const filters = { type: 'read' };
expect(filterByType(notifications[1].read_at, filters.type)).toEqual(false);
});
});
describe('#filterByTypeAndStatus', () => {
it('returns the notifications with type and status', () => {
const filters = { type: 'read', status: 'snoozed' };
notifications.forEach(notification => {
expect(
filterByTypeAndStatus(
notification.read_at,
notification.snoozed_until,
filters.type,
filters.status
)
).toEqual(
notification.read_at !== null && notification.snoozed_until !== null
);
});
});
it('returns true if the notification is read and snoozed', () => {
const filters = { type: 'read', status: 'snoozed' };
expect(
filterByTypeAndStatus(
notifications[4].read_at,
notifications[4].snoozed_until,
filters.type,
filters.status
)
).toEqual(true);
});
it('returns false if the notification is not read and snoozed', () => {
const filters = { type: 'read', status: 'snoozed' };
expect(
filterByTypeAndStatus(
notifications[3].read_at,
notifications[3].snoozed_until,
filters.type,
filters.status
)
).toEqual(false);
});
});
describe('#applyInboxPageFilters', () => {
it('returns the notifications with type and status', () => {
const filters = { type: 'read', status: 'snoozed' };
notifications.forEach(notification => {
expect(applyInboxPageFilters(notification, filters)).toEqual(
filterByTypeAndStatus(
notification.read_at,
notification.snoozed_until,
filters.type,
filters.status
)
);
});
});
it('returns the notifications with type only', () => {
const filters = { type: 'read', status: null };
notifications.forEach(notification => {
expect(applyInboxPageFilters(notification, filters)).toEqual(
filterByType(notification.read_at, filters.type)
);
});
});
it('returns the notifications with status only', () => {
const filters = { type: null, status: 'snoozed' };
notifications.forEach(notification => {
expect(applyInboxPageFilters(notification, filters)).toEqual(
filterByStatus(notification.snoozed_until, filters.status)
);
});
});
it('returns true if there are no filters', () => {
const filters = { type: null, status: null };
notifications.forEach(notification => {
expect(applyInboxPageFilters(notification, filters)).toEqual(true);
});
});
});
describe('#sortComparator', () => {
it('returns the notifications sorted by newest', () => {
const sortOrder = 'newest';