Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Co-authored-by: iamsivin <iamsivin@gmail.com> Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
300 lines
9.5 KiB
Vue
300 lines
9.5 KiB
Vue
<script>
|
|
import { mapGetters } from 'vuex';
|
|
import { useAlert } from 'dashboard/composables';
|
|
import { useUISettings } from 'dashboard/composables/useUISettings';
|
|
import { useFontSize } from 'dashboard/composables/useFontSize';
|
|
import { clearCookiesOnLogout } from 'dashboard/store/utils/api.js';
|
|
import { copyTextToClipboard } from 'shared/helpers/clipboard';
|
|
import { parseAPIErrorResponse } from 'dashboard/store/utils/api';
|
|
import globalConfigMixin from 'shared/mixins/globalConfigMixin';
|
|
import UserProfilePicture from './UserProfilePicture.vue';
|
|
import UserBasicDetails from './UserBasicDetails.vue';
|
|
import MessageSignature from './MessageSignature.vue';
|
|
import FontSize from './FontSize.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';
|
|
import AccessToken from './AccessToken.vue';
|
|
import Policy from 'dashboard/components/policy.vue';
|
|
import {
|
|
ROLES,
|
|
CONVERSATION_PERMISSIONS,
|
|
} from 'dashboard/constants/permissions.js';
|
|
|
|
export default {
|
|
components: {
|
|
MessageSignature,
|
|
FormSection,
|
|
FontSize,
|
|
UserProfilePicture,
|
|
Policy,
|
|
UserBasicDetails,
|
|
HotKeyCard,
|
|
ChangePassword,
|
|
NotificationPreferences,
|
|
AudioNotifications,
|
|
AccessToken,
|
|
},
|
|
mixins: [globalConfigMixin],
|
|
setup() {
|
|
const { isEditorHotKeyEnabled, updateUISettings } = useUISettings();
|
|
const { currentFontSize, updateFontSize } = useFontSize();
|
|
|
|
return {
|
|
currentFontSize,
|
|
updateFontSize,
|
|
isEditorHotKeyEnabled,
|
|
updateUISettings,
|
|
};
|
|
},
|
|
data() {
|
|
return {
|
|
avatarFile: '',
|
|
avatarUrl: '',
|
|
name: '',
|
|
displayName: '',
|
|
email: '',
|
|
messageSignature: '',
|
|
hotKeys: [
|
|
{
|
|
key: 'enter',
|
|
title: this.$t(
|
|
'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.ENTER_KEY.HEADING'
|
|
),
|
|
description: this.$t(
|
|
'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.ENTER_KEY.CONTENT'
|
|
),
|
|
lightImage: '/assets/images/dashboard/profile/hot-key-enter.svg',
|
|
darkImage: '/assets/images/dashboard/profile/hot-key-enter-dark.svg',
|
|
},
|
|
{
|
|
key: 'cmd_enter',
|
|
title: this.$t(
|
|
'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.CMD_ENTER_KEY.HEADING'
|
|
),
|
|
description: this.$t(
|
|
'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.CMD_ENTER_KEY.CONTENT'
|
|
),
|
|
lightImage: '/assets/images/dashboard/profile/hot-key-ctrl-enter.svg',
|
|
darkImage:
|
|
'/assets/images/dashboard/profile/hot-key-ctrl-enter-dark.svg',
|
|
},
|
|
],
|
|
notificationPermissions: [...ROLES, ...CONVERSATION_PERMISSIONS],
|
|
audioNotificationPermissions: [...ROLES, ...CONVERSATION_PERMISSIONS],
|
|
};
|
|
},
|
|
computed: {
|
|
...mapGetters({
|
|
currentUser: 'getCurrentUser',
|
|
currentUserId: 'getCurrentUserID',
|
|
globalConfig: 'globalConfig/get',
|
|
}),
|
|
},
|
|
mounted() {
|
|
if (this.currentUserId) {
|
|
this.initializeUser();
|
|
}
|
|
},
|
|
methods: {
|
|
initializeUser() {
|
|
this.name = this.currentUser.name;
|
|
this.email = this.currentUser.email;
|
|
this.avatarUrl = this.currentUser.avatar_url;
|
|
this.displayName = this.currentUser.display_name;
|
|
this.messageSignature = this.currentUser.message_signature;
|
|
},
|
|
async dispatchUpdate(payload, successMessage, errorMessage) {
|
|
let alertMessage = '';
|
|
try {
|
|
await this.$store.dispatch('updateProfile', payload);
|
|
alertMessage = successMessage;
|
|
|
|
return true; // return the value so that the status can be known
|
|
} catch (error) {
|
|
alertMessage = parseAPIErrorResponse(error) || errorMessage;
|
|
|
|
return false; // return the value so that the status can be known
|
|
} finally {
|
|
useAlert(alertMessage);
|
|
}
|
|
},
|
|
async updateProfile(userAttributes) {
|
|
const { name, email, displayName } = userAttributes;
|
|
const hasEmailChanged = this.currentUser.email !== email;
|
|
this.name = name || this.name;
|
|
this.email = email || this.email;
|
|
this.displayName = displayName || this.displayName;
|
|
|
|
const updatePayload = {
|
|
name: this.name,
|
|
email: this.email,
|
|
displayName: this.displayName,
|
|
avatar: this.avatarFile,
|
|
};
|
|
|
|
const success = await this.dispatchUpdate(
|
|
updatePayload,
|
|
hasEmailChanged
|
|
? this.$t('PROFILE_SETTINGS.AFTER_EMAIL_CHANGED')
|
|
: this.$t('PROFILE_SETTINGS.UPDATE_SUCCESS'),
|
|
this.$t('RESET_PASSWORD.API.ERROR_MESSAGE')
|
|
);
|
|
|
|
if (hasEmailChanged && success) clearCookiesOnLogout();
|
|
},
|
|
async updateSignature(signature) {
|
|
const payload = { message_signature: signature };
|
|
let successMessage = this.$t(
|
|
'PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.API_SUCCESS'
|
|
);
|
|
let errorMessage = this.$t(
|
|
'PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.API_ERROR'
|
|
);
|
|
|
|
await this.dispatchUpdate(payload, successMessage, errorMessage);
|
|
},
|
|
updateProfilePicture({ file, url }) {
|
|
this.avatarFile = file;
|
|
this.avatarUrl = url;
|
|
},
|
|
async deleteProfilePicture() {
|
|
try {
|
|
await this.$store.dispatch('deleteAvatar');
|
|
this.avatarUrl = '';
|
|
this.avatarFile = '';
|
|
useAlert(this.$t('PROFILE_SETTINGS.AVATAR_DELETE_SUCCESS'));
|
|
} catch (error) {
|
|
useAlert(this.$t('PROFILE_SETTINGS.AVATAR_DELETE_FAILED'));
|
|
}
|
|
},
|
|
toggleHotKey(key) {
|
|
this.hotKeys = this.hotKeys.map(hotKey =>
|
|
hotKey.key === key ? { ...hotKey, active: !hotKey.active } : hotKey
|
|
);
|
|
this.updateUISettings({ editor_message_key: key });
|
|
useAlert(this.$t('PROFILE_SETTINGS.FORM.SEND_MESSAGE.UPDATE_SUCCESS'));
|
|
},
|
|
async onCopyToken(value) {
|
|
await copyTextToClipboard(value);
|
|
useAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL'));
|
|
},
|
|
async resetAccessToken() {
|
|
const success = await this.$store.dispatch('resetAccessToken');
|
|
if (success) {
|
|
useAlert(this.$t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.RESET_SUCCESS'));
|
|
} else {
|
|
useAlert(this.$t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.RESET_ERROR'));
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="grid py-16 px-5 font-inter mx-auto gap-16 sm:max-w-screen-md">
|
|
<div class="flex flex-col gap-6">
|
|
<h2 class="text-2xl font-medium text-ash-900">
|
|
{{ $t('PROFILE_SETTINGS.TITLE') }}
|
|
</h2>
|
|
<UserProfilePicture
|
|
:src="avatarUrl"
|
|
:name="name"
|
|
@change="updateProfilePicture"
|
|
@delete="deleteProfilePicture"
|
|
/>
|
|
<UserBasicDetails
|
|
:name="name"
|
|
:display-name="displayName"
|
|
:email="email"
|
|
:email-enabled="!globalConfig.disableUserProfileUpdate"
|
|
@update-user="updateProfile"
|
|
/>
|
|
</div>
|
|
<FormSection
|
|
:title="$t('PROFILE_SETTINGS.FORM.INTERFACE_SECTION.TITLE')"
|
|
:description="$t('PROFILE_SETTINGS.FORM.INTERFACE_SECTION.NOTE')"
|
|
>
|
|
<FontSize
|
|
:value="currentFontSize"
|
|
:label="$t('PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.TITLE')"
|
|
:description="
|
|
$t('PROFILE_SETTINGS.FORM.INTERFACE_SECTION.FONT_SIZE.NOTE')
|
|
"
|
|
@change="updateFontSize"
|
|
/>
|
|
</FormSection>
|
|
<FormSection
|
|
:title="$t('PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.TITLE')"
|
|
:description="$t('PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.NOTE')"
|
|
>
|
|
<MessageSignature
|
|
:message-signature="messageSignature"
|
|
@update-signature="updateSignature"
|
|
/>
|
|
</FormSection>
|
|
<FormSection
|
|
:title="$t('PROFILE_SETTINGS.FORM.SEND_MESSAGE.TITLE')"
|
|
:description="$t('PROFILE_SETTINGS.FORM.SEND_MESSAGE.NOTE')"
|
|
>
|
|
<div
|
|
class="flex flex-col justify-between w-full gap-5 sm:gap-4 sm:flex-row"
|
|
>
|
|
<button
|
|
v-for="hotKey in hotKeys"
|
|
:key="hotKey.key"
|
|
class="px-0 reset-base w-full sm:flex-1"
|
|
>
|
|
<HotKeyCard
|
|
:key="hotKey.title"
|
|
:title="hotKey.title"
|
|
:description="hotKey.description"
|
|
:light-image="hotKey.lightImage"
|
|
:dark-image="hotKey.darkImage"
|
|
:active="isEditorHotKeyEnabled(hotKey.key)"
|
|
@click="toggleHotKey(hotKey.key)"
|
|
/>
|
|
</button>
|
|
</div>
|
|
</FormSection>
|
|
<FormSection
|
|
v-if="!globalConfig.disableUserProfileUpdate"
|
|
:title="$t('PROFILE_SETTINGS.FORM.PASSWORD_SECTION.TITLE')"
|
|
>
|
|
<ChangePassword />
|
|
</FormSection>
|
|
<Policy :permissions="audioNotificationPermissions">
|
|
<FormSection
|
|
:title="$t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.TITLE')"
|
|
:description="
|
|
$t('PROFILE_SETTINGS.FORM.AUDIO_NOTIFICATIONS_SECTION.NOTE')
|
|
"
|
|
>
|
|
<AudioNotifications />
|
|
</FormSection>
|
|
</Policy>
|
|
<Policy :permissions="notificationPermissions">
|
|
<FormSection :title="$t('PROFILE_SETTINGS.FORM.NOTIFICATIONS.TITLE')">
|
|
<NotificationPreferences />
|
|
</FormSection>
|
|
</Policy>
|
|
<FormSection
|
|
:title="$t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.TITLE')"
|
|
:description="
|
|
useInstallationName(
|
|
$t('PROFILE_SETTINGS.FORM.ACCESS_TOKEN.NOTE'),
|
|
globalConfig.installationName
|
|
)
|
|
"
|
|
>
|
|
<AccessToken
|
|
:value="currentUser.access_token"
|
|
@on-copy="onCopyToken"
|
|
@on-reset="resetAccessToken"
|
|
/>
|
|
</FormSection>
|
|
</div>
|
|
</template>
|