mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-28 17:52:39 +00:00
feat: Update Inbox/Team creation UI (#12305)
This commit is contained in:
@@ -2,23 +2,23 @@ import { computed } from 'vue';
|
||||
|
||||
export function useChannelIcon(inbox) {
|
||||
const channelTypeIconMap = {
|
||||
'Channel::Api': 'i-ri-cloudy-fill',
|
||||
'Channel::Email': 'i-ri-mail-fill',
|
||||
'Channel::FacebookPage': 'i-ri-messenger-fill',
|
||||
'Channel::Line': 'i-ri-line-fill',
|
||||
'Channel::Sms': 'i-ri-chat-1-fill',
|
||||
'Channel::Telegram': 'i-ri-telegram-fill',
|
||||
'Channel::TwilioSms': 'i-ri-chat-1-fill',
|
||||
'Channel::Api': 'i-woot-api',
|
||||
'Channel::Email': 'i-woot-mail',
|
||||
'Channel::FacebookPage': 'i-woot-messenger',
|
||||
'Channel::Line': 'i-woot-line',
|
||||
'Channel::Sms': 'i-woot-sms',
|
||||
'Channel::Telegram': 'i-woot-telegram',
|
||||
'Channel::TwilioSms': 'i-woot-sms',
|
||||
'Channel::TwitterProfile': 'i-ri-twitter-x-fill',
|
||||
'Channel::WebWidget': 'i-ri-global-fill',
|
||||
'Channel::Whatsapp': 'i-ri-whatsapp-fill',
|
||||
'Channel::Instagram': 'i-ri-instagram-fill',
|
||||
'Channel::WebWidget': 'i-woot-website',
|
||||
'Channel::Whatsapp': 'i-woot-whatsapp',
|
||||
'Channel::Instagram': 'i-woot-instagram',
|
||||
'Channel::Voice': 'i-ri-phone-fill',
|
||||
};
|
||||
|
||||
const providerIconMap = {
|
||||
microsoft: 'i-ri-microsoft-fill',
|
||||
google: 'i-ri-google-fill',
|
||||
microsoft: 'i-woot-outlook',
|
||||
google: 'i-woot-gmail',
|
||||
};
|
||||
|
||||
const channelIcon = computed(() => {
|
||||
@@ -34,7 +34,7 @@ export function useChannelIcon(inbox) {
|
||||
|
||||
// Special case for Twilio whatsapp
|
||||
if (type === 'Channel::TwilioSms' && inboxDetails.medium === 'whatsapp') {
|
||||
icon = 'i-ri-whatsapp-fill';
|
||||
icon = 'i-woot-whatsapp';
|
||||
}
|
||||
|
||||
return icon ?? 'i-ri-global-fill';
|
||||
|
||||
@@ -4,19 +4,19 @@ describe('useChannelIcon', () => {
|
||||
it('returns correct icon for API channel', () => {
|
||||
const inbox = { channel_type: 'Channel::Api' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-cloudy-fill');
|
||||
expect(icon).toBe('i-woot-api');
|
||||
});
|
||||
|
||||
it('returns correct icon for Facebook channel', () => {
|
||||
const inbox = { channel_type: 'Channel::FacebookPage' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-messenger-fill');
|
||||
expect(icon).toBe('i-woot-messenger');
|
||||
});
|
||||
|
||||
it('returns correct icon for WhatsApp channel', () => {
|
||||
const inbox = { channel_type: 'Channel::Whatsapp' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-whatsapp-fill');
|
||||
expect(icon).toBe('i-woot-whatsapp');
|
||||
});
|
||||
|
||||
it('returns correct icon for Voice channel', () => {
|
||||
@@ -28,19 +28,19 @@ describe('useChannelIcon', () => {
|
||||
it('returns correct icon for Line channel', () => {
|
||||
const inbox = { channel_type: 'Channel::Line' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-line-fill');
|
||||
expect(icon).toBe('i-woot-line');
|
||||
});
|
||||
|
||||
it('returns correct icon for SMS channel', () => {
|
||||
const inbox = { channel_type: 'Channel::Sms' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-chat-1-fill');
|
||||
expect(icon).toBe('i-woot-sms');
|
||||
});
|
||||
|
||||
it('returns correct icon for Telegram channel', () => {
|
||||
const inbox = { channel_type: 'Channel::Telegram' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-telegram-fill');
|
||||
expect(icon).toBe('i-woot-telegram');
|
||||
});
|
||||
|
||||
it('returns correct icon for Twitter channel', () => {
|
||||
@@ -52,20 +52,20 @@ describe('useChannelIcon', () => {
|
||||
it('returns correct icon for WebWidget channel', () => {
|
||||
const inbox = { channel_type: 'Channel::WebWidget' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-global-fill');
|
||||
expect(icon).toBe('i-woot-website');
|
||||
});
|
||||
|
||||
it('returns correct icon for Instagram channel', () => {
|
||||
const inbox = { channel_type: 'Channel::Instagram' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-instagram-fill');
|
||||
expect(icon).toBe('i-woot-instagram');
|
||||
});
|
||||
|
||||
describe('TwilioSms channel', () => {
|
||||
it('returns chat icon for regular Twilio SMS channel', () => {
|
||||
const inbox = { channel_type: 'Channel::TwilioSms' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-chat-1-fill');
|
||||
expect(icon).toBe('i-woot-sms');
|
||||
});
|
||||
|
||||
it('returns WhatsApp icon for Twilio SMS with WhatsApp medium', () => {
|
||||
@@ -74,7 +74,7 @@ describe('useChannelIcon', () => {
|
||||
medium: 'whatsapp',
|
||||
};
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-whatsapp-fill');
|
||||
expect(icon).toBe('i-woot-whatsapp');
|
||||
});
|
||||
|
||||
it('returns chat icon for Twilio SMS with non-WhatsApp medium', () => {
|
||||
@@ -83,7 +83,7 @@ describe('useChannelIcon', () => {
|
||||
medium: 'sms',
|
||||
};
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-chat-1-fill');
|
||||
expect(icon).toBe('i-woot-sms');
|
||||
});
|
||||
|
||||
it('returns chat icon for Twilio SMS with undefined medium', () => {
|
||||
@@ -92,7 +92,7 @@ describe('useChannelIcon', () => {
|
||||
medium: undefined,
|
||||
};
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-chat-1-fill');
|
||||
expect(icon).toBe('i-woot-sms');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,7 +100,7 @@ describe('useChannelIcon', () => {
|
||||
it('returns mail icon for generic email channel', () => {
|
||||
const inbox = { channel_type: 'Channel::Email' };
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-mail-fill');
|
||||
expect(icon).toBe('i-woot-mail');
|
||||
});
|
||||
|
||||
it('returns Microsoft icon for Microsoft email provider', () => {
|
||||
@@ -109,7 +109,7 @@ describe('useChannelIcon', () => {
|
||||
provider: 'microsoft',
|
||||
};
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-microsoft-fill');
|
||||
expect(icon).toBe('i-woot-outlook');
|
||||
});
|
||||
|
||||
it('returns Google icon for Google email provider', () => {
|
||||
@@ -118,7 +118,7 @@ describe('useChannelIcon', () => {
|
||||
provider: 'google',
|
||||
};
|
||||
const { value: icon } = useChannelIcon(inbox);
|
||||
expect(icon).toBe('i-ri-google-fill');
|
||||
expect(icon).toBe('i-woot-gmail');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ const reauthorizationRequired = computed(() => {
|
||||
|
||||
<template>
|
||||
<span
|
||||
class="size-4 grid place-content-center rounded-full bg-n-alpha-2"
|
||||
class="size-5 grid place-content-center rounded-full bg-n-alpha-2"
|
||||
:class="{ 'bg-n-solid-blue': active }"
|
||||
>
|
||||
<ChannelIcon :inbox="inbox" class="size-3" />
|
||||
|
||||
@@ -1,50 +1,57 @@
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isComingSoon: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
<script setup>
|
||||
import Icon from 'next/icon/Icon.vue';
|
||||
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
};
|
||||
description: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isComingSoon: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
class="relative bg-n-background cursor-pointer flex flex-col justify-end transition-all duration-200 ease-in -m-px py-4 px-0 items-center border border-solid border-n-weak hover:border-n-brand hover:shadow-md hover:z-50 disabled:opacity-60"
|
||||
class="relative bg-n-solid-1 gap-6 cursor-pointer rounded-2xl flex flex-col justify-start transition-all duration-200 ease-in -m-px py-6 px-5 items-start border border-solid border-n-weak"
|
||||
:class="{
|
||||
'hover:enabled:border-n-blue-9 hover:enabled:shadow-md disabled:opacity-60 disabled:cursor-not-allowed':
|
||||
!isComingSoon,
|
||||
'cursor-not-allowed disabled:opacity-80': isComingSoon,
|
||||
}"
|
||||
>
|
||||
<img :src="src" :alt="title" draggable="false" class="w-1/2 my-4 mx-auto" />
|
||||
<h3 class="text-n-slate-12 text-base text-center capitalize">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<div
|
||||
class="flex size-10 items-center justify-center rounded-full bg-n-alpha-2"
|
||||
>
|
||||
<Icon :icon="icon" class="text-n-slate-10 size-6" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-start gap-1.5">
|
||||
<h3 class="text-n-slate-12 text-sm text-start font-medium capitalize">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<p class="text-n-slate-11 text-start text-sm">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="isComingSoon"
|
||||
class="absolute inset-0 flex items-center justify-center backdrop-blur-[2px] rounded-md bg-gradient-to-br from-n-background/90 via-n-background/70 to-n-background/95"
|
||||
class="absolute inset-0 flex items-center justify-center backdrop-blur-[2px] rounded-2xl bg-gradient-to-br from-n-background/90 via-n-background/70 to-n-background/95 cursor-not-allowed"
|
||||
>
|
||||
<span class="text-n-slate-12 font-medium text-base">
|
||||
<span class="text-n-slate-12 font-medium text-sm">
|
||||
{{ $t('CHANNEL_SELECTOR.COMING_SOON') }} 🚀
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.inactive {
|
||||
img {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@apply border-n-strong shadow-none cursor-not-allowed;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,97 +1,75 @@
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
classObject() {
|
||||
return 'w-full';
|
||||
},
|
||||
activeIndex() {
|
||||
return this.items.findIndex(i => i.route === this.$route.name);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
isActive(item) {
|
||||
return this.items.indexOf(item) === this.activeIndex;
|
||||
},
|
||||
isOver(item) {
|
||||
return this.items.indexOf(item) < this.activeIndex;
|
||||
},
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
const props = defineProps({
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const activeIndex = computed(() => {
|
||||
return props.items.findIndex(i => i.route === route.name);
|
||||
});
|
||||
|
||||
const isActive = item => {
|
||||
return props.items.indexOf(item) === activeIndex.value;
|
||||
};
|
||||
|
||||
const isOver = item => {
|
||||
return props.items.indexOf(item) < activeIndex.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<transition-group
|
||||
name="wizard-items"
|
||||
tag="div"
|
||||
class="wizard-box"
|
||||
:class="classObject"
|
||||
>
|
||||
<transition-group tag="div">
|
||||
<div
|
||||
v-for="item in items"
|
||||
v-for="(item, index) in items"
|
||||
:key="item.route"
|
||||
class="item"
|
||||
:class="{ active: isActive(item), over: isOver(item) }"
|
||||
class="cursor-pointer flex items-start gap-6 relative after:content-[''] after:absolute after:w-0.5 after:h-full after:top-5 ltr:after:left-4 rtl:after:right-4 before:content-[''] before:absolute before:w-0.5 before:h-4 before:top-0 before:left-4 rtl:before:right-4 last:after:hidden last:before:hidden"
|
||||
:class="
|
||||
isOver(item)
|
||||
? 'after:bg-n-blue-9 before:bg-n-blue-9'
|
||||
: 'after:bg-n-weak before:bg-n-weak'
|
||||
"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<h3
|
||||
class="text-n-slate-12 text-base font-medium pl-6 overflow-hidden whitespace-nowrap mt-0.5 text-ellipsis leading-tight"
|
||||
<div
|
||||
class="rounded-2xl flex-shrink-0 size-8 flex items-center justify-center left-2 outline outline-2 leading-4 z-10 top-5 bg-n-background"
|
||||
:class="
|
||||
isActive(item) || isOver(item) ? 'outline-n-blue-9' : 'outline-n-weak'
|
||||
"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-bold"
|
||||
:class="
|
||||
isActive(item) || isOver(item)
|
||||
? 'text-n-blue-11'
|
||||
: 'text-n-slate-11'
|
||||
"
|
||||
>
|
||||
{{ item.title }}
|
||||
</h3>
|
||||
<span v-if="isOver(item)" class="mx-1 mt-0.5 text-n-teal-9">
|
||||
<fluent-icon icon="checkmark" />
|
||||
{{ index + 1 }}
|
||||
</span>
|
||||
</div>
|
||||
<span class="step">
|
||||
{{ items.indexOf(item) + 1 }}
|
||||
</span>
|
||||
<p class="pl-6 m-0 mt-1.5 text-sm text-n-slate-11">
|
||||
{{ item.body }}
|
||||
</p>
|
||||
<div class="flex flex-col items-start gap-1.5 pb-10 pt-1">
|
||||
<div class="flex items-center">
|
||||
<h3
|
||||
class="text-sm font-medium overflow-hidden whitespace-nowrap mt-0.5 text-ellipsis leading-tight"
|
||||
:class="
|
||||
isActive(item) || isOver(item)
|
||||
? 'text-n-blue-11'
|
||||
: 'text-n-slate-12'
|
||||
"
|
||||
>
|
||||
{{ item.title }}
|
||||
</h3>
|
||||
</div>
|
||||
<p class="m-0 mt-1.5 text-sm text-n-slate-11">
|
||||
{{ item.body }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wizard-box {
|
||||
.item {
|
||||
@apply cursor-pointer after:bg-n-slate-6 before:bg-n-slate-6 py-4 ltr:pr-4 rtl:pl-4 ltr:pl-6 rtl:pr-6 relative before:h-4 before:top-0 last:before:h-0 first:before:h-0 last:after:h-0 before:content-[''] before:absolute before:w-0.5 after:content-[''] after:h-full after:absolute after:top-5 after:w-0.5 rtl:after:left-6 rtl:before:left-6;
|
||||
|
||||
&.active {
|
||||
h3 {
|
||||
@apply text-n-blue-text dark:text-n-blue-text;
|
||||
}
|
||||
|
||||
.step {
|
||||
@apply bg-n-brand dark:bg-n-brand;
|
||||
}
|
||||
}
|
||||
|
||||
&.over {
|
||||
&::after {
|
||||
@apply bg-n-brand dark:bg-n-brand;
|
||||
}
|
||||
|
||||
.step {
|
||||
@apply bg-n-brand dark:bg-n-brand;
|
||||
}
|
||||
|
||||
& + .item {
|
||||
&::before {
|
||||
@apply bg-n-brand dark:bg-n-brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.step {
|
||||
@apply bg-n-slate-7 rounded-2xl font-medium w-4 left-4 leading-4 z-10 absolute text-center text-white dark:text-white text-xxs top-5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,91 +1,87 @@
|
||||
<script>
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import ChannelSelector from '../ChannelSelector.vue';
|
||||
export default {
|
||||
components: { ChannelSelector },
|
||||
props: {
|
||||
channel: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
enabledFeatures: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ['channelItemClick'],
|
||||
computed: {
|
||||
hasFbConfigured() {
|
||||
return window.chatwootConfig?.fbAppId;
|
||||
},
|
||||
hasInstagramConfigured() {
|
||||
return window.chatwootConfig?.instagramAppId;
|
||||
},
|
||||
isActive() {
|
||||
const { key } = this.channel;
|
||||
if (Object.keys(this.enabledFeatures).length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (key === 'website') {
|
||||
return this.enabledFeatures.channel_website;
|
||||
}
|
||||
if (key === 'facebook') {
|
||||
return this.enabledFeatures.channel_facebook && this.hasFbConfigured;
|
||||
}
|
||||
if (key === 'email') {
|
||||
return this.enabledFeatures.channel_email;
|
||||
}
|
||||
|
||||
if (key === 'instagram') {
|
||||
return (
|
||||
this.enabledFeatures.channel_instagram && this.hasInstagramConfigured
|
||||
);
|
||||
}
|
||||
|
||||
if (key === 'voice') {
|
||||
return this.enabledFeatures.channel_voice;
|
||||
}
|
||||
|
||||
return [
|
||||
'website',
|
||||
'twilio',
|
||||
'api',
|
||||
'whatsapp',
|
||||
'sms',
|
||||
'telegram',
|
||||
'line',
|
||||
'instagram',
|
||||
'voice',
|
||||
].includes(key);
|
||||
},
|
||||
isComingSoon() {
|
||||
const { key } = this.channel;
|
||||
// Show "Coming Soon" only if the channel is marked as coming soon
|
||||
// and the corresponding feature flag is not enabled yet.
|
||||
return ['voice'].includes(key) && !this.isActive;
|
||||
},
|
||||
const props = defineProps({
|
||||
channel: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
methods: {
|
||||
getChannelThumbnail() {
|
||||
if (this.channel.key === 'api' && this.channel.thumbnail) {
|
||||
return this.channel.thumbnail;
|
||||
}
|
||||
return `/assets/images/dashboard/channels/${this.channel.key}.png`;
|
||||
},
|
||||
onItemClick() {
|
||||
if (this.isActive) {
|
||||
this.$emit('channelItemClick', this.channel.key);
|
||||
}
|
||||
},
|
||||
enabledFeatures: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['channelItemClick']);
|
||||
|
||||
const hasFbConfigured = computed(() => {
|
||||
return window.chatwootConfig?.fbAppId;
|
||||
});
|
||||
|
||||
const hasInstagramConfigured = computed(() => {
|
||||
return window.chatwootConfig?.instagramAppId;
|
||||
});
|
||||
|
||||
const isActive = computed(() => {
|
||||
const { key } = props.channel;
|
||||
if (Object.keys(props.enabledFeatures).length === 0) {
|
||||
return false;
|
||||
}
|
||||
if (key === 'website') {
|
||||
return props.enabledFeatures.channel_website;
|
||||
}
|
||||
if (key === 'facebook') {
|
||||
return props.enabledFeatures.channel_facebook && hasFbConfigured.value;
|
||||
}
|
||||
if (key === 'email') {
|
||||
return props.enabledFeatures.channel_email;
|
||||
}
|
||||
|
||||
if (key === 'instagram') {
|
||||
return (
|
||||
props.enabledFeatures.channel_instagram && hasInstagramConfigured.value
|
||||
);
|
||||
}
|
||||
|
||||
if (key === 'voice') {
|
||||
return props.enabledFeatures.channel_voice;
|
||||
}
|
||||
|
||||
return [
|
||||
'website',
|
||||
'twilio',
|
||||
'api',
|
||||
'whatsapp',
|
||||
'sms',
|
||||
'telegram',
|
||||
'line',
|
||||
'instagram',
|
||||
'voice',
|
||||
].includes(key);
|
||||
});
|
||||
|
||||
const isComingSoon = computed(() => {
|
||||
const { key } = props.channel;
|
||||
// Show "Coming Soon" only if the channel is marked as coming soon
|
||||
// and the corresponding feature flag is not enabled yet.
|
||||
return ['voice'].includes(key) && !isActive.value;
|
||||
});
|
||||
|
||||
const onItemClick = () => {
|
||||
if (isActive.value) {
|
||||
emit('channelItemClick', props.channel.key);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ChannelSelector
|
||||
:class="{ inactive: !isActive }"
|
||||
:title="channel.name"
|
||||
:src="getChannelThumbnail()"
|
||||
:title="channel.title"
|
||||
:description="channel.description"
|
||||
:icon="channel.icon"
|
||||
:is-coming-soon="isComingSoon"
|
||||
:disabled="!isActive"
|
||||
@click="onItemClick"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -13,7 +13,7 @@ defineProps({
|
||||
<div class="flex items-center text-n-slate-11 text-xs min-w-0">
|
||||
<ChannelIcon
|
||||
:inbox="inbox"
|
||||
class="size-3 ltr:mr-0.5 rtl:ml-0.5 flex-shrink-0"
|
||||
class="size-3 ltr:mr-1 rtl:ml-1 flex-shrink-0"
|
||||
/>
|
||||
<span class="truncate">
|
||||
{{ inbox.name }}
|
||||
|
||||
@@ -250,7 +250,6 @@ const deleteConversation = () => {
|
||||
:src="currentContact.thumbnail"
|
||||
:size="32"
|
||||
:status="currentContact.availability_status"
|
||||
:inbox="inbox"
|
||||
:class="!showInboxName ? 'mt-4' : 'mt-8'"
|
||||
hide-offline-status
|
||||
rounded-full
|
||||
|
||||
@@ -424,7 +424,51 @@
|
||||
},
|
||||
"AUTH": {
|
||||
"TITLE": "Choose a channel",
|
||||
"DESC": "Chatwoot supports live-chat widgets, Facebook Messenger, WhatsApp, Emails, etc., as channels. If you want to build a custom channel, you can create it using the API channel. To get started, choose one of the channels below."
|
||||
"DESC": "Chatwoot supports live-chat widgets, Facebook Messenger, WhatsApp, Emails, etc., as channels. If you want to build a custom channel, you can create it using the API channel. To get started, choose one of the channels below.",
|
||||
"TITLE_NEXT": "Complete the setup",
|
||||
"TITLE_FINISH": "Voilà!",
|
||||
"CHANNEL": {
|
||||
"WEBSITE": {
|
||||
"TITLE": "Website",
|
||||
"DESCRIPTION": "Create a live-chat widget"
|
||||
},
|
||||
"FACEBOOK": {
|
||||
"TITLE": "Facebook",
|
||||
"DESCRIPTION": "Connect your Facebook page"
|
||||
},
|
||||
"WHATSAPP": {
|
||||
"TITLE": "WhatsApp",
|
||||
"DESCRIPTION": "Support your customers on WhatsApp"
|
||||
},
|
||||
"EMAIL": {
|
||||
"TITLE": "Email",
|
||||
"DESCRIPTION": "Connect with Gmail, Outlook, or other providers"
|
||||
},
|
||||
"SMS": {
|
||||
"TITLE": "SMS",
|
||||
"DESCRIPTION": "Integrate SMS channel with Twilio or bandwidth"
|
||||
},
|
||||
"API": {
|
||||
"TITLE": "API",
|
||||
"DESCRIPTION": "Make a custom channel using our API"
|
||||
},
|
||||
"TELEGRAM": {
|
||||
"TITLE": "Telegram",
|
||||
"DESCRIPTION": "Configure Telegram channel using Bot token"
|
||||
},
|
||||
"LINE": {
|
||||
"TITLE": "Line",
|
||||
"DESCRIPTION": "Integrate your Line channel"
|
||||
},
|
||||
"INSTAGRAM": {
|
||||
"TITLE": "Instagram",
|
||||
"DESCRIPTION": "Connect your instagram account"
|
||||
},
|
||||
"VOICE": {
|
||||
"TITLE": "Voice",
|
||||
"DESCRIPTION": "Integrate with Twilio Voice"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AGENTS": {
|
||||
"TITLE": "Agents",
|
||||
@@ -871,9 +915,18 @@
|
||||
"SCRIPT_SETTINGS": "\n window.chatwootSettings = {options};"
|
||||
},
|
||||
"EMAIL_PROVIDERS": {
|
||||
"MICROSOFT": "Microsoft",
|
||||
"GOOGLE": "Google",
|
||||
"OTHER_PROVIDERS": "Other Providers"
|
||||
"MICROSOFT": {
|
||||
"TITLE": "Microsoft",
|
||||
"DESCRIPTION": "Connect with Microsoft"
|
||||
},
|
||||
"GOOGLE": {
|
||||
"TITLE": "Google",
|
||||
"DESCRIPTION": "Connect with Google"
|
||||
},
|
||||
"OTHER_PROVIDERS": {
|
||||
"TITLE": "Other Providers",
|
||||
"DESCRIPTION": "Connect with Other Providers"
|
||||
}
|
||||
},
|
||||
"CHANNELS": {
|
||||
"MESSENGER": "Messenger",
|
||||
|
||||
@@ -63,9 +63,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<form class="flex flex-wrap flex-col mx-0" @submit.prevent="addAgents()">
|
||||
<div class="w-full">
|
||||
<PageHeader
|
||||
|
||||
@@ -1,83 +1,108 @@
|
||||
<script>
|
||||
import ChannelItem from 'dashboard/components/widgets/ChannelItem.vue';
|
||||
import router from '../../../index';
|
||||
import PageHeader from '../SettingsSubPageHeader.vue';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { useBranding } from 'shared/composables/useBranding';
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useMapGetter } from 'dashboard/composables/store';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ChannelItem,
|
||||
PageHeader,
|
||||
},
|
||||
setup() {
|
||||
const { replaceInstallationName } = useBranding();
|
||||
return {
|
||||
replaceInstallationName,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
enabledFeatures: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
account() {
|
||||
return this.$store.getters['accounts/getAccount'](this.accountId);
|
||||
import { useAccount } from 'dashboard/composables/useAccount';
|
||||
|
||||
import ChannelItem from 'dashboard/components/widgets/ChannelItem.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const { accountId, currentAccount } = useAccount();
|
||||
|
||||
const globalConfig = useMapGetter('globalConfig/get');
|
||||
|
||||
const enabledFeatures = ref({});
|
||||
|
||||
const channelList = computed(() => {
|
||||
const { apiChannelName } = globalConfig.value;
|
||||
return [
|
||||
{
|
||||
key: 'website',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.WEBSITE.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.WEBSITE.DESCRIPTION'),
|
||||
icon: 'i-woot-website',
|
||||
},
|
||||
channelList() {
|
||||
const { apiChannelName, apiChannelThumbnail } = this.globalConfig;
|
||||
return [
|
||||
{ key: 'website', name: 'Website' },
|
||||
{ key: 'facebook', name: 'Messenger' },
|
||||
{ key: 'whatsapp', name: 'WhatsApp' },
|
||||
{ key: 'sms', name: 'SMS' },
|
||||
{ key: 'email', name: 'Email' },
|
||||
{
|
||||
key: 'api',
|
||||
name: apiChannelName || 'API',
|
||||
thumbnail: apiChannelThumbnail,
|
||||
},
|
||||
{ key: 'telegram', name: 'Telegram' },
|
||||
{ key: 'line', name: 'Line' },
|
||||
{ key: 'instagram', name: 'Instagram' },
|
||||
{ key: 'voice', name: 'Voice' },
|
||||
];
|
||||
{
|
||||
key: 'facebook',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.FACEBOOK.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.FACEBOOK.DESCRIPTION'),
|
||||
icon: 'i-woot-messenger',
|
||||
},
|
||||
...mapGetters({
|
||||
accountId: 'getCurrentAccountId',
|
||||
globalConfig: 'globalConfig/get',
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.initializeEnabledFeatures();
|
||||
},
|
||||
methods: {
|
||||
async initializeEnabledFeatures() {
|
||||
this.enabledFeatures = this.account.features;
|
||||
{
|
||||
key: 'whatsapp',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.WHATSAPP.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.WHATSAPP.DESCRIPTION'),
|
||||
icon: 'i-woot-whatsapp',
|
||||
},
|
||||
initChannelAuth(channel) {
|
||||
const params = {
|
||||
sub_page: channel,
|
||||
accountId: this.accountId,
|
||||
};
|
||||
router.push({ name: 'settings_inboxes_page_channel', params });
|
||||
{
|
||||
key: 'sms',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.SMS.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.SMS.DESCRIPTION'),
|
||||
icon: 'i-woot-sms',
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'email',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.EMAIL.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.EMAIL.DESCRIPTION'),
|
||||
icon: 'i-woot-mail',
|
||||
},
|
||||
{
|
||||
key: 'api',
|
||||
title: apiChannelName || t('INBOX_MGMT.ADD.AUTH.CHANNEL.API.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.API.DESCRIPTION'),
|
||||
icon: 'i-woot-api',
|
||||
},
|
||||
{
|
||||
key: 'telegram',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.TELEGRAM.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.TELEGRAM.DESCRIPTION'),
|
||||
icon: 'i-woot-telegram',
|
||||
},
|
||||
{
|
||||
key: 'line',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.LINE.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.LINE.DESCRIPTION'),
|
||||
icon: 'i-woot-line',
|
||||
},
|
||||
{
|
||||
key: 'instagram',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.INSTAGRAM.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.INSTAGRAM.DESCRIPTION'),
|
||||
icon: 'i-woot-instagram',
|
||||
},
|
||||
{
|
||||
key: 'voice',
|
||||
title: t('INBOX_MGMT.ADD.AUTH.CHANNEL.VOICE.TITLE'),
|
||||
description: t('INBOX_MGMT.ADD.AUTH.CHANNEL.VOICE.DESCRIPTION'),
|
||||
icon: 'i-ri-phone-fill',
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const initializeEnabledFeatures = async () => {
|
||||
enabledFeatures.value = currentAccount.value.features;
|
||||
};
|
||||
|
||||
const initChannelAuth = channel => {
|
||||
const params = {
|
||||
sub_page: channel,
|
||||
accountId: accountId.value,
|
||||
};
|
||||
router.push({ name: 'settings_inboxes_page_channel', params });
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initializeEnabledFeatures();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="w-full h-full col-span-6 p-6 overflow-auto border border-b-0 rounded-t-lg border-n-weak bg-n-solid-1"
|
||||
>
|
||||
<PageHeader
|
||||
class="max-w-4xl"
|
||||
:header-title="$t('INBOX_MGMT.ADD.AUTH.TITLE')"
|
||||
:header-content="replaceInstallationName($t('INBOX_MGMT.ADD.AUTH.DESC'))"
|
||||
/>
|
||||
<div class="w-full p-8 overflow-auto">
|
||||
<div
|
||||
class="grid max-w-3xl grid-cols-2 mx-0 mt-6 sm:grid-cols-3 lg:grid-cols-4"
|
||||
class="grid max-w-3xl grid-cols-1 xs:grid-cols-2 mx-0 gap-6 sm:grid-cols-3"
|
||||
>
|
||||
<ChannelItem
|
||||
v-for="channel in channelList"
|
||||
|
||||
@@ -168,9 +168,7 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="overflow-auto col-span-6 p-6 w-full h-full rounded-t-lg border border-b-0 border-n-weak bg-n-solid-1"
|
||||
>
|
||||
<div class="w-full h-full col-span-6 p-6 overflow-auto">
|
||||
<DuplicateInboxBanner
|
||||
v-if="hasDuplicateInstagramInbox"
|
||||
:content="$t('INBOX_MGMT.ADD.INSTAGRAM.NEW_INBOX_SUGGESTION')"
|
||||
|
||||
@@ -1,55 +1,106 @@
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useMapGetter } from 'dashboard/composables/store';
|
||||
import { useBranding } from 'shared/composables/useBranding';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const { replaceInstallationName } = useBranding();
|
||||
import PageHeader from '../SettingsSubPageHeader.vue';
|
||||
import Icon from 'next/icon/Icon.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const { replaceInstallationName } = useBranding();
|
||||
|
||||
const globalConfig = useMapGetter('globalConfig/get');
|
||||
|
||||
const ALL_CHANNEL_ICONS = [
|
||||
'i-woot-line',
|
||||
'i-woot-facebook',
|
||||
'i-woot-whatsapp',
|
||||
'i-woot-instagram',
|
||||
'i-woot-messenger',
|
||||
'i-woot-website',
|
||||
'i-woot-mail',
|
||||
'i-woot-sms',
|
||||
'i-woot-telegram',
|
||||
'i-woot-api',
|
||||
'i-woot-twilio',
|
||||
'i-woot-gmail',
|
||||
'i-woot-outlook',
|
||||
];
|
||||
|
||||
const createFlowSteps = computed(() => {
|
||||
const steps = ['CHANNEL', 'INBOX', 'AGENT', 'FINISH'];
|
||||
|
||||
const routes = {
|
||||
CHANNEL: 'settings_inbox_new',
|
||||
INBOX: 'settings_inboxes_page_channel',
|
||||
AGENT: 'settings_inboxes_add_agents',
|
||||
FINISH: 'settings_inbox_finish',
|
||||
};
|
||||
|
||||
return steps.map(step => {
|
||||
return {
|
||||
replaceInstallationName,
|
||||
title: t(`INBOX_MGMT.CREATE_FLOW.${step}.TITLE`),
|
||||
body: t(`INBOX_MGMT.CREATE_FLOW.${step}.BODY`),
|
||||
route: routes[step],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
globalConfig: 'globalConfig/get',
|
||||
}),
|
||||
createFlowSteps() {
|
||||
const steps = ['CHANNEL', 'INBOX', 'AGENT', 'FINISH'];
|
||||
});
|
||||
});
|
||||
|
||||
const routes = {
|
||||
CHANNEL: 'settings_inbox_new',
|
||||
INBOX: 'settings_inboxes_page_channel',
|
||||
AGENT: 'settings_inboxes_add_agents',
|
||||
FINISH: 'settings_inbox_finish',
|
||||
};
|
||||
const isFirstStep = computed(() => {
|
||||
return route.name === 'settings_inbox_new';
|
||||
});
|
||||
|
||||
return steps.map(step => {
|
||||
return {
|
||||
title: this.$t(`INBOX_MGMT.CREATE_FLOW.${step}.TITLE`),
|
||||
body: this.$t(`INBOX_MGMT.CREATE_FLOW.${step}.BODY`),
|
||||
route: routes[step],
|
||||
};
|
||||
});
|
||||
},
|
||||
items() {
|
||||
return this.createFlowSteps.map(item => ({
|
||||
...item,
|
||||
body: this.replaceInstallationName(item.body),
|
||||
}));
|
||||
},
|
||||
},
|
||||
};
|
||||
const isFinishStep = computed(() => {
|
||||
return route.name === 'settings_inbox_finish';
|
||||
});
|
||||
|
||||
const pageTitle = computed(() => {
|
||||
if (isFirstStep.value) {
|
||||
return t('INBOX_MGMT.ADD.AUTH.TITLE');
|
||||
}
|
||||
if (isFinishStep.value) {
|
||||
return t('INBOX_MGMT.ADD.AUTH.TITLE_FINISH');
|
||||
}
|
||||
return t('INBOX_MGMT.ADD.AUTH.TITLE_NEXT');
|
||||
});
|
||||
|
||||
const items = computed(() => {
|
||||
return createFlowSteps.value.map(item => ({
|
||||
...item,
|
||||
body: replaceInstallationName(item.body),
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-1 md:grid-cols-8 overflow-auto h-full">
|
||||
<woot-wizard
|
||||
class="hidden md:block col-span-2"
|
||||
:global-config="globalConfig"
|
||||
:items="items"
|
||||
/>
|
||||
<div class="col-span-6">
|
||||
<router-view />
|
||||
<div class="mx-2 flex flex-col gap-6 mb-8">
|
||||
<PageHeader class="block lg:hidden !mb-0" :header-title="pageTitle" />
|
||||
<div class="hidden lg:grid grid-cols-1 lg:grid-cols-8 items-center gap-2">
|
||||
<div class="col-span-2 w-full" />
|
||||
<div class="flex items-center gap-2 col-span-6 ltr:ml-8 rtl:mr-8">
|
||||
<div
|
||||
v-for="icon in ALL_CHANNEL_ICONS"
|
||||
:key="icon"
|
||||
class="size-8 bg-n-alpha-2 flex items-center flex-shrink-0 justify-center rounded-full"
|
||||
>
|
||||
<Icon :icon="icon" class="size-4 text-n-slate-10" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="grid grid-cols-1 lg:grid-cols-8 lg:divide-x lg:divide-n-weak rounded-xl border border-n-weak min-h-[52rem]"
|
||||
>
|
||||
<woot-wizard
|
||||
class="hidden lg:block col-span-2 h-fit py-8 px-6"
|
||||
:global-config="globalConfig"
|
||||
:items="items"
|
||||
/>
|
||||
<div class="col-span-6 overflow-hidden">
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -116,7 +116,7 @@ const openDelete = inbox => {
|
||||
v-else
|
||||
class="size-12 flex justify-center items-center bg-n-alpha-3 rounded-full p-2 ring ring-n-solid-1 border border-n-strong shadow-sm"
|
||||
>
|
||||
<ChannelIcon class="size-5" :inbox="inbox" />
|
||||
<ChannelIcon class="size-5 text-n-slate-10" :inbox="inbox" />
|
||||
</div>
|
||||
<div>
|
||||
<span class="block font-medium capitalize">
|
||||
|
||||
@@ -65,9 +65,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('INBOX_MGMT.ADD.API_CHANNEL.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.API_CHANNEL.DESC')"
|
||||
|
||||
@@ -20,22 +20,25 @@ const isAChatwootInstance = getters['globalConfig/isAChatwootInstance'];
|
||||
const emailProviderList = computed(() => {
|
||||
return [
|
||||
{
|
||||
title: t('INBOX_MGMT.EMAIL_PROVIDERS.MICROSOFT'),
|
||||
title: t('INBOX_MGMT.EMAIL_PROVIDERS.MICROSOFT.TITLE'),
|
||||
description: t('INBOX_MGMT.EMAIL_PROVIDERS.MICROSOFT.DESCRIPTION'),
|
||||
isEnabled: !!globalConfig.value.azureAppId,
|
||||
key: 'microsoft',
|
||||
src: '/assets/images/dashboard/channels/microsoft.png',
|
||||
icon: 'i-woot-outlook',
|
||||
},
|
||||
{
|
||||
title: t('INBOX_MGMT.EMAIL_PROVIDERS.GOOGLE'),
|
||||
title: t('INBOX_MGMT.EMAIL_PROVIDERS.GOOGLE.TITLE'),
|
||||
description: t('INBOX_MGMT.EMAIL_PROVIDERS.GOOGLE.DESCRIPTION'),
|
||||
isEnabled: !!window.chatwootConfig.googleOAuthClientId,
|
||||
key: 'google',
|
||||
src: '/assets/images/dashboard/channels/google.png',
|
||||
icon: 'i-woot-gmail',
|
||||
},
|
||||
{
|
||||
title: t('INBOX_MGMT.EMAIL_PROVIDERS.OTHER_PROVIDERS'),
|
||||
title: t('INBOX_MGMT.EMAIL_PROVIDERS.OTHER_PROVIDERS.TITLE'),
|
||||
description: t('INBOX_MGMT.EMAIL_PROVIDERS.OTHER_PROVIDERS.DESCRIPTION'),
|
||||
isEnabled: true,
|
||||
key: 'other_provider',
|
||||
src: '/assets/images/dashboard/channels/email.png',
|
||||
icon: 'i-woot-mail',
|
||||
},
|
||||
].filter(providerConfig => {
|
||||
if (isAChatwootInstance.value) {
|
||||
@@ -53,22 +56,20 @@ function onClick(emailProvider) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="!provider"
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div v-if="!provider" class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
class="max-w-4xl"
|
||||
:header-title="$t('INBOX_MGMT.ADD.EMAIL_PROVIDER.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.EMAIL_PROVIDER.DESCRIPTION')"
|
||||
/>
|
||||
<div class="grid max-w-3xl grid-cols-4 mx-0 mt-6">
|
||||
<div class="grid max-w-3xl grid-cols-4 gap-6 mx-0 mt-6">
|
||||
<ChannelSelector
|
||||
v-for="emailProvider in emailProviderList"
|
||||
:key="emailProvider.key"
|
||||
:class="{ inactive: !emailProvider.isEnabled }"
|
||||
:title="emailProvider.title"
|
||||
:src="emailProvider.src"
|
||||
:description="emailProvider.description"
|
||||
:icon="emailProvider.icon"
|
||||
:disabled="!emailProvider.isEnabled"
|
||||
@click="() => onClick(emailProvider)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -206,16 +206,14 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="w-full h-full col-span-6 p-6 overflow-auto border border-b-0 rounded-t-lg border-n-weak bg-n-solid-1"
|
||||
>
|
||||
<div class="w-full h-full col-span-6 p-6 overflow-auto">
|
||||
<div
|
||||
v-if="!hasLoginStarted"
|
||||
class="flex flex-col items-center justify-center h-full text-center"
|
||||
>
|
||||
<a href="#" @click="startLogin()">
|
||||
<img
|
||||
class="w-auto h-10"
|
||||
class="w-auto h-10 rounded-md"
|
||||
src="~dashboard/assets/images/channels/facebook_login.png"
|
||||
alt="Facebook-logo"
|
||||
/>
|
||||
|
||||
@@ -71,9 +71,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('INBOX_MGMT.ADD.LINE_CHANNEL.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.LINE_CHANNEL.DESC')"
|
||||
|
||||
@@ -18,9 +18,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('INBOX_MGMT.ADD.SMS.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.SMS.DESC')"
|
||||
|
||||
@@ -65,9 +65,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.TELEGRAM_CHANNEL.DESC')"
|
||||
|
||||
@@ -30,9 +30,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<div class="login-init h-full text-center">
|
||||
<form @submit.prevent="requestAuthorization">
|
||||
<NextButton
|
||||
|
||||
@@ -93,9 +93,7 @@ async function createChannel() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="overflow-auto col-span-6 p-6 w-full h-full rounded-t-lg border border-b-0 border-n-weak bg-n-solid-1"
|
||||
>
|
||||
<div class="overflow-auto col-span-6 p-6 w-full h-full">
|
||||
<PageHeader
|
||||
:header-title="t('INBOX_MGMT.ADD.VOICE.TITLE')"
|
||||
:header-content="t('INBOX_MGMT.ADD.VOICE.DESC')"
|
||||
|
||||
@@ -78,9 +78,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.DESC')"
|
||||
|
||||
@@ -7,6 +7,7 @@ import Twilio from './Twilio.vue';
|
||||
import ThreeSixtyDialogWhatsapp from './360DialogWhatsapp.vue';
|
||||
import CloudWhatsapp from './CloudWhatsapp.vue';
|
||||
import WhatsappEmbeddedSignup from './WhatsappEmbeddedSignup.vue';
|
||||
import ChannelSelector from 'dashboard/components/ChannelSelector.vue';
|
||||
import { FEATURE_FLAGS } from 'dashboard/featureFlags';
|
||||
|
||||
const route = useRoute();
|
||||
@@ -45,16 +46,16 @@ const showConfiguration = computed(() => Boolean(selectedProvider.value));
|
||||
|
||||
const availableProviders = computed(() => [
|
||||
{
|
||||
value: PROVIDER_TYPES.WHATSAPP,
|
||||
label: t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.WHATSAPP_CLOUD'),
|
||||
key: PROVIDER_TYPES.WHATSAPP,
|
||||
title: t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.WHATSAPP_CLOUD'),
|
||||
description: t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.WHATSAPP_CLOUD_DESC'),
|
||||
icon: '/assets/images/dashboard/channels/whatsapp.png',
|
||||
icon: 'i-woot-whatsapp',
|
||||
},
|
||||
{
|
||||
value: PROVIDER_TYPES.TWILIO,
|
||||
label: t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.TWILIO'),
|
||||
key: PROVIDER_TYPES.TWILIO,
|
||||
title: t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.TWILIO'),
|
||||
description: t('INBOX_MGMT.ADD.WHATSAPP.PROVIDERS.TWILIO_DESC'),
|
||||
icon: '/assets/images/dashboard/channels/twilio.png',
|
||||
icon: 'i-woot-twilio',
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -92,9 +93,7 @@ const shouldShowCloudWhatsapp = provider => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="overflow-auto col-span-6 p-6 w-full h-full rounded-t-lg border border-b-0 border-n-weak bg-n-solid-1"
|
||||
>
|
||||
<div class="overflow-auto col-span-6 p-6 w-full h-full">
|
||||
<div v-if="showProviderSelection">
|
||||
<div class="mb-10 text-left">
|
||||
<h1 class="mb-2 text-lg font-medium text-slate-12">
|
||||
@@ -106,51 +105,30 @@ const shouldShowCloudWhatsapp = provider => {
|
||||
</div>
|
||||
|
||||
<div class="flex gap-6 justify-start">
|
||||
<div
|
||||
<ChannelSelector
|
||||
v-for="provider in availableProviders"
|
||||
:key="provider.value"
|
||||
class="gap-6 px-5 py-6 w-96 rounded-2xl border transition-all duration-200 cursor-pointer border-n-weak hover:bg-n-slate-3"
|
||||
@click="selectProvider(provider.value)"
|
||||
>
|
||||
<div class="flex justify-start mb-5">
|
||||
<div
|
||||
class="flex justify-center items-center rounded-full size-10 bg-n-alpha-2"
|
||||
>
|
||||
<img
|
||||
:src="provider.icon"
|
||||
:alt="provider.label"
|
||||
class="object-contain size-[26px]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-start">
|
||||
<h3 class="mb-1.5 text-sm font-medium text-slate-12">
|
||||
{{ provider.label }}
|
||||
</h3>
|
||||
<p class="text-sm text-slate-11">
|
||||
{{ provider.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
:key="provider.key"
|
||||
:title="provider.title"
|
||||
:description="provider.description"
|
||||
:icon="provider.icon"
|
||||
@click="selectProvider(provider.key)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="showConfiguration">
|
||||
<div class="px-6 py-5 rounded-2xl border bg-n-solid-2 border-n-weak">
|
||||
<WhatsappEmbeddedSignup
|
||||
v-if="shouldShowEmbeddedSignup(selectedProvider)"
|
||||
/>
|
||||
<CloudWhatsapp v-else-if="shouldShowCloudWhatsapp(selectedProvider)" />
|
||||
<Twilio
|
||||
v-else-if="selectedProvider === PROVIDER_TYPES.TWILIO"
|
||||
type="whatsapp"
|
||||
/>
|
||||
<ThreeSixtyDialogWhatsapp
|
||||
v-else-if="selectedProvider === PROVIDER_TYPES.THREE_SIXTY_DIALOG"
|
||||
/>
|
||||
<CloudWhatsapp v-else />
|
||||
</div>
|
||||
<WhatsappEmbeddedSignup
|
||||
v-if="shouldShowEmbeddedSignup(selectedProvider)"
|
||||
/>
|
||||
<CloudWhatsapp v-else-if="shouldShowCloudWhatsapp(selectedProvider)" />
|
||||
<Twilio
|
||||
v-else-if="selectedProvider === PROVIDER_TYPES.TWILIO"
|
||||
type="whatsapp"
|
||||
/>
|
||||
<ThreeSixtyDialogWhatsapp
|
||||
v-else-if="selectedProvider === PROVIDER_TYPES.THREE_SIXTY_DIALOG"
|
||||
/>
|
||||
<CloudWhatsapp v-else />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -70,9 +70,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.TITLE')"
|
||||
:header-content="$t('INBOX_MGMT.ADD.EMAIL_CHANNEL.DESC')"
|
||||
|
||||
@@ -60,9 +60,7 @@ async function requestAuthorization() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<SettingsSubPageHeader
|
||||
:header-title="title"
|
||||
:header-content="description"
|
||||
|
||||
@@ -88,9 +88,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<form
|
||||
class="flex flex-wrap mx-0 overflow-x-auto"
|
||||
@submit.prevent="addAgents"
|
||||
|
||||
@@ -37,9 +37,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('TEAMS_SETTINGS.CREATE_FLOW.CREATE.TITLE')"
|
||||
:header-content="$t('TEAMS_SETTINGS.CREATE_FLOW.CREATE.DESC')"
|
||||
|
||||
@@ -23,8 +23,15 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-1 md:grid-cols-8 overflow-auto h-full px-5 flex-1">
|
||||
<woot-wizard class="hidden md:block col-span-2" :items="items" />
|
||||
<router-view />
|
||||
<div class="mx-2 flex flex-col gap-6 mb-8">
|
||||
<div
|
||||
class="grid grid-cols-1 lg:grid-cols-8 lg:divide-x lg:divide-n-weak rounded-xl border border-n-weak min-h-[43rem]"
|
||||
>
|
||||
<woot-wizard
|
||||
class="hidden lg:block col-span-2 h-fit py-8 px-6"
|
||||
:items="items"
|
||||
/>
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -103,9 +103,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-8 col-span-6">
|
||||
<form
|
||||
class="flex flex-wrap mx-0 overflow-x-auto"
|
||||
@submit.prevent="addAgents"
|
||||
|
||||
@@ -57,9 +57,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-8 col-span-6">
|
||||
<PageHeader
|
||||
:header-title="$t('TEAMS_SETTINGS.EDIT_FLOW.CREATE.TITLE')"
|
||||
:header-content="$t('TEAMS_SETTINGS.EDIT_FLOW.CREATE.DESC')"
|
||||
|
||||
@@ -27,8 +27,15 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-1 md:grid-cols-8 overflow-auto h-full px-5 flex-1">
|
||||
<woot-wizard class="hidden md:block col-span-2" :items="items" />
|
||||
<router-view />
|
||||
<div class="mx-2 flex flex-col gap-6 mb-8">
|
||||
<div
|
||||
class="grid grid-cols-1 lg:grid-cols-8 lg:divide-x lg:divide-n-weak rounded-xl border border-n-weak min-h-[43rem]"
|
||||
>
|
||||
<woot-wizard
|
||||
class="hidden lg:block col-span-2 h-fit py-8 px-6"
|
||||
:items="items"
|
||||
/>
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,9 +11,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="border border-n-weak bg-n-solid-1 rounded-t-lg border-b-0 h-full w-full p-6 col-span-6 overflow-auto"
|
||||
>
|
||||
<div class="h-full w-full p-6 col-span-6">
|
||||
<EmptyState
|
||||
:title="$t('TEAMS_SETTINGS.FINISH.TITLE')"
|
||||
:message="$t('TEAMS_SETTINGS.FINISH.MESSAGE')"
|
||||
|
||||
@@ -113,4 +113,71 @@ export const icons = {
|
||||
width: 16,
|
||||
height: 20,
|
||||
},
|
||||
/** Channels Starts */
|
||||
website: {
|
||||
body: `<path d="m3.023 1.664.126-.001.418-.001 1.286-.004h.34l1.596-.003q.92 0 1.84-.004l1.425-.003.85-.002a108 108 0 0 1 1.092-.003c.628-.004 1.163.04 1.706.388.554.593.645 1.218.64 2.004v.192l-.002.624v.435l-.004 1.14-.002 1.166-.006 2.283a4 4 0 0 1-.798-.15l-.182-.056-.193-.061-.2-.062-.634-.198-1.03-.32q-.088-.03-.18-.057l-.158-.05c-.39-.117-.764-.18-1.151-.013-.261.15-.403.338-.513.616-.059.432.047.817.18 1.224l.055.177q.086.278.175.554l.285.904.05.157.044.138c.031.127.031.127.031.361a1215 1215 0 0 1-4.146.014 337 337 0 0 1-1.753.005l-.68.001-.2.002c-.606-.002-1.133-.094-1.603-.493a1.78 1.78 0 0 1-.54-1.298l-.002-.703-.002-1.102-.002-1.481q0-.69-.003-1.378l-.002-1.185-.001-.707v-.666l-.002-.358c.004-.622.125-1.103.557-1.563.395-.347.776-.462 1.293-.463m-.648 1.121c-.48.604-.293.955-.293 1.875h11.309c.135-1.332.135-1.332-.235-1.816-.303-.28-.518-.3-.924-.302h-.12l-.687-.002-.943-.003h-.325q-.762-.003-1.525-.003-.88 0-1.76-.005L5.51 2.527l-.813-.003a99 99 0 0 0-1.044-.002c-.675-.009-.675-.009-1.279.263" fill="currentColor"/><path d="M10.52 9.406c.193.044.193.044.396.105l.112.034.621.189.534.163a164 164 0 0 0 1.211.369l.252.076.554.17c.507.179.507.179.597.359.034.365.034.365-.092.532-.176.14-.355.197-.567.258l-.251.079q-.196.06-.394.118c-.498.13-.498.13-.908.416a2 2 0 0 0-.132.413q-.057.177-.117.351-.09.28-.176.561l-.058.183-.052.164a.93.93 0 0 1-.3.382c-.205.03-.205.03-.41 0-.226-.176-.292-.356-.374-.625l-.037-.118-.116-.384-.081-.268-.17-.562q-.107-.36-.218-.717a136 136 0 0 1-.36-1.19q-.03-.105-.064-.212a2 2 0 0 1-.045-.611c.174-.272.34-.252.645-.235M6.184 3.162c.175.033.175.033.318.158.092.168.092.168.092.351-.068.194-.11.253-.293.344-.147.026-.147.026-.293 0-.136-.095-.136-.095-.235-.234-.035-.215-.028-.31.096-.49.139-.096.139-.096.315-.129m-1.172.033c.139.096.139.096.234.235.027.186.034.296-.066.458a.74.74 0 0 1-.461.128c-.172-.121-.172-.121-.293-.293 0-.191.026-.3.128-.462.161-.1.272-.092.458-.066m-1.231.059c.117.117.117.117.14.348-.006.168-.01.222-.114.359-.203.078-.345.046-.553-.004-.117-.117-.117-.117-.14-.348.006-.168.01-.222.114-.359.203-.078.345-.046.553.004" fill="currentColor"/>`,
|
||||
width: 16,
|
||||
height: 16,
|
||||
},
|
||||
line: {
|
||||
body: `<g clip-path="url(#a)"><path d="M2.778.778a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2zm4 2.25c2.344 0 4.25 1.528 4.25 3.407 0 .751-.295 1.429-.912 2.096-.892 1.014-2.885 2.249-3.339 2.437-.453.189-.386-.12-.367-.226l.06-.36c.014-.107.03-.273-.013-.38-.048-.116-.236-.177-.375-.206-2.042-.267-3.554-1.677-3.554-3.361 0-1.879 1.907-3.407 4.25-3.407M4.27 5.443a.22.22 0 0 0-.223.22v1.669c0 .122.1.22.223.22h.844a.22.22 0 0 0 .223-.22c0-.121-.1-.22-.223-.22h-.621V5.664c0-.122-.1-.22-.223-.22m1.495 0a.22.22 0 0 0-.223.22v1.669c0 .122.1.22.223.22a.22.22 0 0 0 .223-.22V5.664c0-.122-.1-.22-.223-.22m.766 0a.22.22 0 0 0-.224.22v1.669c0 .122.101.22.224.22a.22.22 0 0 0 .223-.22V6.3l.865 1.164a.225.225 0 0 0 .25.077.22.22 0 0 0 .151-.209V5.664c0-.122-.1-.22-.222-.22a.22.22 0 0 0-.223.22v1.032l-.866-1.164a.23.23 0 0 0-.178-.089m2.011 0a.22.22 0 0 0-.222.221v1.668c0 .122.1.22.222.22h.845a.22.22 0 0 0 .223-.22c0-.121-.1-.22-.223-.22h-.622v-.394h.622a.22.22 0 0 0 .223-.22c0-.122-.1-.22-.223-.22h-.622v-.394h.622a.22.22 0 0 0 .223-.22c0-.121-.1-.22-.223-.22z" fill="currentColor"/></g><defs><clipPath id="a"><path fill="currentColor" d="M.333.333h13.333v13.333H.333z"/></clipPath></defs>`,
|
||||
width: 13,
|
||||
height: 13,
|
||||
},
|
||||
facebook: {
|
||||
body: `<path d="M7 .333a6.667 6.667 0 0 1 1 13.258v-4.59h.666a1 1 0 0 0 0-2H8V5.665c0-.183.15-.333.333-.333h.333a1 1 0 0 0 0-2h-.333A2.333 2.333 0 0 0 6 5.668V7h-.667a1 1 0 1 0 0 2H6v4.592A6.668 6.668 0 0 1 7 .333" fill="currentColor"/>`,
|
||||
width: 14,
|
||||
height: 14,
|
||||
},
|
||||
whatsapp: {
|
||||
body: `<path d="M7 .333A6.667 6.667 0 1 1 3.554 12.71l-2.02.594a.673.673 0 0 1-.836-.836l.593-2.021A6.667 6.667 0 0 1 7 .334M5.524 3.84a.46.46 0 0 0-.456-.05 1.86 1.86 0 0 0-1.072 1.258l-.004.02c-.026.101-.047.22-.042.35.016.455.194 1.743 1.543 3.091 1.347 1.348 2.634 1.527 3.09 1.543.13.005.249-.017.35-.042l.023-.006a1.85 1.85 0 0 0 1.254-1.067.47.47 0 0 0-.06-.469c-.355-.455-.832-.784-1.256-1.077l-.085-.058a.474.474 0 0 0-.649.105l-.4.61a.153.153 0 0 1-.203.05 5 5 0 0 1-.951-.703 4.4 4.4 0 0 1-.671-.915.15.15 0 0 1 .045-.194l.615-.457a.474.474 0 0 0 .081-.626l-.09-.133c-.28-.413-.607-.898-1.062-1.23" fill="currentColor"/>`,
|
||||
width: 14,
|
||||
height: 14,
|
||||
},
|
||||
instagram: {
|
||||
body: `<path d="M8.667 0A3.333 3.333 0 0 1 12 3.333v5.334A3.333 3.333 0 0 1 8.667 12H3.333A3.333 3.333 0 0 1 0 8.667V3.333A3.333 3.333 0 0 1 3.333 0zM6 3.333a2.667 2.667 0 1 0 0 5.334 2.667 2.667 0 0 0 0-5.334m0 1.334a1.333 1.333 0 1 1 0 2.666 1.333 1.333 0 0 1 0-2.666m3-2.334a.667.667 0 1 0 0 1.334.667.667 0 0 0 0-1.334" fill="currentColor"/>`,
|
||||
width: 12,
|
||||
height: 12,
|
||||
},
|
||||
messenger: {
|
||||
body: `<path fill-rule="evenodd" clip-rule="evenodd" d="M.333 7a6.667 6.667 0 1 1 3.221 5.709l-2.033.597a.667.667 0 0 1-.827-.827l.598-2.033A6.64 6.64 0 0 1 .333 7M5.53 5.53c.26-.26.682-.26.942 0L8 7.057 9.529 5.53a.667.667 0 1 1 .942.943l-2 2a.667.667 0 0 1-.942 0L6 6.943 4.471 8.472a.667.667 0 1 1-.942-.943z" fill="currentColor"/>`,
|
||||
width: 14,
|
||||
height: 14,
|
||||
},
|
||||
mail: {
|
||||
body: `<g clip-path="url(#a)" fill="currentColor"><path d="M0 4.676q.058.03.116.063l.065.036c.105.06.204.128.304.196l.068.047.54.366.083.056q.421.284.847.562.598.393 1.19.793.673.454 1.352.9a57 57 0 0 1 1.1.738c.525.356 1.087.543 1.725.437.46-.096.845-.36 1.225-.621q.193-.134.387-.265l.081-.055q.418-.284.843-.56.597-.392 1.19-.793.669-.452 1.345-.896.38-.249.757-.501l.076-.05.358-.24.127-.086.059-.04c.132-.087.132-.087.162-.087l.007 2.49v.354l.006 1.92.001.545.002.703c.004.486-.045.832-.387 1.2-.262.242-.547.369-.907.369h-.409l-.403.001h-.434l-.85.001h-.692l-1.96.001H7.76l-1.715.001-2.75.002a262 262 0 0 1-1.664 0l-.142.001c-.422.003-.775-.061-1.098-.354l-.063-.07-.04-.04c-.17-.181-.292-.427-.291-.678V9.407l.001-1.933v-.06z"/><path d="M1.278 1.743h.263l.549-.001h.434l1.542-.002H6.24q.858 0 1.715-.002a1231 1231 0 0 1 3.592-.002h.964c.422-.003.775.061 1.098.354l.063.07.04.04c.26.272.3.613.296.97-.013.348-.198.612-.44.85a2 2 0 0 1-.303.221l-.07.046-.15.097-.407.265-.084.055q-.421.276-.837.56-.63.425-1.265.842-.565.371-1.124.75a123 123 0 0 1-1.22.817c-.46.305-.85.525-1.419.433a1.6 1.6 0 0 1-.46-.213l-.056-.036q-.33-.211-.651-.433A98 98 0 0 0 4.21 6.55q-.634-.417-1.262-.843-.531-.358-1.065-.71l-.654-.43-.062-.041-.47-.312C.451 4.047.235 3.873.108 3.6l-.046-.097a1.37 1.37 0 0 1-.005-.94c.16-.352.434-.613.79-.76a1.5 1.5 0 0 1 .43-.061"/></g><defs><clipPath id="a"><path fill="currentColor" d="M0 0h14v14H0z"/></clipPath></defs>`,
|
||||
width: 14,
|
||||
height: 14,
|
||||
},
|
||||
sms: {
|
||||
body: `<path fill-rule="evenodd" clip-rule="evenodd" d="M.333 2a2 2 0 0 1 2-2h9.334a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2h-1.448a.67.67 0 0 0-.472.195L8.414 11.53a2 2 0 0 1-2.828 0l-1.333-1.334A.67.67 0 0 0 3.78 10H2.333a2 2 0 0 1-2-2zm3.334.667a.667.667 0 1 0 0 1.333h6.666a.667.667 0 1 0 0-1.333zm0 2.666a.667.667 0 1 0 0 1.334H7a.667.667 0 1 0 0-1.334z" fill="currentColor"/>`,
|
||||
width: 14,
|
||||
height: 12,
|
||||
},
|
||||
telegram: {
|
||||
body: `<path fill-rule="evenodd" clip-rule="evenodd" d="M12.185.287A1 1 0 0 1 13.56 1.37l-1.513 9.171c-.146.884-1.117 1.392-1.928.951a39 39 0 0 1-2.594-1.53c-.453-.296-1.841-1.245-1.67-1.921C6 7.464 8.332 5.292 9.666 4c.524-.507.285-.8-.334-.333C7.8 4.826 5.336 6.587 4.521 7.083c-.719.438-1.094.512-1.542.438a10.2 10.2 0 0 1-2.194-.604c-.836-.346-.795-1.496 0-1.83z" fill="currentColor"/>`,
|
||||
width: 14,
|
||||
height: 12,
|
||||
},
|
||||
api: {
|
||||
body: `<path d="M4.468 11.5q-1.14 0-1.776-.636-.624-.636-.624-1.632v-.996q0-.504-.12-.792a.7.7 0 0 0-.348-.408q-.24-.132-.624-.132V5.488q.384 0 .624-.12a.7.7 0 0 0 .348-.408q.12-.3.12-.804V3.16q0-.996.624-1.62.636-.636 1.776-.636h.756v1.548q-.756-.036-1.104.204-.336.24-.336.792v.828q0 .852-.42 1.332-.408.48-.972.552v.072q.564.06.972.552.42.48.42 1.332v.84q0 .552.336.816.348.252 1.104.228v1.5zm6.855 0h-.756V10q.756.024 1.092-.228.348-.264.348-.816v-.84q0-.852.408-1.332.42-.492.984-.552V6.16q-.552-.072-.972-.552t-.42-1.332v-.828q0-.552-.348-.792-.336-.24-1.092-.204V.904h.756q1.152 0 1.776.636.624.624.624 1.62v.996q0 .504.108.804.12.288.36.408t.624.12v1.416q-.384 0-.624.132a.76.76 0 0 0-.36.408q-.108.288-.108.792v.996q0 .996-.624 1.632t-1.776.636" fill="currentColor"/>`,
|
||||
width: 15,
|
||||
height: 12,
|
||||
},
|
||||
twilio: {
|
||||
body: `<path d="M8 .5c4.14 0 7.5 3.36 7.5 7.5s-3.36 7.5-7.5 7.5S.5 12.14.5 8 3.86.5 8 .5m0 1.98C4.94 2.48 2.48 4.94 2.48 8S4.94 13.52 8 13.52s5.52-2.46 5.52-5.52S11.06 2.48 8 2.48M9.86 8.3a1.56 1.56 0 1 1 0 3.12 1.56 1.56 0 0 1 0-3.12m-3.72 0a1.56 1.56 0 1 1 0 3.12 1.56 1.56 0 0 1 0-3.12m3.72-3.72a1.56 1.56 0 1 1 0 3.12 1.56 1.56 0 0 1 0-3.12m-3.72 0a1.56 1.56 0 1 1 0 3.12 1.56 1.56 0 0 1 0-3.12" fill="currentColor"/>`,
|
||||
width: 16,
|
||||
height: 16,
|
||||
},
|
||||
gmail: {
|
||||
body: `<path d="M3.182 12.253H.955A.954.954 0 0 1 0 11.298V3.185c0-1.18 1.346-1.854 2.29-1.146L7 5.571l4.71-3.532c.942-.708 2.29-.035 2.29 1.146v8.113a.954.954 0 0 1-.955.955h-2.227v-5.41L7 9.708 3.182 6.844z" fill="currentColor"/>`,
|
||||
width: 14,
|
||||
height: 14,
|
||||
},
|
||||
outlook: {
|
||||
body: `<path d="M6.18.365a1 1 0 0 0-.267.028l-4.405.978A1.505 1.505 0 0 0 .333 2.836v8.328c0 .7.492 1.313 1.175 1.465l4.405.98v-.001c.718.16 1.42-.404 1.42-1.14V1.532C7.333.888 6.796.376 6.18.365m2.153 2.319v3.713l1.17.826 4.494-3.1c-.03-.8-.69-1.44-1.497-1.44zM3.833 4.5c1.028 0 1.834 1.172 1.834 2.667S4.86 9.834 3.833 9.834 2 8.662 2 7.167 2.805 4.5 3.833 4.5M14 5.337 9.783 8.244a.49.49 0 0 1-.573-.003l-.877-.621v4.064H12.5c.827 0 1.5-.674 1.5-1.5zM3.833 5.5C3.44 5.5 3 6.213 3 7.167s.44 1.667.833 1.667c.394 0 .834-.713.834-1.667S4.227 5.5 3.833 5.5" fill="currentColor"/>`,
|
||||
width: 14,
|
||||
height: 14,
|
||||
},
|
||||
/** Ends */
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user