feat: Add more files
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class="avatar-container" :style="style" aria-hidden="true">
|
||||
<slot>{{ userInitial }}</slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Avatar',
|
||||
props: {
|
||||
username: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 40,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
style() {
|
||||
return {
|
||||
fontSize: `${Math.floor(this.size / 2.5)}px`,
|
||||
};
|
||||
},
|
||||
userInitial() {
|
||||
const parts = this.username.split(/[ -]/);
|
||||
let initials = parts.reduce((acc, curr) => acc + curr.charAt(0), '');
|
||||
|
||||
if (initials.length > 2 && initials.search(/[A-Z]/) !== -1) {
|
||||
initials = initials.replace(/[a-z]+/g, '');
|
||||
}
|
||||
initials = initials.substring(0, 2).toUpperCase();
|
||||
|
||||
return initials;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@tailwind components;
|
||||
@layer components {
|
||||
.avatar-color {
|
||||
background-image: linear-gradient(to top, #c2e1ff 0%, #d6ebff 100%);
|
||||
}
|
||||
|
||||
.dark-avatar-color {
|
||||
background-image: linear-gradient(to top, #135899 0%, #135899 100%);
|
||||
}
|
||||
}
|
||||
.avatar-container {
|
||||
@apply flex leading-[100%] font-medium items-center justify-center text-center cursor-default avatar-color dark:dark-avatar-color text-woot-600 dark:text-woot-200;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-1 h-full justify-between flex-col m-0 bg-white dark:bg-slate-900 overflow-auto"
|
||||
>
|
||||
<div class="flex p-5 pt-16 mx-auto my-0">
|
||||
<div class="flex flex-col gap-8 min-w-[335px] sm:w-[720px]">
|
||||
<span class="font-medium dark:text-white text-slate-900 text-[24px]">
|
||||
Profile Settings
|
||||
</span>
|
||||
<div>
|
||||
<span
|
||||
class="text-slate-900 dark:text-slate-25 text-normal font-medium"
|
||||
>
|
||||
Profile picture
|
||||
</span>
|
||||
<!-- <thumbnail src="" username="John Doe" size="72px" /> -->
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="text-slate-900 dark:text-slate-25 text-lg font-medium">
|
||||
Personal message signature
|
||||
</span>
|
||||
<div class="w-full h-[1px] bg-slate-200 dark:bg-slate-700 my-2" />
|
||||
<p class="text-slate-600 dark:text-slate-400 text-sm font-normal">
|
||||
Create a unique message signature to appear at the end of every
|
||||
message you send from any inbox. You can also include an inline
|
||||
image, which is supported in live-chat, email, and API inboxes.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="text-slate-900 dark:text-slate-25 text-lg font-medium">
|
||||
Hot key to send messages
|
||||
</span>
|
||||
<div class="w-full h-[1px] bg-slate-200 dark:bg-slate-700 my-2" />
|
||||
<p class="text-slate-600 dark:text-slate-400 text-sm font-normal">
|
||||
You can select a hotkey (either Enter or Cmd/Ctrl+Enter) based on
|
||||
your preference of writing.
|
||||
</p>
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="flex-1 p-4 border">
|
||||
<div class="flex flex-row justify-between">
|
||||
<div class="text-sm">Enter (↵)</div>
|
||||
<input type="radio" name="hotkey" value="enter" />
|
||||
</div>
|
||||
<div class="text-xs pt-2">
|
||||
Send messages by pressing Enter key instead of clicking send
|
||||
button.
|
||||
</div>
|
||||
<img class="pt-4" src="/hot-key-enter.png" alt="Enter key" />
|
||||
</div>
|
||||
|
||||
<div class="flex-1 p-4 border">BOX 2</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
// import Thumbnail from './Thumbnail.vue';
|
||||
</script>
|
||||
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<div
|
||||
:class="thumbnailBoxClass"
|
||||
:style="{ height: size, width: size }"
|
||||
:title="title"
|
||||
>
|
||||
<!-- Using v-show instead of v-if to avoid flickering as v-if removes dom elements. -->
|
||||
<slot>
|
||||
<img
|
||||
v-show="shouldShowImage"
|
||||
:src="src"
|
||||
draggable="false"
|
||||
:class="thumbnailClass"
|
||||
@load="onImgLoad"
|
||||
@error="onImgError"
|
||||
/>
|
||||
<Avatar
|
||||
v-show="!shouldShowImage"
|
||||
:username="userNameWithoutEmoji"
|
||||
:class="thumbnailClass"
|
||||
:size="avatarSize"
|
||||
/>
|
||||
<!-- Show image on hover -->
|
||||
<img
|
||||
v-show="!shouldShowImage"
|
||||
src="/upload.png"
|
||||
draggable="false"
|
||||
:class="thumbnailClass"
|
||||
@load="onImgLoad"
|
||||
@error="onImgError"
|
||||
/>
|
||||
</slot>
|
||||
<img
|
||||
v-if="badgeSrc"
|
||||
class="source-badge"
|
||||
:style="badgeStyle"
|
||||
:src="uploadImage"
|
||||
alt="Badge"
|
||||
/>
|
||||
<div
|
||||
v-if="showStatusIndicator"
|
||||
:class="`source-badge user-online-status user-online-status--${status}`"
|
||||
:style="statusStyle"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
/**
|
||||
* Thumbnail Component
|
||||
* Src - source for round image
|
||||
* Size - Size of the thumbnail
|
||||
* Badge - Chat source indication { fb / telegram }
|
||||
* Username - Username for avatar
|
||||
*/
|
||||
|
||||
import Avatar from './Avatar.vue';
|
||||
import { removeEmoji } from 'shared/helpers/emoji';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Avatar,
|
||||
},
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: '40px',
|
||||
},
|
||||
badge: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hasBorder: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
shouldShowStatusAlways: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
variant: {
|
||||
type: String,
|
||||
default: 'circle',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hasImageLoaded: false,
|
||||
imgError: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
userNameWithoutEmoji() {
|
||||
return removeEmoji(this.username);
|
||||
},
|
||||
showStatusIndicator() {
|
||||
if (this.shouldShowStatusAlways) return true;
|
||||
return this.status === 'online' || this.status === 'busy';
|
||||
},
|
||||
avatarSize() {
|
||||
return Number(this.size.replace(/\D+/g, ''));
|
||||
},
|
||||
badgeSrc() {
|
||||
return {
|
||||
instagram_direct_message: 'instagram-dm',
|
||||
facebook: 'messenger',
|
||||
'twitter-tweet': 'twitter-tweet',
|
||||
'twitter-dm': 'twitter-dm',
|
||||
whatsapp: 'whatsapp',
|
||||
sms: 'sms',
|
||||
'Channel::Line': 'line',
|
||||
'Channel::Telegram': 'telegram',
|
||||
'Channel::WebWidget': '',
|
||||
}[this.badge];
|
||||
},
|
||||
badgeStyle() {
|
||||
const size = Math.floor(this.avatarSize / 3);
|
||||
const badgeSize = `${size + 2}px`;
|
||||
const borderRadius = `${size / 2}px`;
|
||||
return { width: badgeSize, height: badgeSize, borderRadius };
|
||||
},
|
||||
statusStyle() {
|
||||
const statusSize = `${this.avatarSize / 4}px`;
|
||||
return { width: statusSize, height: statusSize };
|
||||
},
|
||||
thumbnailClass() {
|
||||
const className = this.hasBorder
|
||||
? 'border border-solid border-white dark:border-slate-700/50'
|
||||
: '';
|
||||
const variant =
|
||||
this.variant === 'circle' ? 'thumbnail-rounded' : 'thumbnail-square';
|
||||
return `user-thumbnail ${className} ${variant}`;
|
||||
},
|
||||
thumbnailBoxClass() {
|
||||
const boxClass = this.variant === 'circle' ? 'is-rounded' : '';
|
||||
return `user-thumbnail-box ${boxClass}`;
|
||||
},
|
||||
shouldShowImage() {
|
||||
if (!this.src) {
|
||||
return false;
|
||||
}
|
||||
if (this.hasImageLoaded) {
|
||||
return !this.imgError;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
src(value, oldValue) {
|
||||
if (value !== oldValue && this.imgError) {
|
||||
this.imgError = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onImgError() {
|
||||
this.imgError = true;
|
||||
},
|
||||
onImgLoad() {
|
||||
this.hasImageLoaded = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user-thumbnail-box {
|
||||
flex: 0 0 auto;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
|
||||
.user-thumbnail {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
object-fit: cover;
|
||||
vertical-align: initial;
|
||||
}
|
||||
|
||||
.source-badge {
|
||||
border-radius: var(--border-radius-small);
|
||||
bottom: var(--space-minus-micro);
|
||||
box-shadow: var(--shadow-small);
|
||||
height: var(--space-slab);
|
||||
padding: var(--space-micro);
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: var(--space-slab);
|
||||
@apply bg-white dark:bg-slate-900;
|
||||
}
|
||||
|
||||
.user-online-status {
|
||||
border-radius: 50%;
|
||||
bottom: var(--space-micro);
|
||||
|
||||
&:after {
|
||||
content: ' ';
|
||||
}
|
||||
}
|
||||
|
||||
.user-online-status--online {
|
||||
@apply bg-green-400 dark:bg-green-400;
|
||||
}
|
||||
|
||||
.user-online-status--busy {
|
||||
@apply bg-yellow-500 dark:bg-yellow-500;
|
||||
}
|
||||
|
||||
.user-online-status--offline {
|
||||
@apply bg-slate-500 dark:bg-slate-500;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,20 @@
|
||||
import { frontendURL } from '../../../../helper/URLHelper';
|
||||
|
||||
const Index = () => import('./Index.vue');
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
{
|
||||
path: frontendURL('accounts/:accountId/personal'),
|
||||
name: 'personal_settings',
|
||||
roles: ['administrator', 'agent'],
|
||||
component: Index,
|
||||
props: {
|
||||
headerTitle: 'PROFILE_SETTINGS.TITLE',
|
||||
icon: 'edit',
|
||||
showNewButton: false,
|
||||
showSidemenuIcon: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 359 B |
@@ -18,6 +18,7 @@ import reports from './reports/reports.routes';
|
||||
import store from '../../../store';
|
||||
import sla from './sla/sla.routes';
|
||||
import teams from './teams/teams.routes';
|
||||
import personal from './personal/personal.routes';
|
||||
|
||||
export default {
|
||||
routes: [
|
||||
@@ -39,6 +40,7 @@ export default {
|
||||
...automation.routes,
|
||||
...auditlogs.routes,
|
||||
...billing.routes,
|
||||
...personal.routes,
|
||||
...campaigns.routes,
|
||||
...canned.routes,
|
||||
...inbox.routes,
|
||||
|
||||
Reference in New Issue
Block a user