feat: add validation and error messages for custom HTML fields in portal settings

This commit is contained in:
gabrieljablonski 2026-03-09 11:48:53 -03:00
parent eaac65c973
commit a4ff73d496
3 changed files with 54 additions and 9 deletions

View File

@ -7,7 +7,13 @@ import { useStore, useStoreGetters } from 'dashboard/composables/store';
import { uploadFile } from 'dashboard/helper/uploadHelper';
import { checkFileSizeLimit } from 'shared/helpers/FileHelper';
import { useVuelidate } from '@vuelidate/core';
import { required, minLength, helpers, url } from '@vuelidate/validators';
import {
required,
minLength,
maxLength,
helpers,
url,
} from '@vuelidate/validators';
import { isValidSlug } from 'shared/helpers/Validators';
import Button from 'dashboard/components-next/button/Button.vue';
@ -35,6 +41,7 @@ const store = useStore();
const getters = useStoreGetters();
const MAXIMUM_FILE_UPLOAD_SIZE = 4; // in MB
const CUSTOM_HTML_MAX_LENGTH = 15_000;
const state = reactive({
name: '',
@ -84,6 +91,8 @@ const rules = {
),
},
homePageLink: { url },
customHeadHtml: { maxLength: maxLength(CUSTOM_HTML_MAX_LENGTH) },
customBodyHtml: { maxLength: maxLength(CUSTOM_HTML_MAX_LENGTH) },
};
const v$ = useVuelidate(rules, state);
@ -102,6 +111,18 @@ const homePageLinkError = computed(() =>
: ''
);
const customHeadHtmlError = computed(() =>
v$.value.customHeadHtml.$error
? t('HELP_CENTER.PORTAL_SETTINGS.FORM.CUSTOM_HEAD_HTML.ERROR')
: ''
);
const customBodyHtmlError = computed(() =>
v$.value.customBodyHtml.$error
? t('HELP_CENTER.PORTAL_SETTINGS.FORM.CUSTOM_BODY_HTML.ERROR')
: ''
);
const isUpdatingPortal = computed(() => {
const slug = props.activePortal?.slug;
if (slug) return getters['portals/uiFlagsIn'].value(slug)?.isUpdating;
@ -375,10 +396,20 @@ const handleAvatarDelete = () => {
t('HELP_CENTER.PORTAL_SETTINGS.FORM.CUSTOM_HEAD_HTML.PLACEHOLDER')
"
rows="4"
class="w-full px-3 py-2 text-sm border rounded-lg resize-y border-n-weak bg-transparent dark:bg-transparent text-n-slate-12 placeholder:text-n-slate-9 focus:outline-none focus:ring-1 focus:ring-n-brand font-mono"
class="w-full px-3 py-2 text-sm border rounded-lg resize-y bg-transparent dark:bg-transparent text-n-slate-12 placeholder:text-n-slate-9 focus:outline-none focus:ring-1 font-mono"
:class="
customHeadHtmlError
? 'border-n-ruby-9 focus:ring-n-ruby-9'
: 'border-n-weak focus:ring-n-brand'
"
@input="v$.customHeadHtml.$touch()"
/>
<span class="text-xs text-n-slate-11">
<span
class="text-xs"
:class="customHeadHtmlError ? 'text-n-ruby-9' : 'text-n-slate-11'"
>
{{
customHeadHtmlError ||
t('HELP_CENTER.PORTAL_SETTINGS.FORM.CUSTOM_HEAD_HTML.HELP_TEXT')
}}
</span>
@ -399,10 +430,20 @@ const handleAvatarDelete = () => {
t('HELP_CENTER.PORTAL_SETTINGS.FORM.CUSTOM_BODY_HTML.PLACEHOLDER')
"
rows="4"
class="w-full px-3 py-2 text-sm border rounded-lg resize-y border-n-weak bg-transparent dark:bg-transparent text-n-slate-12 placeholder:text-n-slate-9 focus:outline-none focus:ring-1 focus:ring-n-brand font-mono"
class="w-full px-3 py-2 text-sm border rounded-lg resize-y bg-transparent dark:bg-transparent text-n-slate-12 placeholder:text-n-slate-9 focus:outline-none focus:ring-1 font-mono"
:class="
customBodyHtmlError
? 'border-n-ruby-9 focus:ring-n-ruby-9'
: 'border-n-weak focus:ring-n-brand'
"
@input="v$.customBodyHtml.$touch()"
/>
<span class="text-xs text-n-slate-11">
<span
class="text-xs"
:class="customBodyHtmlError ? 'text-n-ruby-9' : 'text-n-slate-11'"
>
{{
customBodyHtmlError ||
t('HELP_CENTER.PORTAL_SETTINGS.FORM.CUSTOM_BODY_HTML.HELP_TEXT')
}}
</span>

View File

@ -754,12 +754,14 @@
"CUSTOM_HEAD_HTML": {
"LABEL": "Custom head HTML",
"PLACEHOLDER": "Add custom HTML to the <head> section (e.g., meta tags, analytics, custom CSS)",
"HELP_TEXT": "This code will be injected into the <head> of your portal pages"
"HELP_TEXT": "This code will be injected into the <head> of your portal pages",
"ERROR": "Custom head HTML must be less than 15,000 characters"
},
"CUSTOM_BODY_HTML": {
"LABEL": "Custom body HTML",
"PLACEHOLDER": "Add custom HTML before </body> (e.g., scripts, tracking pixels, widgets)",
"HELP_TEXT": "This code will be injected before the closing </body> tag of your portal pages"
"HELP_TEXT": "This code will be injected before the closing </body> tag of your portal pages",
"ERROR": "Custom body HTML must be less than 15,000 characters"
},
"SAVE_CHANGES": "Save changes"
},

View File

@ -754,12 +754,14 @@
"CUSTOM_HEAD_HTML": {
"LABEL": "HTML personalizado no head",
"PLACEHOLDER": "Adicione HTML personalizado na seção <head> (ex: meta tags, analytics, CSS personalizado)",
"HELP_TEXT": "Este código será injetado no <head> das páginas do seu portal"
"HELP_TEXT": "Este código será injetado no <head> das páginas do seu portal",
"ERROR": "O HTML personalizado do head deve ter menos de 15.000 caracteres"
},
"CUSTOM_BODY_HTML": {
"LABEL": "HTML personalizado no body",
"PLACEHOLDER": "Adicione HTML personalizado antes do </body> (ex: scripts, pixels de rastreamento, widgets)",
"HELP_TEXT": "Este código será injetado antes da tag de fechamento </body> das páginas do seu portal"
"HELP_TEXT": "Este código será injetado antes da tag de fechamento </body> das páginas do seu portal",
"ERROR": "O HTML personalizado do body deve ter menos de 15.000 caracteres"
},
"SAVE_CHANGES": "Salvar Alterações"
},