Skip to content

Commit

Permalink
feat: Revamp notification and audio preferences (#9312)
Browse files Browse the repository at this point in the history
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
  • Loading branch information
muhsin-k and iamsivin committed Apr 30, 2024
1 parent 4fd8c7a commit c92ea11
Show file tree
Hide file tree
Showing 13 changed files with 794 additions and 7 deletions.
26 changes: 24 additions & 2 deletions app/javascript/dashboard/i18n/locale/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,19 @@
},
"ACCESS_TOKEN": {
"TITLE": "Access Token",
"NOTE": "This token can be used if you are building an API based integration"
"NOTE": "This token can be used if you are building an API based integration",
"COPY": "Copy"
},
"AUDIO_NOTIFICATIONS_SECTION": {
"TITLE": "Audio Notifications",
"NOTE": "Enable audio notifications in dashboard for new messages and conversations.",
"ALERT_TYPES": {
"NONE": "None",
"MINE": "Assigned",
"ALL": "All"
},
"ALERT_TYPE": {
"TITLE": "Alert events:",
"TITLE": "Alert events for conversations:",
"NONE": "None",
"ASSIGNED": "Assigned Conversations",
"ALL_CONVERSATIONS": "All Conversations"
Expand All @@ -89,6 +95,22 @@
"SLA_MISSED_NEXT_RESPONSE": "Send email notifications when a conversation misses next response SLA",
"SLA_MISSED_RESOLUTION": "Send email notifications when a conversation misses resolution SLA"
},
"NOTIFICATIONS": {
"TITLE": "Notification preferences",
"TYPE_TITLE": "Notification type",
"EMAIL": "Email",
"PUSH": "Push notification",
"TYPES": {
"CONVERSATION_CREATED": "A new conversation is created",
"CONVERSATION_ASSIGNED": "A conversation is assigned to you",
"CONVERSATION_MENTION": "You are mentioned in a conversation",
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "A new message is created in an assigned conversation",
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "A new message is created in a participating conversation",
"SLA_MISSED_FIRST_RESPONSE": "A conversation misses first response SLA",
"SLA_MISSED_NEXT_RESPONSE": "A conversation misses next response SLA",
"SLA_MISSED_RESOLUTION": "A conversation misses resolution SLA"
}
},
"API": {
"UPDATE_SUCCESS": "Your notification preferences are updated successfully",
"UPDATE_ERROR": "There is an error while updating the preferences, please try again"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<template>
<div>
<label
class="flex justify-between pb-1 text-sm font-medium leading-6 text-ash-900"
>
{{ label }}
</label>
<div class="flex flex-col gap-4">
<div
v-for="item in items"
:key="item.id"
class="flex flex-row items-start gap-2"
>
<CheckBox
:is-checked="item.model"
:value="item.value"
@update="onChange"
/>
<label class="text-sm font-normal text-ash-900">
{{ item.label }}
</label>
</div>
</div>
</div>
</template>
<script setup>
import CheckBox from 'v3/components/Form/CheckBox.vue';
defineProps({
label: {
type: String,
required: true,
},
items: {
type: Array,
required: true,
},
});
const emit = defineEmits(['change']);
const onChange = (id, value) => {
emit('change', id, value);
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template>
<div>
<label
class="flex justify-between pb-1 text-sm font-medium leading-6 text-ash-900"
>
{{ label }}
</label>
<div
class="flex flex-row justify-between h-10 max-w-xl p-2 border border-solid rounded-xl border-ash-200"
>
<div
v-for="option in alertEvents"
:key="option.value"
class="flex flex-row items-center justify-center gap-2 px-4 border-r border-ash-200 grow last:border-r-0"
>
<input
:id="`radio-${option.value}`"
v-model="selectedValue"
class="shadow cursor-pointer grid place-items-center border-2 border-ash-200 appearance-none rounded-full w-4 h-4 checked:bg-primary-600 before:content-[''] before:bg-primary-600 before:border-4 before:rounded-full before:border-ash-25 checked:before:w-[14px] checked:before:h-[14px] checked:border checked:border-primary-600"
type="radio"
:value="option.value"
/>
<label
:for="`radio-${option.value}`"
class="text-sm font-medium"
:class="
selectedValue === option.value ? 'text-ash-900' : 'text-ash-800'
"
>
{{
$t(
`PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALERT_TYPES.${option.label.toUpperCase()}`
)
}}
</label>
</div>
</div>
</div>
</template>

<script setup>
import { computed } from 'vue';
import { ALERT_EVENTS } from './constants';
const props = defineProps({
label: {
type: String,
default: '',
},
value: {
type: String,
default: 'all',
},
});
const alertEvents = ALERT_EVENTS;
const emit = defineEmits(['update']);
const selectedValue = computed({
get: () => props.value,
set: value => {
emit('update', value);
},
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<form-select
v-model="selectedValue"
name="alertTone"
spacing="compact"
:value="selectedValue"
:options="alertTones"
:label="label"
class="max-w-xl"
>
<option
v-for="tone in alertTones"
:key="tone.label"
:value="tone.value"
:selected="tone.value === selectedValue"
>
{{ tone.label }}
</option>
</form-select>
</template>
<script setup>
import { computed } from 'vue';
import FormSelect from 'v3/components/Form/Select.vue';
const props = defineProps({
value: {
type: String,
required: true,
validator: value => ['ding', 'bell'].includes(value),
},
label: {
type: String,
default: '',
},
});
const alertTones = computed(() => [
{
value: 'ding',
label: 'Ding',
},
{
value: 'bell',
label: 'Bell',
},
]);
const emit = defineEmits(['change']);
const selectedValue = computed({
get: () => props.value,
set: value => {
emit('change', value);
},
});
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<template>
<div id="profile-settings-notifications" class="flex flex-col gap-6">
<audio-alert-tone
:value="alertTone"
:label="
$t(
'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.DEFAULT_TONE.TITLE'
)
"
@change="handleAudioToneChange"
/>

<audio-alert-event
:label="
$t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.ALERT_TYPE.TITLE')
"
:value="audioAlert"
@update="handAudioAlertChange"
/>

<audio-alert-condition
:items="audioAlertConditions"
:label="
$t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.CONDITIONS.TITLE')
"
@change="handleAudioAlertConditions"
/>
</div>
</template>

<script>
import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin';
import configMixin from 'shared/mixins/configMixin';
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
import AudioAlertTone from './AudioAlertTone.vue';
import AudioAlertEvent from './AudioAlertEvent.vue';
import AudioAlertCondition from './AudioAlertCondition.vue';
export default {
components: {
AudioAlertEvent,
AudioAlertTone,
AudioAlertCondition,
},
mixins: [alertMixin, configMixin, uiSettingsMixin],
data() {
return {
audioAlert: '',
playAudioWhenTabIsInactive: false,
alertIfUnreadConversationExist: false,
alertTone: 'ding',
audioAlertConditions: [],
};
},
computed: {
...mapGetters({
accountId: 'getCurrentAccountId',
uiSettings: 'getUISettings',
}),
},
watch: {
uiSettings(value) {
this.notificationUISettings(value);
},
},
mounted() {
this.notificationUISettings(this.uiSettings);
this.$store.dispatch('userNotificationSettings/get');
},
methods: {
notificationUISettings(uiSettings) {
const {
enable_audio_alerts: audioAlert = '',
always_play_audio_alert: alwaysPlayAudioAlert,
alert_if_unread_assigned_conversation_exist:
alertIfUnreadConversationExist,
notification_tone: alertTone,
} = uiSettings;
this.audioAlert = audioAlert;
this.playAudioWhenTabIsInactive = !alwaysPlayAudioAlert;
this.alertIfUnreadConversationExist = alertIfUnreadConversationExist;
this.audioAlertConditions = [
{
id: 'audio1',
label: this.$t(
'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.CONDITIONS.CONDITION_ONE'
),
model: this.playAudioWhenTabIsInactive,
value: 'tab_is_inactive',
},
{
id: 'audio2',
label: this.$t(
'PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.CONDITIONS.CONDITION_TWO'
),
model: this.alertIfUnreadConversationExist,
value: 'conversations_are_read',
},
];
this.alertTone = alertTone || 'ding';
},
handAudioAlertChange(value) {
this.audioAlert = value;
this.updateUISettings({
enable_audio_alerts: this.audioAlert,
});
this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS'));
},
handleAudioAlertConditions(id, value) {
if (id === 'tab_is_inactive') {
this.updateUISettings({
always_play_audio_alert: !value,
});
} else if (id === 'conversations_are_read') {
this.updateUISettings({
alert_if_unread_assigned_conversation_exist: value,
});
}
this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS'));
},
handleAudioToneChange(value) {
this.updateUISettings({ notification_tone: value });
this.showAlert(this.$t('PROFILE_SETTINGS.FORM.API.UPDATE_SUCCESS'));
},
},
};
</script>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="flex items-center w-full overflow-y-auto">
<div class="flex flex-col h-full p-5 pt-16 mx-auto my-0 font-inter">
<div class="flex flex-col gap-16 sm:max-w-[720px]">
<div class="flex flex-col gap-16 pb-8 sm:max-w-[720px]">
<div class="flex flex-col gap-6">
<h2 class="mt-4 text-2xl font-medium text-ash-900">
{{ $t('PROFILE_SETTINGS.TITLE') }}
Expand Down Expand Up @@ -62,6 +62,19 @@
>
<change-password v-if="!globalConfig.disableUserProfileUpdate" />
</form-section>
<form-section
:header="
$t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.TITLE')
"
:description="
$t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.NOTE')
"
>
<audio-notifications />
</form-section>
<form-section :header="$t('PROFILE_SETTINGS.FORM.NOTIFICATIONS.TITLE')">
<notification-preferences />
</form-section>
</div>
</div>
</div>
Expand All @@ -80,6 +93,8 @@ import UserBasicDetails from './UserBasicDetails.vue';
import MessageSignature from './MessageSignature.vue';
import HotKeyCard from './HotKeyCard.vue';
import ChangePassword from './ChangePassword.vue';
import NotificationPreferences from './NotificationPreferences.vue';
import AudioNotifications from './AudioNotifications.vue';
import FormSection from 'dashboard/components/FormSection.vue';
export default {
Expand All @@ -90,6 +105,8 @@ export default {
UserBasicDetails,
HotKeyCard,
ChangePassword,
NotificationPreferences,
AudioNotifications,
},
mixins: [alertMixin, globalConfigMixin, uiSettingsMixin],
data() {
Expand Down

0 comments on commit c92ea11

Please sign in to comment.