Update header, add a sidebar to the design
This commit is contained in:
@@ -5,6 +5,7 @@ import { useRoute } from 'vue-router';
|
||||
import { useMapGetter } from 'dashboard/composables/store.js';
|
||||
|
||||
import PaginationFooter from 'dashboard/components-next/pagination/PaginationFooter.vue';
|
||||
import PortalAvatar from 'dashboard/components-next/HelpCenter/PortalAvatar.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import PortalSwitcher from 'dashboard/components-next/HelpCenter/PortalSwitcher/PortalSwitcher.vue';
|
||||
import CreatePortalDialog from 'dashboard/components-next/HelpCenter/PortalSwitcher/CreatePortalDialog.vue';
|
||||
@@ -30,6 +31,10 @@ defineProps({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
breadcrumbLabel: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:currentPage']);
|
||||
@@ -44,10 +49,15 @@ const portals = useMapGetter('portals/allPortals');
|
||||
|
||||
const currentPortalSlug = computed(() => route.params.portalSlug);
|
||||
|
||||
const activePortalName = computed(() => {
|
||||
return portals.value?.find(portal => portal.slug === currentPortalSlug.value)
|
||||
?.name;
|
||||
});
|
||||
const activePortal = computed(() =>
|
||||
portals.value?.find(portal => portal.slug === currentPortalSlug.value)
|
||||
);
|
||||
|
||||
const activePortalName = computed(() => activePortal.value?.name);
|
||||
|
||||
const activePortalLogo = computed(
|
||||
() => activePortal.value?.logo?.file_url || ''
|
||||
);
|
||||
|
||||
const updateCurrentPage = page => {
|
||||
emit('update:currentPage', page);
|
||||
@@ -65,32 +75,45 @@ const togglePortalSwitcher = () => {
|
||||
v-if="showHeaderTitle"
|
||||
class="flex items-center justify-start h-20 gap-2"
|
||||
>
|
||||
<span
|
||||
v-if="activePortalName"
|
||||
class="text-xl font-medium text-n-slate-12"
|
||||
>
|
||||
{{ activePortalName }}
|
||||
</span>
|
||||
<div v-if="activePortalName" class="relative group">
|
||||
<OnClickOutside @trigger="showPortalSwitcher = false">
|
||||
<Button
|
||||
icon="i-lucide-chevron-down"
|
||||
variant="ghost"
|
||||
color="slate"
|
||||
size="xs"
|
||||
class="rounded-md group-hover:bg-n-slate-3 hover:bg-n-slate-3"
|
||||
@click="togglePortalSwitcher"
|
||||
<nav v-if="activePortalName" class="flex items-center gap-2">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<PortalAvatar
|
||||
:src="activePortalLogo"
|
||||
:name="activePortalName"
|
||||
:size="24"
|
||||
/>
|
||||
<span class="text-lg font-medium text-n-slate-12">
|
||||
{{ activePortalName }}
|
||||
</span>
|
||||
<div class="relative group">
|
||||
<OnClickOutside @trigger="showPortalSwitcher = false">
|
||||
<Button
|
||||
icon="i-lucide-chevron-down"
|
||||
:variant="showPortalSwitcher ? 'faded' : 'ghost'"
|
||||
color="slate"
|
||||
size="xs"
|
||||
class="rounded-md group-hover:bg-n-slate-3 hover:bg-n-slate-3 [&>span]:size-4"
|
||||
@click="togglePortalSwitcher"
|
||||
/>
|
||||
|
||||
<PortalSwitcher
|
||||
v-if="showPortalSwitcher"
|
||||
class="absolute ltr:left-0 rtl:right-0 top-9"
|
||||
@close="showPortalSwitcher = false"
|
||||
@create-portal="createPortalDialogRef.dialogRef.open()"
|
||||
/>
|
||||
</OnClickOutside>
|
||||
<CreatePortalDialog ref="createPortalDialogRef" />
|
||||
</div>
|
||||
<PortalSwitcher
|
||||
v-if="showPortalSwitcher"
|
||||
class="absolute ltr:left-0 rtl:right-0 top-9"
|
||||
@close="showPortalSwitcher = false"
|
||||
@create-portal="createPortalDialogRef.dialogRef.open()"
|
||||
/>
|
||||
</OnClickOutside>
|
||||
<CreatePortalDialog ref="createPortalDialogRef" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="breadcrumbLabel">
|
||||
<div class="w-0.5 h-4 rounded-2xl bg-n-weak shrink-0" />
|
||||
<span class="pl-1.5 text-lg font-medium text-n-slate-11">
|
||||
{{ breadcrumbLabel }}
|
||||
</span>
|
||||
</template>
|
||||
</nav>
|
||||
</div>
|
||||
<slot name="header-actions" />
|
||||
</div>
|
||||
|
||||
@@ -256,6 +256,7 @@ watch(
|
||||
:total-items="articlesCount"
|
||||
:items-per-page="25"
|
||||
:header="portalName"
|
||||
:breadcrumb-label="$t('HELP_CENTER.BREADCRUMB.ARTICLES')"
|
||||
:show-pagination-footer="shouldShowPaginationFooter"
|
||||
@update:current-page="handlePageChange"
|
||||
>
|
||||
|
||||
+4
-1
@@ -112,7 +112,10 @@ const reorderCategories = async reorderedGroup => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<HelpCenterLayout :show-pagination-footer="false">
|
||||
<HelpCenterLayout
|
||||
:show-pagination-footer="false"
|
||||
:breadcrumb-label="$t('HELP_CENTER.BREADCRUMB.CATEGORIES')"
|
||||
>
|
||||
<template #header-actions>
|
||||
<CategoryHeaderControls
|
||||
:categories="categories"
|
||||
|
||||
+4
-1
@@ -31,7 +31,10 @@ const localeCount = computed(() => props.locales?.length);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<HelpCenterLayout :show-pagination-footer="false">
|
||||
<HelpCenterLayout
|
||||
:show-pagination-footer="false"
|
||||
:breadcrumb-label="$t('HELP_CENTER.BREADCRUMB.LOCALES')"
|
||||
>
|
||||
<template #header-actions>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-4">
|
||||
|
||||
+2
-45
@@ -12,8 +12,7 @@ import { isValidSlug } from 'shared/helpers/Validators';
|
||||
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import Input from 'dashboard/components-next/input/Input.vue';
|
||||
import Avatar from 'dashboard/components-next/avatar/Avatar.vue';
|
||||
import ComboBox from 'dashboard/components-next/combobox/ComboBox.vue';
|
||||
import PortalAvatar from 'dashboard/components-next/HelpCenter/PortalAvatar.vue';
|
||||
import ColorPicker from 'dashboard/components-next/colorpicker/ColorPicker.vue';
|
||||
|
||||
const props = defineProps({
|
||||
@@ -42,31 +41,12 @@ const state = reactive({
|
||||
slug: '',
|
||||
widgetColor: '',
|
||||
homePageLink: '',
|
||||
liveChatWidgetInboxId: '',
|
||||
logoUrl: '',
|
||||
avatarBlobId: '',
|
||||
});
|
||||
|
||||
const originalState = reactive({ ...state });
|
||||
|
||||
const liveChatWidgets = computed(() => {
|
||||
const inboxes = store.getters['inboxes/getInboxes'];
|
||||
const widgetOptions = inboxes
|
||||
.filter(inbox => inbox.channel_type === 'Channel::WebWidget')
|
||||
.map(inbox => ({
|
||||
value: inbox.id,
|
||||
label: inbox.name,
|
||||
}));
|
||||
|
||||
return [
|
||||
{
|
||||
value: '',
|
||||
label: t('HELP_CENTER.PORTAL_SETTINGS.FORM.LIVE_CHAT_WIDGET.NONE_OPTION'),
|
||||
},
|
||||
...widgetOptions,
|
||||
];
|
||||
});
|
||||
|
||||
const rules = {
|
||||
name: { required, minLength: minLength(2) },
|
||||
slug: {
|
||||
@@ -116,7 +96,6 @@ watch(
|
||||
widgetColor: newVal.color,
|
||||
homePageLink: newVal.homepage_link,
|
||||
slug: newVal.slug,
|
||||
liveChatWidgetInboxId: newVal.inbox?.id || '',
|
||||
});
|
||||
if (newVal.logo) {
|
||||
const {
|
||||
@@ -148,7 +127,6 @@ const handleUpdatePortal = () => {
|
||||
header_text: state.headerText,
|
||||
homepage_link: state.homePageLink,
|
||||
blob_id: state.avatarBlobId,
|
||||
inbox_id: state.liveChatWidgetInboxId,
|
||||
};
|
||||
emit('updatePortal', portal);
|
||||
};
|
||||
@@ -204,12 +182,11 @@ const handleAvatarDelete = () => {
|
||||
<label class="mb-0.5 text-sm font-medium text-gray-900 dark:text-gray-50">
|
||||
{{ t('HELP_CENTER.PORTAL_SETTINGS.FORM.AVATAR.LABEL') }}
|
||||
</label>
|
||||
<Avatar
|
||||
<PortalAvatar
|
||||
:src="state.logoUrl"
|
||||
:name="state.name"
|
||||
:size="72"
|
||||
allow-upload
|
||||
icon-name="i-lucide-building-2"
|
||||
@upload="handleAvatarUpload"
|
||||
@delete="handleAvatarDelete"
|
||||
/>
|
||||
@@ -303,26 +280,6 @@ const handleAvatarDelete = () => {
|
||||
@blur="v$.slug.$touch()"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="grid items-start justify-between w-full gap-2 grid-cols-[200px,1fr]"
|
||||
>
|
||||
<label
|
||||
class="text-sm font-medium whitespace-nowrap py-2.5 text-n-slate-12"
|
||||
>
|
||||
{{ t('HELP_CENTER.PORTAL_SETTINGS.FORM.LIVE_CHAT_WIDGET.LABEL') }}
|
||||
</label>
|
||||
<ComboBox
|
||||
v-model="state.liveChatWidgetInboxId"
|
||||
:options="liveChatWidgets"
|
||||
:placeholder="
|
||||
t('HELP_CENTER.PORTAL_SETTINGS.FORM.LIVE_CHAT_WIDGET.PLACEHOLDER')
|
||||
"
|
||||
:message="
|
||||
t('HELP_CENTER.PORTAL_SETTINGS.FORM.LIVE_CHAT_WIDGET.HELP_TEXT')
|
||||
"
|
||||
class="[&>div>button:not(.focused)]:!outline-n-weak"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="grid items-start justify-between w-full gap-2 grid-cols-[200px,1fr]"
|
||||
>
|
||||
|
||||
+15
-5
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useAccount } from 'dashboard/composables/useAccount';
|
||||
|
||||
@@ -62,6 +62,7 @@ const { isOnChatwootCloud } = useAccount();
|
||||
const addCustomDomainDialogRef = ref(null);
|
||||
const dnsConfigurationDialogRef = ref(null);
|
||||
const updatedDomainAddress = ref('');
|
||||
const pendingDomain = ref('');
|
||||
|
||||
const customDomainAddress = computed(
|
||||
() => props.activePortal?.custom_domain || ''
|
||||
@@ -111,14 +112,23 @@ const updatePortalConfiguration = customDomain => {
|
||||
id: props.activePortal?.id,
|
||||
custom_domain: customDomain,
|
||||
};
|
||||
pendingDomain.value = customDomain;
|
||||
emit('updatePortalConfiguration', portal);
|
||||
addCustomDomainDialogRef.value.dialogRef.close();
|
||||
if (customDomain) {
|
||||
updatedDomainAddress.value = customDomain;
|
||||
dnsConfigurationDialogRef.value.dialogRef.open();
|
||||
}
|
||||
};
|
||||
|
||||
// The save above is fire-and-forget, so the DNS instructions dialog must not
|
||||
// open until the domain is actually persisted — otherwise a failed save still
|
||||
// advances to the next step. We open it once the stored value reflects the
|
||||
// submitted domain.
|
||||
watch(customDomainAddress, savedDomain => {
|
||||
if (!pendingDomain.value || savedDomain !== pendingDomain.value) return;
|
||||
|
||||
pendingDomain.value = '';
|
||||
updatedDomainAddress.value = savedDomain;
|
||||
dnsConfigurationDialogRef.value.dialogRef.open();
|
||||
});
|
||||
|
||||
const closeDNSConfigurationDialog = () => {
|
||||
updatedDomainAddress.value = '';
|
||||
dnsConfigurationDialogRef.value.dialogRef.close();
|
||||
|
||||
+83
-72
@@ -5,12 +5,12 @@ import { useI18n } from 'vue-i18n';
|
||||
import { useMapGetter } from 'dashboard/composables/store.js';
|
||||
|
||||
import HelpCenterLayout from 'dashboard/components-next/HelpCenter/HelpCenterLayout.vue';
|
||||
import PortalBaseSettings from 'dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/PortalBaseSettings.vue';
|
||||
import PortalGeneralSettings from './PortalGeneralSettings.vue';
|
||||
import PortalConfigurationSettings from './PortalConfigurationSettings.vue';
|
||||
import PortalLayoutContentSettings from './PortalLayoutContentSettings.vue';
|
||||
import ConfirmDeletePortalDialog from 'dashboard/components-next/HelpCenter/Pages/PortalSettingsPage/ConfirmDeletePortalDialog.vue';
|
||||
import PortalIntegrationsSettings from './PortalIntegrationsSettings.vue';
|
||||
import Spinner from 'dashboard/components-next/spinner/Spinner.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import Icon from 'dashboard/components-next/icon/Icon.vue';
|
||||
|
||||
const props = defineProps({
|
||||
portals: {
|
||||
@@ -34,7 +34,30 @@ const emit = defineEmits([
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
|
||||
const confirmDeletePortalDialogRef = ref(null);
|
||||
const SETTINGS_TABS = [
|
||||
{
|
||||
id: 'general',
|
||||
labelKey: 'HELP_CENTER.PORTAL_SETTINGS.NAV.GENERAL',
|
||||
icon: 'i-lucide-settings-2',
|
||||
},
|
||||
{
|
||||
id: 'domain',
|
||||
labelKey: 'HELP_CENTER.PORTAL_SETTINGS.NAV.DOMAIN',
|
||||
icon: 'i-lucide-globe',
|
||||
},
|
||||
{
|
||||
id: 'appearance',
|
||||
labelKey: 'HELP_CENTER.PORTAL_SETTINGS.NAV.APPEARANCE',
|
||||
icon: 'i-lucide-palette',
|
||||
},
|
||||
{
|
||||
id: 'integrations',
|
||||
labelKey: 'HELP_CENTER.PORTAL_SETTINGS.NAV.INTEGRATIONS',
|
||||
icon: 'i-lucide-blocks',
|
||||
},
|
||||
];
|
||||
|
||||
const activeTab = ref('general');
|
||||
|
||||
const currentPortalSlug = computed(() => route.params.portalSlug);
|
||||
|
||||
@@ -45,8 +68,6 @@ const activePortal = computed(() => {
|
||||
return props.portals?.find(portal => portal.slug === currentPortalSlug.value);
|
||||
});
|
||||
|
||||
const activePortalName = computed(() => activePortal.value?.name || '');
|
||||
|
||||
const isLoading = computed(() => props.isFetching || isSwitchingPortal.value);
|
||||
|
||||
const handleUpdatePortal = portal => {
|
||||
@@ -65,18 +86,16 @@ const handleSendCnameInstructions = payload => {
|
||||
emit('sendCnameInstructions', payload);
|
||||
};
|
||||
|
||||
const openConfirmDeletePortalDialog = () => {
|
||||
confirmDeletePortalDialogRef.value.dialogRef.open();
|
||||
};
|
||||
|
||||
const handleDeletePortal = () => {
|
||||
emit('deletePortal', activePortal.value);
|
||||
confirmDeletePortalDialogRef.value.dialogRef.close();
|
||||
const handleDeletePortal = portal => {
|
||||
emit('deletePortal', portal);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<HelpCenterLayout :show-pagination-footer="false">
|
||||
<HelpCenterLayout
|
||||
:show-pagination-footer="false"
|
||||
:breadcrumb-label="t('HELP_CENTER.BREADCRUMB.SETTINGS')"
|
||||
>
|
||||
<template #content>
|
||||
<div
|
||||
v-if="isLoading"
|
||||
@@ -84,68 +103,60 @@ const handleDeletePortal = () => {
|
||||
>
|
||||
<Spinner />
|
||||
</div>
|
||||
<div
|
||||
v-else-if="activePortal"
|
||||
class="flex flex-col w-full gap-4 max-w-[40rem] pb-8"
|
||||
>
|
||||
<PortalBaseSettings
|
||||
:active-portal="activePortal"
|
||||
:is-fetching="isFetching"
|
||||
@update-portal="handleUpdatePortal"
|
||||
/>
|
||||
<div class="w-full h-px bg-n-weak" />
|
||||
<PortalConfigurationSettings
|
||||
:active-portal="activePortal"
|
||||
:is-fetching="isFetching"
|
||||
:is-fetching-status="isFetchingSSLStatus"
|
||||
@update-portal-configuration="handleUpdatePortalConfiguration"
|
||||
@refresh-status="fetchSSLStatus"
|
||||
@send-cname-instructions="handleSendCnameInstructions"
|
||||
/>
|
||||
<div class="w-full h-px bg-n-weak" />
|
||||
<PortalLayoutContentSettings
|
||||
:active-portal="activePortal"
|
||||
:is-fetching="isFetching"
|
||||
@update-portal-configuration="handleUpdatePortalConfiguration"
|
||||
/>
|
||||
<div class="w-full h-px bg-n-weak" />
|
||||
<div class="flex items-end justify-between w-full gap-4">
|
||||
<div class="flex flex-col gap-2">
|
||||
<h6 class="text-base font-medium text-n-slate-12">
|
||||
{{
|
||||
t(
|
||||
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.DELETE_PORTAL.HEADER'
|
||||
)
|
||||
}}
|
||||
</h6>
|
||||
<span class="text-sm text-n-slate-11">
|
||||
{{
|
||||
t(
|
||||
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.DELETE_PORTAL.DESCRIPTION'
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
:label="
|
||||
t(
|
||||
'HELP_CENTER.PORTAL_SETTINGS.CONFIGURATION_FORM.DELETE_PORTAL.BUTTON',
|
||||
{
|
||||
portalName: activePortalName,
|
||||
}
|
||||
)
|
||||
<div v-else-if="activePortal" class="flex items-start w-full gap-8">
|
||||
<nav class="sticky top-0 flex flex-col w-48 gap-0.5 shrink-0 py-1">
|
||||
<button
|
||||
v-for="tab in SETTINGS_TABS"
|
||||
:key="tab.id"
|
||||
type="button"
|
||||
class="flex items-center w-full h-9 gap-2 px-2.5 text-sm transition-colors rounded-lg"
|
||||
:class="
|
||||
activeTab === tab.id
|
||||
? 'bg-n-alpha-2 text-n-slate-12 font-medium'
|
||||
: 'text-n-slate-11 hover:bg-n-alpha-1 hover:text-n-slate-12'
|
||||
"
|
||||
color="ruby"
|
||||
class="max-w-56 !w-fit"
|
||||
@click="openConfirmDeletePortalDialog"
|
||||
:aria-current="activeTab === tab.id ? 'page' : undefined"
|
||||
@click="activeTab = tab.id"
|
||||
>
|
||||
<Icon :icon="tab.icon" class="shrink-0 size-4" />
|
||||
{{ t(tab.labelKey) }}
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<div class="flex flex-col flex-1 min-w-0 max-w-[40rem] pb-8">
|
||||
<PortalGeneralSettings
|
||||
v-if="activeTab === 'general'"
|
||||
:active-portal="activePortal"
|
||||
:is-fetching="isFetching"
|
||||
@update-portal="handleUpdatePortal"
|
||||
@delete-portal="handleDeletePortal"
|
||||
/>
|
||||
|
||||
<PortalConfigurationSettings
|
||||
v-else-if="activeTab === 'domain'"
|
||||
:active-portal="activePortal"
|
||||
:is-fetching="isFetching"
|
||||
:is-fetching-status="isFetchingSSLStatus"
|
||||
@update-portal-configuration="handleUpdatePortalConfiguration"
|
||||
@refresh-status="fetchSSLStatus"
|
||||
@send-cname-instructions="handleSendCnameInstructions"
|
||||
/>
|
||||
|
||||
<PortalLayoutContentSettings
|
||||
v-else-if="activeTab === 'appearance'"
|
||||
:active-portal="activePortal"
|
||||
:is-fetching="isFetching"
|
||||
@update-portal-configuration="handleUpdatePortalConfiguration"
|
||||
/>
|
||||
|
||||
<PortalIntegrationsSettings
|
||||
v-else-if="activeTab === 'integrations'"
|
||||
:active-portal="activePortal"
|
||||
:is-fetching="isFetching"
|
||||
@update-portal-configuration="handleUpdatePortalConfiguration"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<ConfirmDeletePortalDialog
|
||||
ref="confirmDeletePortalDialogRef"
|
||||
:active-portal-name="activePortalName"
|
||||
@delete-portal="handleDeletePortal"
|
||||
/>
|
||||
</HelpCenterLayout>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<script setup>
|
||||
import Avatar from 'dashboard/components-next/avatar/Avatar.vue';
|
||||
|
||||
// Renders a portal's logo consistently across the help center — the layout
|
||||
// header, the portal switcher, and portal settings — so the icon fallback
|
||||
// and shape stay in one place instead of being copied per call site.
|
||||
defineProps({
|
||||
src: { type: String, default: '' },
|
||||
name: { type: String, default: '' },
|
||||
size: { type: Number, default: 24 },
|
||||
allowUpload: { type: Boolean, default: false },
|
||||
});
|
||||
|
||||
const emit = defineEmits(['upload', 'delete']);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Avatar
|
||||
:src="src"
|
||||
:name="name"
|
||||
:size="size"
|
||||
:allow-upload="allowUpload"
|
||||
icon-name="i-lucide-building-2"
|
||||
@upload="emit('upload', $event)"
|
||||
@delete="emit('delete')"
|
||||
/>
|
||||
</template>
|
||||
+2
-4
@@ -6,7 +6,7 @@ import { useMapGetter, useStore } from 'dashboard/composables/store.js';
|
||||
import { buildPortalURL } from 'dashboard/helper/portalHelper';
|
||||
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import Avatar from 'dashboard/components-next/avatar/Avatar.vue';
|
||||
import PortalAvatar from 'dashboard/components-next/HelpCenter/PortalAvatar.vue';
|
||||
|
||||
const emit = defineEmits(['close', 'createPortal']);
|
||||
|
||||
@@ -151,13 +151,11 @@ const redirectToPortalHomePage = () => {
|
||||
<span class="text-sm font-medium truncate text-n-slate-12">
|
||||
{{ portal.name || '' }}
|
||||
</span>
|
||||
<Avatar
|
||||
<PortalAvatar
|
||||
v-if="portal"
|
||||
:name="portal.name"
|
||||
:src="getPortalThumbnailSrc(portal)"
|
||||
:size="20"
|
||||
icon-name="i-lucide-building-2"
|
||||
rounded-full
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -404,6 +404,12 @@
|
||||
"PLACEHOLDER": "Search for articles"
|
||||
}
|
||||
},
|
||||
"BREADCRUMB": {
|
||||
"ARTICLES": "Articles",
|
||||
"CATEGORIES": "Categories",
|
||||
"LOCALES": "Locales",
|
||||
"SETTINGS": "Settings"
|
||||
},
|
||||
"CATEGORY": {
|
||||
"ADD": {
|
||||
"TITLE": "Create a category",
|
||||
@@ -806,12 +812,6 @@
|
||||
"LABEL": "Slug",
|
||||
"PLACEHOLDER": "Portal slug"
|
||||
},
|
||||
"LIVE_CHAT_WIDGET": {
|
||||
"LABEL": "Live chat widget",
|
||||
"PLACEHOLDER": "Select live chat widget",
|
||||
"HELP_TEXT": "Select a live chat widget that will appear on your help center",
|
||||
"NONE_OPTION": "No widget"
|
||||
},
|
||||
"BRAND_COLOR": {
|
||||
"LABEL": "Brand color"
|
||||
},
|
||||
@@ -888,6 +888,30 @@
|
||||
},
|
||||
"SAVE": "Save changes"
|
||||
},
|
||||
"INTEGRATIONS": {
|
||||
"HEADER": "Integrations",
|
||||
"DESCRIPTION": "Connect tools that extend what your help center can do.",
|
||||
"LIVE_CHAT": {
|
||||
"TITLE": "Live chat with Chatwoot",
|
||||
"DESCRIPTION": "Show a live chat widget on your help center so visitors can reach you while they read.",
|
||||
"PLACEHOLDER": "Select live chat widget",
|
||||
"NONE_OPTION": "No widget"
|
||||
},
|
||||
"GTM": {
|
||||
"TITLE": "Google Tag Manager",
|
||||
"DESCRIPTION": "Add analytics and marketing tags, like Google Analytics, by connecting your Tag Manager container.",
|
||||
"PLACEHOLDER": "GTM-XXXXXXX",
|
||||
"HELP": "Find this in your Google Tag Manager workspace. Leave empty to disable.",
|
||||
"INVALID": "Enter a valid container ID, for example GTM-XXXXXXX."
|
||||
},
|
||||
"SAVE": "Save changes"
|
||||
},
|
||||
"NAV": {
|
||||
"GENERAL": "General",
|
||||
"DOMAIN": "Domain",
|
||||
"APPEARANCE": "Appearance",
|
||||
"INTEGRATIONS": "Integrations"
|
||||
},
|
||||
"API": {
|
||||
"CREATE_PORTAL": {
|
||||
"SUCCESS_MESSAGE": "Portal created successfully",
|
||||
|
||||
Reference in New Issue
Block a user