feat: Add settings for audio alert notifications (#2415)

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
Sivin Varghese
2021-07-05 12:01:54 +05:30
committed by GitHub
parent 48127e00d7
commit 0bd48129b9
9 changed files with 130 additions and 42 deletions

View File

@@ -28,7 +28,9 @@
"AUDIO_NOTIFICATIONS_SECTION": {
"TITLE": "Audio Notifications",
"NOTE": "Enable audio notifications in dashboard for new messages and conversations.",
"ENABLE_AUDIO": "Play audio notification when a new conversation is created or new messages arrives"
"NONE": "None",
"ASSIGNED": "Assigned Conversations",
"ALL_CONVERSATIONS": "All Conversations"
},
"EMAIL_NOTIFICATIONS_SECTION": {
"TITLE": "Email Notifications",

View File

@@ -12,16 +12,45 @@
<div class="columns small-9">
<div>
<input
id="audio_enable_alert"
id="audio_enable_alert_none"
v-model="enableAudioAlerts"
class="notification--checkbox"
type="checkbox"
type="radio"
value="none"
@input="handleAudioInput"
/>
<label for="audio_enable_alert">
<label for="audio_enable_alert_none">
{{ $t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.NONE') }}
</label>
</div>
<div>
<input
id="audio_enable_alert_mine"
v-model="enableAudioAlerts"
class="notification--checkbox"
type="radio"
value="mine"
@input="handleAudioInput"
/>
<label for="audio_enable_alert_mine">
{{
$t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ASSIGNED')
}}
</label>
</div>
<div>
<input
id="audio_enable_alert_all"
v-model="enableAudioAlerts"
class="notification--checkbox"
type="radio"
value="all"
@input="handleAudioInput"
/>
<label for="audio_enable_alert_all">
{{
$t(
'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ENABLE_AUDIO'
'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALL_CONVERSATIONS'
)
}}
</label>
@@ -315,7 +344,7 @@ export default {
this.updateNotificationSettings();
},
handleAudioInput(e) {
this.enableAudioAlerts = e.target.checked;
this.enableAudioAlerts = e.target.value;
this.updateUISettings({
enable_audio_alerts: this.enableAudioAlerts,
});

View File

@@ -63,6 +63,9 @@ const getters = {
},
getChatStatusFilter: ({ chatStatusFilter }) => chatStatusFilter,
getSelectedInbox: ({ currentInbox }) => currentInbox,
getConversationById: _state => conversationId => {
return _state.allConversations.find(value => value.id === conversationId);
},
};
export default getters;

View File

@@ -102,4 +102,16 @@ describe('#getters', () => {
]);
});
});
describe('#getConversationById', () => {
it('get conversations based on id', () => {
const state = {
allConversations: [
{
id: 1,
},
],
};
expect(getters.getConversationById(state)(1)).toEqual({ id: 1 });
});
});
});

View File

@@ -1,16 +1,7 @@
import { MESSAGE_TYPE } from 'shared/constants/messages';
const notificationAudio = require('shared/assets/audio/ding.mp3');
import axios from 'axios';
import { showBadgeOnFavicon } from './faviconHelper';
export const playNotificationAudio = () => {
try {
new Audio(notificationAudio).play();
} catch (error) {
// error
}
};
export const getAlertAudio = async () => {
window.playAudioAlert = () => {};
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
@@ -35,11 +26,21 @@ export const getAlertAudio = async () => {
}
};
export const notificationEnabled = (enableAudioAlerts, id, userId) => {
if (enableAudioAlerts === 'mine') {
return userId === id;
}
if (enableAudioAlerts === 'all') {
return true;
}
return false;
};
export const shouldPlayAudio = (
message,
conversationId,
userId,
isDocHiddden
isDocHidden
) => {
const {
conversation_id: incomingConvId,
@@ -51,29 +52,44 @@ export const shouldPlayAudio = (
const playAudio =
!isFromCurrentUser && (messageType === MESSAGE_TYPE.INCOMING || isPrivate);
if (isDocHiddden) return playAudio;
if (isDocHidden) return playAudio;
if (conversationId !== incomingConvId) return playAudio;
return false;
};
export const getAssigneeFromNotification = currentConv => {
let id;
if (currentConv.meta) {
const assignee = currentConv.meta.assignee;
if (assignee) {
id = assignee.id;
}
}
return id;
};
export const newMessageNotification = data => {
const { conversation_id: currentConvId } = window.WOOT.$route.params;
const currentUserId = window.WOOT.$store.getters.getCurrentUserID;
const isDocHiddden = document.hidden;
const { conversation_id: incomingConvId } = data;
const currentConv =
window.WOOT.$store.getters.getConversationById(incomingConvId) || {};
const assigneeId = getAssigneeFromNotification(currentConv);
const isDocHidden = document.hidden;
const {
enable_audio_alerts: enableAudioAlerts = false,
} = window.WOOT.$store.getters.getUISettings;
const playAudio = shouldPlayAudio(
data,
currentConvId,
currentUserId,
isDocHiddden
isDocHidden
);
if (enableAudioAlerts && playAudio) {
const isNotificationEnabled = notificationEnabled(
enableAudioAlerts,
currentUserId,
assigneeId
);
if (playAudio && isNotificationEnabled) {
window.playAudioAlert();
showBadgeOnFavicon();
}

View File

@@ -2,7 +2,11 @@
* @jest-environment jsdom
*/
import { shouldPlayAudio } from '../AudioNotificationHelper';
import {
shouldPlayAudio,
notificationEnabled,
getAssigneeFromNotification,
} from '../AudioNotificationHelper';
describe('shouldPlayAudio', () => {
describe('Document active', () => {
@@ -107,3 +111,41 @@ describe('shouldPlayAudio', () => {
});
});
});
describe('notificationEnabled', () => {
it('returns true if mine', () => {
const [enableAudioAlerts, userId, id] = ['mine', 1, 1];
const result = notificationEnabled(enableAudioAlerts, userId, id);
expect(result).toBe(true);
});
it('returns true if all', () => {
const [enableAudioAlerts, userId, id] = ['all', 1, 2];
const result = notificationEnabled(enableAudioAlerts, userId, id);
expect(result).toBe(true);
});
it('returns false if none', () => {
const [enableAudioAlerts, userId, id] = ['none', 1, 2];
const result = notificationEnabled(enableAudioAlerts, userId, id);
expect(result).toBe(false);
});
});
describe('getAssigneeFromNotification', () => {
it('Retuns true if gets notification from assignee', () => {
const currentConv = {
id: 1,
accountId: 1,
meta: {
assignee: {
id: 1,
name: 'John',
},
},
};
const result = getAssigneeFromNotification(currentConv);
expect(result).toBe(1);
});
it('Retuns true if gets notification from assignee is udefined', () => {
const currentConv = {};
const result = getAssigneeFromNotification(currentConv);
expect(result).toBe(undefined);
});
});

View File

@@ -8,7 +8,7 @@ import {
} from 'widget/api/conversation';
import { refreshActionCableConnector } from '../../../helpers/actionCable';
import { createTemporaryMessage, onNewMessageCreated } from './helpers';
import { createTemporaryMessage } from './helpers';
export const actions = {
createConversation: async ({ commit, dispatch }, params) => {
@@ -78,7 +78,6 @@ export const actions = {
addMessage: async ({ commit }, data) => {
commit('pushMessageToConversation', data);
onNewMessageCreated(data);
},
updateMessage({ commit }, data) {

View File

@@ -1,5 +1,4 @@
import { MESSAGE_TYPE } from 'widget/helpers/constants';
import { playNotificationAudio } from 'shared/helpers/AudioNotificationHelper';
import { isASubmittedFormMessage } from 'shared/helpers/MessageTypeHelper';
import getUuid from '../../../helpers/uuid';
@@ -47,12 +46,3 @@ export const findUndeliveredMessage = (messageInbox, { content }) =>
Object.values(messageInbox).filter(
message => message.content === content && message.status === 'in_progress'
);
export const onNewMessageCreated = data => {
const { message_type: messageType } = data;
const isIncomingMessage = messageType === MESSAGE_TYPE.OUTGOING;
if (isIncomingMessage) {
playNotificationAudio();
}
};

View File

@@ -1,12 +1,8 @@
import { playNotificationAudio } from 'shared/helpers/AudioNotificationHelper';
import { actions } from '../../conversation/actions';
import getUuid from '../../../../helpers/uuid';
import { API } from 'widget/helpers/axios';
jest.mock('../../../../helpers/uuid');
jest.mock('shared/helpers/AudioNotificationHelper', () => ({
playNotificationAudio: jest.fn(),
}));
jest.mock('widget/helpers/axios');
const commit = jest.fn();
@@ -20,7 +16,6 @@ describe('#actions', () => {
it('plays audio when agent sends a message', () => {
actions.addMessage({ commit }, { id: 1, message_type: 1 });
expect(playNotificationAudio).toBeCalled();
expect(commit).toBeCalledWith('pushMessageToConversation', {
id: 1,
message_type: 1,