diff --git a/app/javascript/dashboard/i18n/locale/en/settings.json b/app/javascript/dashboard/i18n/locale/en/settings.json
index e8eac0e8e..f87e59930 100644
--- a/app/javascript/dashboard/i18n/locale/en/settings.json
+++ b/app/javascript/dashboard/i18n/locale/en/settings.json
@@ -58,9 +58,19 @@
"AUDIO_NOTIFICATIONS_SECTION": {
"TITLE": "Audio Notifications",
"NOTE": "Enable audio notifications in dashboard for new messages and conversations.",
- "NONE": "None",
- "ASSIGNED": "Assigned Conversations",
- "ALL_CONVERSATIONS": "All Conversations"
+ "ALERT_TYPE": {
+ "TITLE": "Alert types:",
+ "NONE": "None",
+ "ASSIGNED": "Assigned Conversations",
+ "ALL_CONVERSATIONS": "All Conversations"
+ },
+ "DEFAULT_TONE": {
+ "TITLE": "Default tone:"
+ },
+ "CONDITIONS": {
+ "TITLE": "Conditions:",
+ "CONDITION_ONE": "Send audio alerts only if the browser window is not active"
+ }
},
"EMAIL_NOTIFICATIONS_SECTION": {
"TITLE": "Email Notifications",
diff --git a/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue b/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue
index 60584d726..af8f14f8f 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue
@@ -10,50 +10,115 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -257,6 +322,18 @@ export default {
selectedPushFlags: [],
enableAudioAlerts: false,
hasEnabledPushPermissions: false,
+ playAudioWhenTabIsInactive: false,
+ notificationTone: 'ding',
+ notificationAlertTones: [
+ {
+ value: 'ding',
+ label: 'Ding',
+ },
+ {
+ value: 'bell',
+ label: 'Bell',
+ },
+ ],
};
},
computed: {
@@ -280,20 +357,27 @@ export default {
this.selectedPushFlags = value;
},
uiSettings(value) {
- const { enable_audio_alerts: enableAudio = false } = value;
- this.enableAudioAlerts = enableAudio;
+ this.notificationUISettings(value);
},
},
mounted() {
if (hasPushPermissions()) {
this.getPushSubscription();
}
-
+ this.notificationUISettings(this.uiSettings);
this.$store.dispatch('userNotificationSettings/get');
- const { enable_audio_alerts: enableAudio = false } = this.uiSettings;
- this.enableAudioAlerts = enableAudio;
},
methods: {
+ notificationUISettings(uiSettings) {
+ const {
+ enable_audio_alerts: enableAudio = false,
+ always_play_audio_alert: alwaysPlayAudioAlert,
+ notification_tone: notificationTone,
+ } = uiSettings;
+ this.enableAudioAlerts = enableAudio;
+ this.playAudioWhenTabIsInactive = !alwaysPlayAudioAlert;
+ this.notificationTone = notificationTone || 'ding';
+ },
onRegistrationSuccess() {
this.hasEnabledPushPermissions = true;
},
@@ -351,6 +435,19 @@ export default {
});
this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS'));
},
+ handleAudioAlertConditions(e) {
+ let condition = e.target.value;
+ if (condition === 'tab_is_inactive') {
+ this.updateUISettings({
+ always_play_audio_alert: !e.target.checked,
+ });
+ }
+ this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS'));
+ },
+ handleAudioToneChange(e) {
+ this.updateUISettings({ notification_tone: e.target.value });
+ this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS'));
+ },
toggleInput(selected, current) {
if (selected.includes(current)) {
const newSelectedFlags = selected.filter(flag => flag !== current);
@@ -372,4 +469,21 @@ export default {
.push-notification--button {
margin-bottom: var(--space-one);
}
+
+.notification-items--wrapper {
+ margin-bottom: var(--space-smaller);
+}
+
+.notification-label {
+ display: flex;
+ font-weight: var(--font-weight-bold);
+ margin-bottom: var(--space-small);
+}
+
+.tone-selector {
+ height: var(--space-large);
+ padding-bottom: var(--space-micro);
+ padding-top: var(--space-micro);
+ width: var(--space-mega);
+}
diff --git a/app/javascript/shared/assets/audio/bell.mp3 b/app/javascript/shared/assets/audio/bell.mp3
new file mode 100644
index 000000000..77087072f
Binary files /dev/null and b/app/javascript/shared/assets/audio/bell.mp3 differ
diff --git a/app/javascript/shared/helpers/AudioNotificationHelper.js b/app/javascript/shared/helpers/AudioNotificationHelper.js
index a80a12e14..7474eb583 100644
--- a/app/javascript/shared/helpers/AudioNotificationHelper.js
+++ b/app/javascript/shared/helpers/AudioNotificationHelper.js
@@ -15,10 +15,20 @@ export const getAudioContext = () => {
return audioCtx;
};
+const getAlertTone = alertType => {
+ if (alertType === 'dashboard') {
+ const {
+ notification_tone: tone,
+ } = window.WOOT.$store.getters.getUISettings;
+ return tone;
+ }
+ return 'ding';
+};
+
export const getAlertAudio = async (baseUrl = '', type = 'dashboard') => {
const audioCtx = getAudioContext();
- const playsound = audioBuffer => {
+ const playSound = audioBuffer => {
window.playAudioAlert = () => {
if (audioCtx) {
const source = audioCtx.createBufferSource();
@@ -31,13 +41,14 @@ export const getAlertAudio = async (baseUrl = '', type = 'dashboard') => {
};
if (audioCtx) {
- const resourceUrl = `${baseUrl}/audio/${type}/ding.mp3`;
+ const alertTone = getAlertTone(type);
+ const resourceUrl = `${baseUrl}/audio/${type}/${alertTone}.mp3`;
const audioRequest = new Request(resourceUrl);
fetch(audioRequest)
.then(response => response.arrayBuffer())
.then(buffer => {
- audioCtx.decodeAudioData(buffer).then(playsound);
+ audioCtx.decodeAudioData(buffer).then(playSound);
return new Promise(res => res());
})
.catch(() => {
@@ -91,6 +102,7 @@ export const getAssigneeFromNotification = currentConv => {
}
return id;
};
+
export const newMessageNotification = data => {
const { conversation_id: currentConvId } = window.WOOT.$route.params;
const currentUserId = window.WOOT.$store.getters.getCurrentUserID;
@@ -98,10 +110,13 @@ export const newMessageNotification = data => {
const currentConv =
window.WOOT.$store.getters.getConversationById(incomingConvId) || {};
const assigneeId = getAssigneeFromNotification(currentConv);
- const isDocHidden = document.hidden;
+
const {
enable_audio_alerts: enableAudioAlerts = false,
+ always_play_audio_alert: alwaysPlayAudioAlert,
} = window.WOOT.$store.getters.getUISettings;
+ const isDocHidden = alwaysPlayAudioAlert ? true : document.hidden;
+
const playAudio = shouldPlayAudio(
data,
currentConvId,
diff --git a/public/audio/dashboard/bell.mp3 b/public/audio/dashboard/bell.mp3
new file mode 100644
index 000000000..77087072f
Binary files /dev/null and b/public/audio/dashboard/bell.mp3 differ