feat: add composables for migration and update portal settings (#9299)

* feat: setup vuelitdate for vue 2.7

* feat: add all composables

* fix: portal settings layout

* feat: remove styles

* feat: use setup API for ListAllCategories

* chore: format ListAllCategories

* refactor: add useAlert

* feat: add track composable

* feat: update map getters

* fix: import

* feat: update edit portal locales page [wip]

* feat: migrate locales page

* feat: remove alert message ref

* chore: format EditPortalLocales

* refactor: use composiiton api for PortalCustomization

* refactor: remove color

* feat: update PortalSettingsCustomizationForm to use setup syntax

* refactor: no need to import defineEmits

* refactor: format component

* fix: update logic

* feat: migrate PortalSettingsBasicForm

* refactor: format PortalSettingsBasicForm

* refactor: migrate EditPortalCustomization to Vue 2.7

* feat: migrate EditPortalBasic to vue 2.7

* chore: revert changes to EditPortal

* fix: portal layout

* fix: width

* feat: use setup syntax

* fix: double border

* feat: return track method

* refactor: track usage

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
This commit is contained in:
Shivam Mishra
2024-04-30 10:13:50 +05:30
committed by GitHub
parent 2012d00109
commit 705f8ef948
10 changed files with 807 additions and 851 deletions

View File

@@ -0,0 +1,34 @@
<script setup>
defineProps({
title: {
type: String,
default: null,
},
});
</script>
<template>
<div
class="flex-grow-0 flex-shrink-0 w-full h-full max-w-full bg-white border border-transparent border-solid dark:bg-slate-900 dark:border-transparent md:max-w-2xl"
>
<h3
v-if="$slots.title || title"
class="text-lg text-black-900 dark:text-slate-200"
>
<slot name="title">{{ title }}</slot>
</h3>
<div
class="mx-0 my-4 border-b border-solid border-slate-25 dark:border-slate-800"
>
<slot />
</div>
<div class="flex justify-between">
<div>
<slot name="footer-left" />
</div>
<div>
<slot name="footer-right" />
</div>
</div>
</div>
</template>

View File

@@ -1,256 +1,241 @@
<template>
<div
class="pt-3 bg-white dark:bg-slate-900 h-full border border-solid border-transparent px-6 pb-6 dark:border-transparent w-full max-w-full md:w-3/4 md:max-w-[75%] flex-shrink-0 flex-grow-0"
>
<div class="w-full">
<h3 class="text-lg text-black-900 dark:text-slate-200">
{{
$t(
'HELP_CENTER.PORTAL.ADD.CREATE_FLOW_PAGE.BASIC_SETTINGS_PAGE.TITLE'
)
}}
</h3>
</div>
<div
class="my-4 mx-0 border-b border-solid border-slate-25 dark:border-slate-800"
>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<div class="mb-4">
<div class="flex items-center flex-row">
<woot-avatar-uploader
ref="imageUpload"
:label="$t('HELP_CENTER.PORTAL.ADD.LOGO.LABEL')"
:src="logoUrl"
@change="onFileChange"
/>
<div v-if="showDeleteButton" class="avatar-delete-btn">
<woot-button
type="button"
color-scheme="alert"
variant="hollow"
size="small"
@click="deleteAvatar"
>
{{ $t('PROFILE_SETTINGS.DELETE_AVATAR') }}
</woot-button>
</div>
</div>
<p
class="mt-1 mb-0 text-xs text-slate-600 dark:text-slate-400 not-italic"
>
{{ $t('HELP_CENTER.PORTAL.ADD.LOGO.HELP_TEXT') }}
</p>
</div>
<div class="mb-4">
<woot-input
v-model.trim="name"
:class="{ error: $v.name.$error }"
:error="nameError"
:label="$t('HELP_CENTER.PORTAL.ADD.NAME.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.NAME.PLACEHOLDER')"
:help-text="$t('HELP_CENTER.PORTAL.ADD.NAME.HELP_TEXT')"
@blur="$v.name.$touch"
@input="onNameChange"
/>
</div>
<div class="mb-4">
<woot-input
v-model.trim="slug"
:class="{ error: $v.slug.$error }"
:error="slugError"
:label="$t('HELP_CENTER.PORTAL.ADD.SLUG.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.SLUG.PLACEHOLDER')"
:help-text="domainHelpText"
@blur="$v.slug.$touch"
/>
</div>
<div class="mb-4">
<woot-input
v-model.trim="domain"
:class="{ error: $v.domain.$error }"
:label="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.PLACEHOLDER')"
:help-text="domainExampleHelpText"
:error="domainError"
@blur="$v.domain.$touch"
/>
</div>
</div>
</div>
<div class="flex justify-end">
<woot-button
:is-loading="isSubmitting"
:is-disabled="$v.$invalid"
@click="onSubmitClick"
>
{{ submitButtonText }}
</woot-button>
</div>
</div>
</template>
<script setup>
import { useVuelidate } from '@vuelidate/core';
import { required, minLength } from '@vuelidate/validators';
<script>
import { required, minLength } from 'vuelidate/lib/validators';
import { isDomain } from 'shared/helpers/Validators';
import { defineComponent, reactive, computed, onMounted } from 'vue';
import { useI18n } from 'dashboard/composables/useI18n';
import { useAlert } from 'dashboard/composables';
import alertMixin from 'shared/mixins/alertMixin';
import { convertToCategorySlug } from 'dashboard/helper/commons.js';
import { buildPortalURL } from 'dashboard/helper/portalHelper';
import wootConstants from 'dashboard/constants/globals';
import { hasValidAvatarUrl } from 'dashboard/helper/URLHelper';
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
import { uploadFile } from 'dashboard/helper/uploadHelper';
import { isDomain } from 'shared/helpers/Validators';
import SettingsLayout from './Layout/SettingsLayout.vue';
const { EXAMPLE_URL } = wootConstants;
const MAXIMUM_FILE_UPLOAD_SIZE = 4; // in MB
export default {
mixins: [alertMixin],
props: {
portal: {
type: Object,
default: () => {},
},
isSubmitting: {
type: Boolean,
default: false,
},
submitButtonText: {
type: String,
default: '',
},
},
data() {
return {
name: '',
slug: '',
domain: '',
alertMessage: '',
const { t } = useI18n();
// Logouploader keys
avatarBlobId: '',
logoUrl: '',
};
},
validations: {
name: {
required,
minLength: minLength(2),
},
slug: {
required,
},
domain: {
isDomain,
},
},
computed: {
nameError() {
if (this.$v.name.$error) {
return this.$t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR');
}
return '';
},
slugError() {
if (this.$v.slug.$error) {
return this.$t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
}
return '';
},
domainError() {
if (this.$v.domain.$error) {
return this.$t('HELP_CENTER.PORTAL.ADD.DOMAIN.ERROR');
}
return '';
},
domainHelpText() {
return buildPortalURL(this.slug);
},
domainExampleHelpText() {
return this.$t('HELP_CENTER.PORTAL.ADD.DOMAIN.HELP_TEXT', {
exampleURL: EXAMPLE_URL,
});
},
showDeleteButton() {
return hasValidAvatarUrl(this.logoUrl);
},
},
mounted() {
const portal = this.portal || {};
this.name = portal.name || '';
this.slug = portal.slug || '';
this.domain = portal.custom_domain || '';
this.alertMessage = '';
if (portal.logo) {
const {
logo: { file_url: logoURL, blob_id: blobId },
} = portal;
this.logoUrl = logoURL;
this.avatarBlobId = blobId;
}
},
methods: {
onNameChange() {
this.slug = convertToCategorySlug(this.name);
},
onSubmitClick() {
this.$v.$touch();
if (this.$v.$invalid) {
return;
}
defineComponent({
name: 'PortalSettingsBasicForm',
});
const portal = {
name: this.name,
slug: this.slug,
custom_domain: this.domain,
blob_id: this.avatarBlobId || null,
};
this.$emit('submit', portal);
},
async deleteAvatar() {
this.logoUrl = '';
this.avatarBlobId = '';
this.$emit('delete-logo');
},
onFileChange({ file }) {
if (checkFileSizeLimit(file, MAXIMUM_FILE_UPLOAD_SIZE)) {
this.uploadLogoToStorage(file);
} else {
this.showAlert(
this.$t(
'PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.IMAGE_UPLOAD_SIZE_ERROR',
{
size: MAXIMUM_FILE_UPLOAD_SIZE,
}
)
);
}
const props = defineProps({
portal: {
type: Object,
default: () => {},
},
isSubmitting: {
type: Boolean,
default: false,
},
submitButtonText: {
type: String,
default: '',
},
});
this.$refs.imageUpload.value = '';
},
async uploadLogoToStorage(file) {
try {
const { fileUrl, blobId } = await uploadFile(file);
if (fileUrl) {
this.logoUrl = fileUrl;
this.avatarBlobId = blobId;
}
} catch (error) {
this.showAlert(
this.$t('HELP_CENTER.PORTAL.ADD.LOGO.IMAGE_DELETE_ERROR')
);
}
},
const state = reactive({
name: '',
slug: '',
domain: '',
logoUrl: '',
avatarBlobId: '',
});
const rules = {
name: {
required,
minLength: minLength(2),
},
slug: {
required,
},
domain: {
isDomain,
},
};
</script>
<style lang="scss" scoped>
::v-deep {
input {
@apply mb-1;
const v$ = useVuelidate(rules, state);
const nameError = computed(() => {
if (v$.value.name.$error) {
return t('HELP_CENTER.CATEGORY.ADD.NAME.ERROR');
}
.help-text {
@apply mb-0;
return '';
});
const slugError = computed(() => {
if (v$.value.slug.$error) {
return t('HELP_CENTER.CATEGORY.ADD.SLUG.ERROR');
}
return '';
});
const domainError = computed(() => {
if (v$.value.domain.$error) {
return t('HELP_CENTER.PORTAL.ADD.DOMAIN.ERROR');
}
return '';
});
const domainHelpText = computed(() => {
return buildPortalURL(state.slug);
});
const domainExampleHelpText = computed(() => {
return t('HELP_CENTER.PORTAL.ADD.DOMAIN.HELP_TEXT', {
exampleURL: EXAMPLE_URL,
});
});
const showDeleteButton = computed(() => {
return hasValidAvatarUrl(state.logoUrl);
});
const emit = defineEmits(['submit', 'delete-logo']);
onMounted(() => {
const portal = props.portal || {};
state.name = portal.name || '';
state.slug = portal.slug || '';
state.domain = portal.custom_domain || '';
if (portal.logo) {
const {
logo: { file_url: logoURL, blob_id: blobId },
} = portal;
state.logoUrl = logoURL;
state.avatarBlobId = blobId;
}
});
function onNameChange() {
state.slug = convertToCategorySlug(state.name);
}
function onSubmitClick() {
v$.value.$touch();
if (v$.value.$invalid) {
return;
}
const portal = {
name: state.name,
slug: state.slug,
custom_domain: state.domain,
blob_id: state.avatarBlobId || null,
};
emit('submit', portal);
}
async function deleteAvatar() {
state.logoUrl = '';
state.avatarBlobId = '';
emit('delete-logo');
}
async function uploadLogoToStorage(file) {
try {
const { fileUrl, blobId } = await uploadFile(file);
if (fileUrl) {
state.logoUrl = fileUrl;
state.avatarBlobId = blobId;
}
} catch (error) {
useAlert(t('HELP_CENTER.PORTAL.ADD.LOGO.IMAGE_UPLOAD_ERROR'));
}
}
</style>
function onFileChange({ file }) {
if (checkFileSizeLimit(file, MAXIMUM_FILE_UPLOAD_SIZE)) {
uploadLogoToStorage(file);
} else {
const errorKey =
'PROFILE_SETTINGS.FORM.MESSAGE_SIGNATURE_SECTION.IMAGE_UPLOAD_SIZE_ERROR';
useAlert(t(errorKey, { size: MAXIMUM_FILE_UPLOAD_SIZE }));
}
}
</script>
<template>
<SettingsLayout
:title="
$t('HELP_CENTER.PORTAL.ADD.CREATE_FLOW_PAGE.BASIC_SETTINGS_PAGE.TITLE')
"
>
<div>
<div class="mb-4">
<div class="flex flex-row items-center">
<woot-avatar-uploader
:label="$t('HELP_CENTER.PORTAL.ADD.LOGO.LABEL')"
:src="state.logoUrl"
@change="onFileChange"
/>
<div v-if="showDeleteButton" class="avatar-delete-btn">
<woot-button
type="button"
color-scheme="alert"
variant="hollow"
size="small"
@click="deleteAvatar"
>
{{ $t('PROFILE_SETTINGS.DELETE_AVATAR') }}
</woot-button>
</div>
</div>
<p
class="mt-1 mb-0 text-xs not-italic text-slate-600 dark:text-slate-400"
>
{{ $t('HELP_CENTER.PORTAL.ADD.LOGO.HELP_TEXT') }}
</p>
</div>
<div class="mb-4">
<woot-input
v-model="state.name"
:class="{ error: v$.name.$error }"
:error="nameError"
:label="$t('HELP_CENTER.PORTAL.ADD.NAME.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.NAME.PLACEHOLDER')"
:help-text="$t('HELP_CENTER.PORTAL.ADD.NAME.HELP_TEXT')"
@blur="v$.name.$touch"
@input="onNameChange"
/>
</div>
<div class="mb-4">
<woot-input
v-model="state.slug"
:class="{ error: v$.slug.$error }"
:error="slugError"
:label="$t('HELP_CENTER.PORTAL.ADD.SLUG.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.SLUG.PLACEHOLDER')"
:help-text="domainHelpText"
@blur="v$.slug.$touch"
/>
</div>
<div class="mb-4">
<woot-input
v-model="state.domain"
:class="{ error: v$.domain.$error }"
:label="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.DOMAIN.PLACEHOLDER')"
:help-text="domainExampleHelpText"
:error="domainError"
@blur="v$.domain.$touch"
/>
</div>
</div>
<template #footer-right>
<woot-button
:is-loading="isSubmitting"
:is-disabled="v$.$invalid"
@click="onSubmitClick"
>
{{ submitButtonText }}
</woot-button>
</template>
</SettingsLayout>
</template>

View File

@@ -1,68 +1,140 @@
<script setup>
import { getRandomColor } from 'dashboard/helper/labelColor';
import SettingsLayout from './Layout/SettingsLayout.vue';
import wootConstants from 'dashboard/constants/globals';
const { EXAMPLE_URL } = wootConstants;
import { useVuelidate } from '@vuelidate/core';
import { url } from '@vuelidate/validators';
import { defineComponent, reactive, computed, onMounted } from 'vue';
import { useI18n } from 'dashboard/composables/useI18n';
defineComponent({
name: 'PortalSettingsCustomizationForm',
});
const { t } = useI18n();
const props = defineProps({
portal: {
type: Object,
default: () => ({}),
},
isSubmitting: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['submit']);
const state = reactive({
color: getRandomColor(),
pageTitle: '',
headerText: '',
homePageLink: '',
});
const rules = {
homePageLink: { url },
};
const homepageExampleHelpText = computed(() => {
return t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.HELP_TEXT', {
exampleURL: EXAMPLE_URL,
});
});
const v$ = useVuelidate(rules, state);
function updateDataFromStore() {
const { portal } = props;
if (portal) {
state.color = portal.color || getRandomColor();
state.pageTitle = portal.page_title || '';
state.headerText = portal.header_text || '';
state.homePageLink = portal.homepage_link || '';
}
}
function onSubmitClick() {
v$.value.$touch();
if (v$.value.$invalid) {
return;
}
const portal = {
id: props.portal.id,
slug: props.portal.slug,
color: state.color,
page_title: state.pageTitle,
header_text: state.headerText,
homepage_link: state.homePageLink,
};
emit('submit', portal);
}
onMounted(() => {
updateDataFromStore();
});
</script>
<template>
<div
class="pt-3 bg-white dark:bg-slate-900 h-full border border-solid border-transparent px-6 pb-6 dark:border-transparent w-full max-w-full md:w-3/4 md:max-w-[75%] flex-shrink-0 flex-grow-0"
<SettingsLayout
:title="
$t('HELP_CENTER.PORTAL.ADD.CREATE_FLOW_PAGE.CUSTOMIZATION_PAGE.TITLE')
"
>
<div class="w-full">
<h3 class="text-lg text-black-900 dark:text-slate-200">
{{
$t('HELP_CENTER.PORTAL.ADD.CREATE_FLOW_PAGE.CUSTOMIZATION_PAGE.TITLE')
}}
</h3>
</div>
<div
class="my-4 mx-0 border-b border-solid border-slate-25 dark:border-slate-800"
>
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
<div class="mb-4">
<label>
{{ $t('HELP_CENTER.PORTAL.ADD.THEME_COLOR.LABEL') }}
</label>
<woot-color-picker v-model="color" />
<p
class="mt-1 mb-0 text-xs text-slate-600 dark:text-slate-400 not-italic"
>
{{ $t('HELP_CENTER.PORTAL.ADD.THEME_COLOR.HELP_TEXT') }}
</p>
</div>
<div class="mb-4">
<woot-input
v-model.trim="pageTitle"
:label="$t('HELP_CENTER.PORTAL.ADD.PAGE_TITLE.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.PAGE_TITLE.PLACEHOLDER')"
:help-text="$t('HELP_CENTER.PORTAL.ADD.PAGE_TITLE.HELP_TEXT')"
/>
</div>
<div class="mb-4">
<woot-input
v-model.trim="headerText"
:label="$t('HELP_CENTER.PORTAL.ADD.HEADER_TEXT.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.HEADER_TEXT.PLACEHOLDER')"
:help-text="$t('HELP_CENTER.PORTAL.ADD.HEADER_TEXT.HELP_TEXT')"
/>
</div>
<div class="mb-4">
<woot-input
v-model.trim="homePageLink"
:label="$t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.LABEL')"
:placeholder="
$t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.PLACEHOLDER')
"
:help-text="homepageExampleHelpText"
:error="
$v.homePageLink.$error
? $t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.ERROR')
: ''
"
:class="{ error: $v.homePageLink.$error }"
@blur="$v.homePageLink.$touch"
/>
</div>
<div class="flex-grow-0 flex-shrink-0">
<div class="mb-4">
<label>
{{ $t('HELP_CENTER.PORTAL.ADD.THEME_COLOR.LABEL') }}
</label>
<woot-color-picker v-model="state.color" />
<p
class="mt-1 mb-0 text-xs not-italic text-slate-600 dark:text-slate-400"
>
{{ $t('HELP_CENTER.PORTAL.ADD.THEME_COLOR.HELP_TEXT') }}
</p>
</div>
<div class="mb-4">
<woot-input
v-model="state.pageTitle"
:label="$t('HELP_CENTER.PORTAL.ADD.PAGE_TITLE.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.PAGE_TITLE.PLACEHOLDER')"
:help-text="$t('HELP_CENTER.PORTAL.ADD.PAGE_TITLE.HELP_TEXT')"
/>
</div>
<div class="mb-4">
<woot-input
v-model="state.headerText"
:label="$t('HELP_CENTER.PORTAL.ADD.HEADER_TEXT.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.HEADER_TEXT.PLACEHOLDER')"
:help-text="$t('HELP_CENTER.PORTAL.ADD.HEADER_TEXT.HELP_TEXT')"
/>
</div>
<div class="mb-4">
<woot-input
v-model="state.homePageLink"
:label="$t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.LABEL')"
:placeholder="$t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.PLACEHOLDER')"
:help-text="homepageExampleHelpText"
:error="
v$.homePageLink.$error
? $t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.ERROR')
: ''
"
:class="{ error: v$.homePageLink.$error }"
@blur="v$.homePageLink.$touch"
/>
</div>
</div>
<div class="flex justify-end">
<template #footer-right>
<woot-button
:is-loading="isSubmitting"
:is-disabled="$v.$invalid"
:is-disabled="v$.$invalid"
@click="onSubmitClick"
>
{{
@@ -71,94 +143,12 @@
)
}}
</woot-button>
</div>
</div>
</template>
</SettingsLayout>
</template>
<script>
import { url } from 'vuelidate/lib/validators';
import { getRandomColor } from 'dashboard/helper/labelColor';
import alertMixin from 'shared/mixins/alertMixin';
import wootConstants from 'dashboard/constants/globals';
const { EXAMPLE_URL } = wootConstants;
export default {
components: {},
mixins: [alertMixin],
props: {
portal: {
type: Object,
default: () => ({}),
},
isSubmitting: {
type: Boolean,
default: false,
},
},
data() {
return {
color: '#000',
pageTitle: '',
headerText: '',
homePageLink: '',
alertMessage: '',
};
},
validations: {
homePageLink: {
url,
},
},
computed: {
homepageExampleHelpText() {
return this.$t('HELP_CENTER.PORTAL.ADD.HOME_PAGE_LINK.HELP_TEXT', {
exampleURL: EXAMPLE_URL,
});
},
},
mounted() {
this.color = getRandomColor();
this.updateDataFromStore();
},
methods: {
updateDataFromStore() {
const { portal } = this;
if (portal) {
this.color = portal.color || getRandomColor();
this.pageTitle = portal.page_title || '';
this.headerText = portal.header_text || '';
this.homePageLink = portal.homepage_link || '';
this.alertMessage = '';
}
},
onSubmitClick() {
this.$v.$touch();
if (this.$v.$invalid) {
return;
}
const portal = {
id: this.portal.id,
slug: this.portal.slug,
color: this.color,
page_title: this.pageTitle,
header_text: this.headerText,
homepage_link: this.homePageLink,
};
this.$emit('submit', portal);
},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
input {
@apply mb-1;
}
.help-text {
@apply mb-0;
}
.colorpicker--selected {
@apply mb-0;
}

View File

@@ -1,15 +1,115 @@
<script setup>
import { useRoute } from 'dashboard/composables/route';
import { useStoreGetters, useStore } from 'dashboard/composables/store';
import { useI18n } from 'dashboard/composables/useI18n';
import { useAlert, useTrack } from 'dashboard/composables';
import { PORTALS_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import { defineComponent, ref, computed } from 'vue';
import CategoryListItem from './CategoryListItem.vue';
import AddCategory from './AddCategory.vue';
import EditCategory from './EditCategory.vue';
defineComponent({
name: 'ListAllCategories',
});
const selectedCategory = ref({});
const currentLocaleCode = ref('en');
const showEditCategoryModal = ref(false);
const showAddCategoryModal = ref(false);
const getters = useStoreGetters();
const store = useStore();
const route = useRoute();
const track = useTrack();
const { t } = useI18n();
const currentPortalSlug = computed(() => {
return route.params.portalSlug;
});
const categoriesByLocaleCode = computed(() => {
return getters['categories/categoriesByLocaleCode'].value(
currentLocaleCode.value
);
});
const currentPortal = computed(() => {
const slug = currentPortalSlug.value;
if (slug) return getters['portals/portalBySlug'].value(slug);
return getters['portals/allPortals'].value[0];
});
const currentPortalName = computed(() => {
return currentPortal.value ? currentPortal.value.name : '';
});
const allLocales = computed(() => {
return currentPortal.value ? currentPortal.value.config.allowed_locales : [];
});
const allowedLocaleCodes = computed(() => {
return allLocales.value.map(locale => locale.code);
});
function openAddCategoryModal() {
showAddCategoryModal.value = true;
}
function openEditCategoryModal(category) {
selectedCategory.value = category;
showEditCategoryModal.value = true;
}
function closeAddCategoryModal() {
showAddCategoryModal.value = false;
}
function closeEditCategoryModal() {
showEditCategoryModal.value = false;
}
async function fetchCategoriesByPortalSlugAndLocale(localeCode) {
await store.dispatch('categories/index', {
portalSlug: currentPortalSlug.value,
locale: localeCode,
});
}
async function deleteCategory(category) {
let alertMessage = '';
try {
await store.dispatch('categories/delete', {
portalSlug: currentPortalSlug.value,
categoryId: category.id,
});
alertMessage = t('HELP_CENTER.CATEGORY.DELETE.API.SUCCESS_MESSAGE');
track(PORTALS_EVENTS.DELETE_CATEGORY, {
hasArticles: category?.meta?.articles_count !== 0,
});
} catch (error) {
const errorMessage = error?.message;
alertMessage =
errorMessage || t('HELP_CENTER.CATEGORY.DELETE.API.ERROR_MESSAGE');
} finally {
useAlert(alertMessage);
}
}
function changeCurrentCategory(event) {
const localeCode = event.target.value;
currentLocaleCode.value = localeCode;
fetchCategoriesByPortalSlugAndLocale(localeCode);
}
</script>
<template>
<div class="w-full pl-4">
<header class="flex justify-between items-center mb-4">
<div class="w-full max-w-5xl">
<header class="flex items-center justify-between mb-4">
<div class="flex items-center w-full gap-3">
<label
class="font-normal mb-0 text-base text-slate-800 dark:text-slate-100"
class="mb-0 text-base font-normal text-slate-800 dark:text-slate-100"
>
{{ $t('HELP_CENTER.PORTAL.EDIT.CATEGORIES.TITLE') }}
</label>
<select
:value="currentLocaleCode"
class="w-[15%] select-locale"
class="w-[15%] h-8 mb-0 py-0.5"
@change="changeCurrentCategory"
>
<option
@@ -21,7 +121,7 @@
</option>
</select>
</div>
<div class="flex-none items-center">
<div class="items-center flex-none">
<woot-button
size="small"
variant="smooth"
@@ -58,119 +158,3 @@
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin';
import portalMixin from '../../mixins/portalMixin';
import CategoryListItem from './CategoryListItem.vue';
import AddCategory from './AddCategory.vue';
import EditCategory from './EditCategory.vue';
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
export default {
components: {
CategoryListItem,
AddCategory,
EditCategory,
},
mixins: [alertMixin, portalMixin],
data() {
return {
selectedCategory: {},
selectedLocaleCode: '',
currentLocaleCode: 'en',
showEditCategoryModal: false,
showAddCategoryModal: false,
alertMessage: '',
};
},
computed: {
...mapGetters({
portals: 'portals/allPortals',
meta: 'portals/getMeta',
isFetching: 'portals/isFetchingPortals',
}),
currentPortalSlug() {
return this.$route.params.portalSlug;
},
categoriesByLocaleCode() {
return this.$store.getters['categories/categoriesByLocaleCode'](
this.currentLocaleCode
);
},
currentPortal() {
const slug = this.currentPortalSlug;
if (slug) return this.$store.getters['portals/portalBySlug'](slug);
return this.$store.getters['portals/allPortals'][0];
},
currentPortalName() {
return this.currentPortal ? this.currentPortal.name : '';
},
currentPortalLocale() {
return this.currentPortal ? this.currentPortal?.meta?.default_locale : '';
},
allLocales() {
return this.currentPortal
? this.currentPortal.config.allowed_locales
: [];
},
allowedLocaleCodes() {
return this.allLocales.map(locale => locale.code);
},
},
methods: {
openAddCategoryModal() {
this.showAddCategoryModal = true;
},
openEditCategoryModal(category) {
this.selectedCategory = category;
this.showEditCategoryModal = true;
},
closeAddCategoryModal() {
this.showAddCategoryModal = false;
},
closeEditCategoryModal() {
this.showEditCategoryModal = false;
},
async fetchCategoriesByPortalSlugAndLocale(localeCode) {
await this.$store.dispatch('categories/index', {
portalSlug: this.currentPortalSlug,
locale: localeCode,
});
},
async deleteCategory(category) {
try {
await this.$store.dispatch('categories/delete', {
portalSlug: this.currentPortalSlug,
categoryId: category.id,
});
this.alertMessage = this.$t(
'HELP_CENTER.CATEGORY.DELETE.API.SUCCESS_MESSAGE'
);
this.$track(PORTALS_EVENTS.DELETE_CATEGORY, {
hasArticles: category?.meta?.articles_count !== 0,
});
} catch (error) {
const errorMessage = error?.message;
this.alertMessage =
errorMessage ||
this.$t('HELP_CENTER.CATEGORY.DELETE.API.ERROR_MESSAGE');
} finally {
this.showAlert(this.alertMessage);
}
},
changeCurrentCategory(event) {
const localeCode = event.target.value;
this.currentLocaleCode = localeCode;
this.fetchCategoriesByPortalSlugAndLocale(localeCode);
},
},
};
</script>
<style lang="scss" scoped>
.select-locale {
@apply h-8 mb-0 py-0.5;
}
</style>

View File

@@ -1,3 +1,75 @@
<script setup>
import PortalSettingsBasicForm from 'dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm.vue';
import { useAlert } from 'dashboard/composables';
import { useStoreGetters, useStore } from 'dashboard/composables/store';
import { useRoute, useRouter } from 'dashboard/composables/route';
import { useI18n } from 'dashboard/composables/useI18n';
import { defineComponent, computed, ref, onMounted } from 'vue';
defineComponent({ name: 'EditPortalBasic' });
const getters = useStoreGetters();
const route = useRoute();
const router = useRouter();
const store = useStore();
const { t } = useI18n();
const uiFlags = getters['portals/uiFlagsIn'];
const lastPortalSlug = ref(null);
const currentPortalSlug = computed(() => {
return route.params.portalSlug;
});
const currentPortal = computed(() => {
const slug = route.params.portalSlug;
return getters['portals/portalBySlug'].value(slug);
});
onMounted(() => {
lastPortalSlug.value = currentPortalSlug.value;
});
async function updatePortalSettings(portalObj) {
let alertMessage = '';
try {
const portalSlug = lastPortalSlug.value;
await store.dispatch('portals/update', { ...portalObj, portalSlug });
alertMessage = t('HELP_CENTER.PORTAL.ADD.API.SUCCESS_MESSAGE_FOR_UPDATE');
if (lastPortalSlug.value !== portalObj.slug) {
await store.dispatch('portals/index');
router.replace({
name: route.name,
params: { portalSlug: portalObj.slug },
});
}
} catch (error) {
alertMessage =
error?.message ||
t('HELP_CENTER.PORTAL.ADD.API.ERROR_MESSAGE_FOR_UPDATE');
} finally {
useAlert(alertMessage);
}
}
async function deleteLogo() {
try {
const portalSlug = lastPortalSlug.value;
await store.dispatch('portals/deleteLogo', {
portalSlug,
});
} catch (error) {
useAlert(
error?.message || t('HELP_CENTER.PORTAL.ADD.LOGO.IMAGE_DELETE_ERROR')
);
}
}
</script>
<template>
<portal-settings-basic-form
v-if="currentPortal"
@@ -10,80 +82,3 @@
@delete-logo="deleteLogo"
/>
</template>
<script>
import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin';
import PortalSettingsBasicForm from 'dashboard/routes/dashboard/helpcenter/components/PortalSettingsBasicForm.vue';
export default {
components: {
PortalSettingsBasicForm,
},
mixins: [alertMixin],
data() {
return {
lastPortalSlug: undefined,
alertMessage: '',
};
},
computed: {
...mapGetters({
uiFlags: 'portals/uiFlagsIn',
}),
currentPortalSlug() {
return this.$route.params.portalSlug;
},
currentPortal() {
return this.$store.getters['portals/portalBySlug'](
this.currentPortalSlug
);
},
},
mounted() {
this.lastPortalSlug = this.currentPortalSlug;
},
methods: {
async updatePortalSettings(portalObj) {
try {
const portalSlug = this.lastPortalSlug;
await this.$store.dispatch('portals/update', {
...portalObj,
portalSlug,
});
this.alertMessage = this.$t(
'HELP_CENTER.PORTAL.ADD.API.SUCCESS_MESSAGE_FOR_UPDATE'
);
if (this.lastPortalSlug !== portalObj.slug) {
await this.$store.dispatch('portals/index');
this.$router.replace({
name: this.$route.name,
params: { portalSlug: portalObj.slug },
});
}
} catch (error) {
this.alertMessage =
error?.message ||
this.$t('HELP_CENTER.PORTAL.ADD.API.ERROR_MESSAGE_FOR_UPDATE');
} finally {
this.showAlert(this.alertMessage);
}
},
async deleteLogo() {
try {
const portalSlug = this.lastPortalSlug;
await this.$store.dispatch('portals/deleteLogo', {
portalSlug,
});
} catch (error) {
this.alertMessage =
error?.message ||
this.$t('HELP_CENTER.PORTAL.ADD.LOGO.IMAGE_DELETE_ERROR');
this.showAlert(this.alertMessage);
}
},
},
};
</script>

View File

@@ -1,3 +1,48 @@
<script setup>
import PortalSettingsCustomizationForm from 'dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue';
import { useAlert } from 'dashboard/composables';
import { useStoreGetters, useStore } from 'dashboard/composables/store';
import { useRoute } from 'dashboard/composables/route';
import { useI18n } from 'dashboard/composables/useI18n';
import { defineComponent, computed } from 'vue';
defineComponent({
name: 'EditPortalCustomization',
});
const getters = useStoreGetters();
const route = useRoute();
const store = useStore();
const { t } = useI18n();
const uiFlags = getters['portals/uiFlagsIn'];
const currentPortal = computed(() => {
const slug = route.params.portalSlug;
return getters['portals/portalBySlug'].value(slug);
});
async function updatePortalSettings(portalObj) {
const portalSlug = route.params.portalSlug;
let alertMessage = '';
try {
await store.dispatch('portals/update', {
...portalObj,
portalSlug,
});
alertMessage = t('HELP_CENTER.PORTAL.ADD.API.SUCCESS_MESSAGE_FOR_UPDATE');
} catch (error) {
alertMessage =
error?.message ||
t('HELP_CENTER.PORTAL.ADD.API.ERROR_MESSAGE_FOR_UPDATE');
} finally {
useAlert(alertMessage);
}
}
</script>
<template>
<portal-settings-customization-form
v-if="currentPortal"
@@ -9,51 +54,3 @@
@submit="updatePortalSettings"
/>
</template>
<script>
import alertMixin from 'shared/mixins/alertMixin';
import PortalSettingsCustomizationForm from 'dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue';
import { mapGetters } from 'vuex';
export default {
components: {
PortalSettingsCustomizationForm,
},
mixins: [alertMixin],
data() {
return {
alertMessage: '',
};
},
computed: {
...mapGetters({
uiFlags: 'portals/uiFlagsIn',
}),
currentPortal() {
const slug = this.$route.params.portalSlug;
return this.$store.getters['portals/portalBySlug'](slug);
},
},
methods: {
async updatePortalSettings(portalObj) {
const portalSlug = this.$route.params.portalSlug;
try {
await this.$store.dispatch('portals/update', {
...portalObj,
portalSlug,
});
this.alertMessage = this.$t(
'HELP_CENTER.PORTAL.ADD.API.SUCCESS_MESSAGE_FOR_UPDATE'
);
} catch (error) {
this.alertMessage =
error?.message ||
this.$t('HELP_CENTER.PORTAL.ADD.API.ERROR_MESSAGE_FOR_UPDATE');
} finally {
this.showAlert(this.alertMessage);
}
},
},
};
</script>

View File

@@ -1,6 +1,117 @@
<script setup>
import LocaleItemTable from 'dashboard/routes/dashboard/helpcenter/components/PortalListItemTable.vue';
import AddLocale from 'dashboard/routes/dashboard/helpcenter/components/AddLocale.vue';
import { PORTALS_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import { useAlert, useTrack } from 'dashboard/composables';
import { useStoreGetters, useStore } from 'dashboard/composables/store';
import { useRoute } from 'dashboard/composables/route';
import { useI18n } from 'dashboard/composables/useI18n';
import { defineComponent, ref, onBeforeMount, computed } from 'vue';
defineComponent({
name: 'EditPortalLocales',
});
const isAddLocaleModalOpen = ref(false);
const getters = useStoreGetters();
const store = useStore();
const route = useRoute();
const track = useTrack();
const { t } = useI18n();
const currentPortalSlug = computed(() => {
return route.params.portalSlug;
});
const currentPortal = computed(() => {
const slug = currentPortalSlug.value;
if (slug) return getters['portals/portalBySlug'].value(slug);
return getters['portals/allPortals'].value[0];
});
const locales = computed(() => {
return currentPortal.value?.config.allowed_locales;
});
const allowedLocales = computed(() => {
return Object.keys(locales.value).map(key => {
return this.locales.value[key].code;
});
});
async function fetchPortals() {
await store.dispatch('portals/index');
}
onBeforeMount(() => {
fetchPortals();
});
async function updatePortalLocales({
newAllowedLocales,
defaultLocale,
messageKey,
}) {
let alertMessage = '';
try {
await store.dispatch('portals/update', {
portalSlug: currentPortalSlug.value,
config: {
default_locale: defaultLocale,
allowed_locales: newAllowedLocales,
},
});
alertMessage = t(`HELP_CENTER.PORTAL.${messageKey}.API.SUCCESS_MESSAGE`);
} catch (error) {
alertMessage =
error?.message || t(`HELP_CENTER.PORTAL.${messageKey}.API.ERROR_MESSAGE`);
} finally {
useAlert(alertMessage);
}
}
function changeDefaultLocale({ localeCode }) {
updatePortalLocales({
allowedLocales: allowedLocales.value,
defaultLocale: localeCode,
messageKey: 'CHANGE_DEFAULT_LOCALE',
});
track(PORTALS_EVENTS.SET_DEFAULT_LOCALE, {
newLocale: localeCode,
from: route.name,
});
}
function deletePortalLocale({ localeCode }) {
const updatedLocales = allowedLocales.value.filter(
code => code !== localeCode
);
const defaultLocale = currentPortal.value?.meta.default_locale;
updatePortalLocales({
allowedLocales: updatedLocales,
defaultLocale,
messageKey: 'DELETE_LOCALE',
});
track(PORTALS_EVENTS.DELETE_LOCALE, {
deletedLocale: localeCode,
from: route.name,
});
}
function closeAddLocaleModal() {
isAddLocaleModalOpen.value = false;
}
function addLocale() {
isAddLocaleModalOpen.value = true;
}
</script>
<template>
<div class="portal-locales">
<div class="button-container">
<div class="w-full h-full max-w-5xl space-y-4 bg-white dark:bg-slate-900">
<div class="flex justify-end">
<woot-button
variant="smooth"
size="small"
@@ -11,19 +122,18 @@
{{ $t('HELP_CENTER.PORTAL.PORTAL_SETTINGS.LIST_ITEM.HEADER.ADD') }}
</woot-button>
</div>
<div class="locale-container">
<locale-item-table
:locales="locales"
:selected-locale-code="currentPortal.meta.default_locale"
@change-default-locale="changeDefaultLocale"
@delete="deletePortalLocale"
/>
</div>
<LocaleItemTable
v-if="currentPortal"
:locales="locales"
:selected-locale-code="currentPortal.meta.default_locale"
@change-default-locale="changeDefaultLocale"
@delete="deletePortalLocale"
/>
<woot-modal
:show.sync="isAddLocaleModalOpen"
:on-close="closeAddLocaleModal"
>
<add-locale
<AddLocale
:show="isAddLocaleModalOpen"
:portal="currentPortal"
@cancel="closeAddLocaleModal"
@@ -31,126 +141,3 @@
</woot-modal>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import alertMixin from 'shared/mixins/alertMixin';
import LocaleItemTable from 'dashboard/routes/dashboard/helpcenter/components/PortalListItemTable.vue';
import AddLocale from 'dashboard/routes/dashboard/helpcenter/components/AddLocale.vue';
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
export default {
components: {
LocaleItemTable,
AddLocale,
},
mixins: [alertMixin],
data() {
return {
isAddLocaleModalOpen: false,
lastPortalSlug: undefined,
alertMessage: '',
};
},
computed: {
...mapGetters({
uiFlags: 'portals/uiFlagsIn',
}),
currentPortalSlug() {
return this.$route.params.portalSlug;
},
currentPortal() {
return this.$store.getters['portals/portalBySlug'](
this.currentPortalSlug
);
},
locales() {
return this.currentPortal.config.allowed_locales;
},
allowedLocales() {
return Object.keys(this.locales).map(key => {
return this.locales[key].code;
});
},
},
mounted() {
this.lastPortalSlug = this.currentPortalSlug;
},
methods: {
changeDefaultLocale({ localeCode }) {
this.updatePortalLocales({
allowedLocales: this.allowedLocales,
defaultLocale: localeCode,
successMessage: this.$t(
'HELP_CENTER.PORTAL.CHANGE_DEFAULT_LOCALE.API.SUCCESS_MESSAGE'
),
errorMessage: this.$t(
'HELP_CENTER.PORTAL.CHANGE_DEFAULT_LOCALE.API.ERROR_MESSAGE'
),
});
this.$track(PORTALS_EVENTS.SET_DEFAULT_LOCALE, {
newLocale: localeCode,
from: this.$route.name,
});
},
deletePortalLocale({ localeCode }) {
const updatedLocales = this.allowedLocales.filter(
code => code !== localeCode
);
const defaultLocale = this.currentPortal.meta.default_locale;
this.updatePortalLocales({
allowedLocales: updatedLocales,
defaultLocale,
successMessage: this.$t(
'HELP_CENTER.PORTAL.DELETE_LOCALE.API.SUCCESS_MESSAGE'
),
errorMessage: this.$t(
'HELP_CENTER.PORTAL.DELETE_LOCALE.API.ERROR_MESSAGE'
),
});
this.$track(PORTALS_EVENTS.DELETE_LOCALE, {
deletedLocale: localeCode,
from: this.$route.name,
});
},
async updatePortalLocales({
allowedLocales,
defaultLocale,
successMessage,
errorMessage,
}) {
try {
await this.$store.dispatch('portals/update', {
portalSlug: this.currentPortal.slug,
config: {
default_locale: defaultLocale,
allowed_locales: allowedLocales,
},
});
this.alertMessage = successMessage;
} catch (error) {
this.alertMessage = error?.message || errorMessage;
} finally {
this.showAlert(this.alertMessage);
}
},
closeAddLocaleModal() {
this.isAddLocaleModalOpen = false;
this.selectedPortal = {};
},
addLocale() {
this.isAddLocaleModalOpen = true;
},
},
};
</script>
<style lang="scss" scoped>
.portal-locales {
@apply w-full bg-white dark:bg-slate-900 h-full py-0 pr-0 pl-4;
.button-container {
@apply flex justify-end;
}
.locale-container {
@apply mt-4;
}
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="flex-1">
<section class="flex-1">
<settings-header
button-route="new"
:header-title="portalHeaderText"
@@ -10,16 +10,20 @@
:show-new-button="false"
/>
<div
class="flex flex-row overflow-auto py-4 pl-4 rtl:pl-0 rtl:pr-4 h-full bg-slate-50 dark:bg-slate-800"
class="grid grid-cols-[20rem_1fr] w-full h-full overflow-auto rtl:pl-0 rtl:pr-4 bg-slate-50 dark:bg-slate-800 p-5"
>
<woot-wizard
class="hidden md:block w-1/4"
class="hidden md:block"
:global-config="globalConfig"
:items="items"
/>
<router-view />
<div
class="w-full p-5 bg-white border border-transparent border-solid rounded-md shadow-sm dark:bg-slate-900 dark:border-transparent"
>
<router-view />
</div>
</div>
</div>
</section>
</template>
<script>

View File

@@ -1,3 +1,63 @@
<script setup>
import PortalSettingsCustomizationForm from 'dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue';
import { PORTALS_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import { useAlert, useTrack } from 'dashboard/composables';
import { useStoreGetters, useStore } from 'dashboard/composables/store';
import { useRoute, useRouter } from 'dashboard/composables/route';
import { useI18n } from 'dashboard/composables/useI18n';
import { defineComponent, onMounted, computed } from 'vue';
defineComponent({
name: 'PortalCustomization',
});
const getters = useStoreGetters();
const route = useRoute();
const router = useRouter();
const store = useStore();
const track = useTrack();
const { t } = useI18n();
const uiFlags = getters['portals/uiFlagsIn'];
const currentPortal = computed(() => {
const slug = route.params.portalSlug;
if (slug) return getters['portals/portalBySlug'].value(slug);
return {};
});
onMounted(() => {
store.dispatch('portals/index');
});
async function updatePortalSettings(portalObj) {
const portalSlug = route.params.portalSlug;
let alertMessage = '';
try {
await store.dispatch('portals/update', {
portalSlug,
...portalObj,
});
alertMessage = t('HELP_CENTER.PORTAL.ADD.API.SUCCESS_MESSAGE_FOR_UPDATE');
track(PORTALS_EVENTS.ONBOARD_CUSTOMIZATION, {
hasHomePageLink: Boolean(portalObj.homepage_link),
hasPageTitle: Boolean(portalObj.page_title),
hasHeaderText: Boolean(portalObj.headerText),
});
} catch (error) {
alertMessage =
error?.message ||
t('HELP_CENTER.PORTAL.ADD.API.ERROR_MESSAGE_FOR_UPDATE');
} finally {
useAlert(alertMessage);
router.push({ name: 'portal_finish' });
}
}
</script>
<template>
<portal-settings-customization-form
v-if="currentPortal"
@@ -9,75 +69,3 @@
@submit="updatePortalSettings"
/>
</template>
<script>
import alertMixin from 'shared/mixins/alertMixin';
import PortalSettingsCustomizationForm from 'dashboard/routes/dashboard/helpcenter/components/PortalSettingsCustomizationForm.vue';
import { mapGetters } from 'vuex';
import { getRandomColor } from 'dashboard/helper/labelColor';
import { PORTALS_EVENTS } from '../../../../../helper/AnalyticsHelper/events';
export default {
components: {
PortalSettingsCustomizationForm,
},
mixins: [alertMixin],
data() {
return {
color: '#000',
pageTitle: '',
headerText: '',
homePageLink: '',
alertMessage: '',
};
},
computed: {
...mapGetters({
uiFlags: 'portals/uiFlagsIn',
portals: 'portals/allPortals',
}),
currentPortal() {
const slug = this.$route.params.portalSlug;
return this.$store.getters['portals/portalBySlug'](slug);
},
},
mounted() {
this.fetchPortals();
this.color = getRandomColor();
},
methods: {
fetchPortals() {
this.$store.dispatch('portals/index');
},
async updatePortalSettings(portalObj) {
const portalSlug = this.$route.params.portalSlug;
try {
await this.$store.dispatch('portals/update', {
portalSlug,
...portalObj,
});
this.alertMessage = this.$t(
'HELP_CENTER.PORTAL.ADD.API.SUCCESS_MESSAGE_FOR_UPDATE'
);
this.$track(PORTALS_EVENTS.ONBOARD_CUSTOMIZATION, {
hasHomePageLink: Boolean(portalObj.homepage_link),
hasPageTitle: Boolean(portalObj.page_title),
hasHeaderText: Boolean(portalObj.headerText),
});
} catch (error) {
this.alertMessage =
error?.message ||
this.$t('HELP_CENTER.PORTAL.ADD.API.ERROR_MESSAGE_FOR_UPDATE');
} finally {
this.showAlert(this.alertMessage);
this.$router.push({
name: 'portal_finish',
});
}
},
},
};
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div
class="pt-3 bg-white dark:bg-slate-900 h-full border border-solid border-transparent px-6 pb-6 dark:border-transparent w-full max-w-full md:w-3/4 md:max-w-[75%] flex-shrink-0 flex-grow-0"
class="flex-grow-0 flex-shrink-0 w-full h-full max-w-full px-6 pt-3 pb-6 bg-white border border-transparent border-solid dark:bg-slate-900 dark:border-transparent"
>
<empty-state
:title="$t('HELP_CENTER.PORTAL.ADD.CREATE_FLOW_PAGE.FINISH_PAGE.TITLE')"
@@ -10,7 +10,7 @@
>
<div class="w-full text-center">
<router-link
class="button success nice rounded"
class="rounded button success nice"
:to="{
name: 'list_all_portals',
}"
@@ -22,18 +22,10 @@
</div>
</template>
<script>
<script setup>
import EmptyState from 'dashboard/components/widgets/EmptyState.vue';
export default {
components: {
EmptyState,
},
methods: {
changeRoute() {
this.$router.push({
name: 'list_all_portals',
});
},
},
};
import { defineComponent } from 'vue';
defineComponent({
name: 'PortalSettingsFinish',
});
</script>