chore: cleanup code
This commit is contained in:
+91
-66
@@ -54,15 +54,17 @@ const buttonComponents = computed(() => {
|
||||
});
|
||||
|
||||
const interactiveComponents = computed(() => {
|
||||
return templateComponents.value.filter(
|
||||
component => ['LIST', 'PRODUCT', 'CATALOG'].includes(component.type)
|
||||
return templateComponents.value.filter(component =>
|
||||
['LIST', 'PRODUCT', 'CATALOG'].includes(component.type)
|
||||
);
|
||||
});
|
||||
|
||||
const isInteractiveTemplate = computed(() => {
|
||||
const hasInteractiveButtons = buttonComponents.value.some(component =>
|
||||
component.buttons?.some(button =>
|
||||
['quick_reply', 'url', 'phone_number', 'catalog_browse'].includes(button.type)
|
||||
['quick_reply', 'url', 'phone_number', 'catalog_browse'].includes(
|
||||
button.type
|
||||
)
|
||||
)
|
||||
);
|
||||
return hasInteractiveButtons || interactiveComponents.value.length > 0;
|
||||
@@ -105,13 +107,16 @@ const processedStringWithVariableHighlight = computed(() => {
|
||||
const rules = computed(() => {
|
||||
const paramRules = {};
|
||||
Object.keys(processedParams.value).forEach(key => {
|
||||
if (key === 'header' && processedParams.value.header.location_type === 'location') {
|
||||
if (
|
||||
key === 'header' &&
|
||||
processedParams.value.header.location_type === 'location'
|
||||
) {
|
||||
// Add specific validation for location parameters
|
||||
paramRules[key] = {
|
||||
location: {
|
||||
latitude: { required: requiredIf(true) },
|
||||
longitude: { required: requiredIf(true) }
|
||||
}
|
||||
longitude: { required: requiredIf(true) },
|
||||
},
|
||||
};
|
||||
} else {
|
||||
paramRules[key] = { required: requiredIf(true) };
|
||||
@@ -131,10 +136,6 @@ const getFieldErrorType = key => {
|
||||
|
||||
const generateVariables = () => {
|
||||
const allVariables = {};
|
||||
|
||||
// Debug: Log template structure
|
||||
console.log('Template components:', templateComponents.value);
|
||||
console.log('Header component:', headerComponent.value);
|
||||
|
||||
// Process body variables
|
||||
const bodyVars = templateString.value.match(/{{([^}]+)}}/g) || [];
|
||||
@@ -191,7 +192,6 @@ const generateVariables = () => {
|
||||
headerComponent.value.format === 'LOCATION'
|
||||
) {
|
||||
// Location headers need location data
|
||||
console.log('Detected LOCATION header template:', headerComponent.value);
|
||||
allVariables.header = {
|
||||
location: {
|
||||
latitude: '',
|
||||
@@ -262,19 +262,19 @@ const generateVariables = () => {
|
||||
allVariables.interactive = {
|
||||
type: 'list',
|
||||
button_text: 'Select Option',
|
||||
sections: component.sections || []
|
||||
sections: component.sections || [],
|
||||
};
|
||||
} else if (component.type === 'PRODUCT') {
|
||||
allVariables.interactive = {
|
||||
type: 'product',
|
||||
catalog_id: component.catalog_id || '',
|
||||
product_id: component.product_id || ''
|
||||
product_id: component.product_id || '',
|
||||
};
|
||||
} else if (component.type === 'CATALOG') {
|
||||
allVariables.interactive = {
|
||||
type: 'catalog',
|
||||
catalog_id: component.catalog_id || '',
|
||||
title: component.title || 'Browse Products'
|
||||
title: component.title || 'Browse Products',
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -450,7 +450,7 @@ onMounted(() => {
|
||||
|
||||
<!-- Header Variables -->
|
||||
<div v-if="processedParams.header" class="w-full">
|
||||
<h4 class="text-sm font-medium text-n-slate-12 mb-2">
|
||||
<h4 class="mb-2 text-sm font-medium text-n-slate-12">
|
||||
{{
|
||||
t('WHATSAPP_TEMPLATES.PARSER.HEADER_PARAMETERS') ||
|
||||
'Header Parameters'
|
||||
@@ -459,18 +459,22 @@ onMounted(() => {
|
||||
<!-- Location Parameters -->
|
||||
<div
|
||||
v-if="processedParams.header.location_type === 'location'"
|
||||
class="w-full space-y-3 mb-4 p-3 bg-n-solid-1 rounded-lg border border-n-weak"
|
||||
class="p-3 mb-4 space-y-3 w-full rounded-lg border bg-n-solid-1 border-n-weak"
|
||||
>
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<div class="w-4 h-4 bg-blue-500 rounded-full flex items-center justify-center">
|
||||
<div class="flex gap-2 items-center mb-2">
|
||||
<div
|
||||
class="flex justify-center items-center w-4 h-4 bg-blue-500 rounded-full"
|
||||
>
|
||||
<div class="w-2 h-2 bg-white rounded-full"></div>
|
||||
</div>
|
||||
<span class="text-sm font-medium text-n-slate-12">Location Details</span>
|
||||
<span class="text-sm font-medium text-n-slate-12"
|
||||
>Location Details</span
|
||||
>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10">
|
||||
📍 Latitude <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
@@ -485,7 +489,7 @@ onMounted(() => {
|
||||
<span class="text-xs text-n-slate-9">Range: -90.0 to 90.0</span>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10">
|
||||
📍 Longitude <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<Input
|
||||
@@ -500,9 +504,9 @@ onMounted(() => {
|
||||
<span class="text-xs text-n-slate-9">Range: -180.0 to 180.0</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10">
|
||||
🏢 Location Name
|
||||
</label>
|
||||
<Input
|
||||
@@ -513,9 +517,9 @@ onMounted(() => {
|
||||
:message-type="getFieldErrorType('header.location.name')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10">
|
||||
📮 Full Address
|
||||
</label>
|
||||
<Input
|
||||
@@ -526,43 +530,44 @@ onMounted(() => {
|
||||
:message-type="getFieldErrorType('header.location.address')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="text-xs text-n-slate-9 bg-blue-50 p-2 rounded border-l-4 border-blue-400">
|
||||
💡 <strong>Tip:</strong> You can get coordinates by searching your location on Google Maps,
|
||||
right-clicking the pin, and copying the latitude/longitude values.
|
||||
|
||||
<div
|
||||
class="p-2 text-xs bg-blue-50 rounded border-l-4 border-blue-400 text-n-slate-9"
|
||||
>
|
||||
💡 <strong>Tip:</strong> You can get coordinates by searching your
|
||||
location on Google Maps, right-clicking the pin, and copying the
|
||||
latitude/longitude values.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Regular Header Parameters -->
|
||||
<div
|
||||
v-if="processedParams.header.location_type !== 'location'"
|
||||
>
|
||||
<div v-if="processedParams.header.location_type !== 'location'">
|
||||
<div
|
||||
v-for="(variable, key) in processedParams.header"
|
||||
v-if="!['location', 'location_type'].includes(key)"
|
||||
:key="`header-${key}`"
|
||||
class="flex items-center w-full gap-2 mb-2"
|
||||
class="flex gap-2 items-center mb-2 w-full"
|
||||
>
|
||||
<span
|
||||
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
|
||||
>
|
||||
{{ getHeaderFieldLabel(key) }}
|
||||
</span>
|
||||
<Input
|
||||
v-model="processedParams.header[key]"
|
||||
custom-input-class="!h-8 w-full !bg-transparent"
|
||||
class="w-full"
|
||||
:message-type="getFieldErrorType(`header.${key}`)"
|
||||
:placeholder="getHeaderFieldPlaceholder(key)"
|
||||
:type="key === 'media_url' ? 'url' : 'text'"
|
||||
/>
|
||||
<span
|
||||
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
|
||||
>
|
||||
{{ getHeaderFieldLabel(key) }}
|
||||
</span>
|
||||
<Input
|
||||
v-model="processedParams.header[key]"
|
||||
custom-input-class="!h-8 w-full !bg-transparent"
|
||||
class="w-full"
|
||||
:message-type="getFieldErrorType(`header.${key}`)"
|
||||
:placeholder="getHeaderFieldPlaceholder(key)"
|
||||
:type="key === 'media_url' ? 'url' : 'text'"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Body Variables -->
|
||||
<div v-if="processedParams.body" class="w-full">
|
||||
<h4 class="text-sm font-medium text-n-slate-12 mb-2">
|
||||
<h4 class="mb-2 text-sm font-medium text-n-slate-12">
|
||||
{{
|
||||
t('WHATSAPP_TEMPLATES.PARSER.BODY_PARAMETERS') || 'Body Parameters'
|
||||
}}
|
||||
@@ -570,7 +575,7 @@ onMounted(() => {
|
||||
<div
|
||||
v-for="(variable, key) in processedParams.body"
|
||||
:key="`body-${key}`"
|
||||
class="flex items-center w-full gap-2 mb-2"
|
||||
class="flex gap-2 items-center mb-2 w-full"
|
||||
>
|
||||
<span
|
||||
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
|
||||
@@ -591,7 +596,7 @@ onMounted(() => {
|
||||
|
||||
<!-- Footer Variables -->
|
||||
<div v-if="processedParams.footer" class="w-full">
|
||||
<h4 class="text-sm font-medium text-n-slate-12 mb-2">
|
||||
<h4 class="mb-2 text-sm font-medium text-n-slate-12">
|
||||
{{
|
||||
t('WHATSAPP_TEMPLATES.PARSER.FOOTER_PARAMETERS') ||
|
||||
'Footer Parameters'
|
||||
@@ -600,7 +605,7 @@ onMounted(() => {
|
||||
<div
|
||||
v-for="(variable, key) in processedParams.footer"
|
||||
:key="`footer-${key}`"
|
||||
class="flex items-center w-full gap-2 mb-2"
|
||||
class="flex gap-2 items-center mb-2 w-full"
|
||||
>
|
||||
<span
|
||||
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
|
||||
@@ -618,17 +623,22 @@ onMounted(() => {
|
||||
|
||||
<!-- Interactive Components -->
|
||||
<div v-if="processedParams.interactive" class="w-full">
|
||||
<h4 class="text-sm font-medium text-n-slate-12 mb-2">
|
||||
<h4 class="mb-2 text-sm font-medium text-n-slate-12">
|
||||
{{
|
||||
t('WHATSAPP_TEMPLATES.PARSER.INTERACTIVE_PARAMETERS') ||
|
||||
'Interactive Parameters'
|
||||
}}
|
||||
</h4>
|
||||
|
||||
|
||||
<!-- Product Template -->
|
||||
<div v-if="processedParams.interactive.type === 'product'" class="space-y-2 mb-4">
|
||||
<div
|
||||
v-if="processedParams.interactive.type === 'product'"
|
||||
class="mb-4 space-y-2"
|
||||
>
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">Catalog ID</label>
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10"
|
||||
>Catalog ID</label
|
||||
>
|
||||
<Input
|
||||
v-model="processedParams.interactive.catalog_id"
|
||||
custom-input-class="!h-8 w-full !bg-transparent"
|
||||
@@ -638,7 +648,9 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">Product ID</label>
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10"
|
||||
>Product ID</label
|
||||
>
|
||||
<Input
|
||||
v-model="processedParams.interactive.product_id"
|
||||
custom-input-class="!h-8 w-full !bg-transparent"
|
||||
@@ -650,9 +662,14 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<!-- Catalog Template -->
|
||||
<div v-else-if="processedParams.interactive.type === 'catalog'" class="space-y-2 mb-4">
|
||||
<div
|
||||
v-else-if="processedParams.interactive.type === 'catalog'"
|
||||
class="mb-4 space-y-2"
|
||||
>
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">Catalog ID</label>
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10"
|
||||
>Catalog ID</label
|
||||
>
|
||||
<Input
|
||||
v-model="processedParams.interactive.catalog_id"
|
||||
custom-input-class="!h-8 w-full !bg-transparent"
|
||||
@@ -662,7 +679,9 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">Browse Title</label>
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10"
|
||||
>Browse Title</label
|
||||
>
|
||||
<Input
|
||||
v-model="processedParams.interactive.title"
|
||||
custom-input-class="!h-8 w-full !bg-transparent"
|
||||
@@ -674,9 +693,14 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<!-- List Template -->
|
||||
<div v-else-if="processedParams.interactive.type === 'list'" class="space-y-2 mb-4">
|
||||
<div
|
||||
v-else-if="processedParams.interactive.type === 'list'"
|
||||
class="mb-4 space-y-2"
|
||||
>
|
||||
<div>
|
||||
<label class="text-xs font-medium text-n-slate-10 mb-1 block">Button Text</label>
|
||||
<label class="block mb-1 text-xs font-medium text-n-slate-10"
|
||||
>Button Text</label
|
||||
>
|
||||
<Input
|
||||
v-model="processedParams.interactive.button_text"
|
||||
custom-input-class="!h-8 w-full !bg-transparent"
|
||||
@@ -686,14 +710,15 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
<div class="text-xs text-n-slate-10">
|
||||
List sections are configured in the template and cannot be modified here.
|
||||
List sections are configured in the template and cannot be modified
|
||||
here.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Button Variables -->
|
||||
<div v-if="processedParams.buttons" class="w-full">
|
||||
<h4 class="text-sm font-medium text-n-slate-12 mb-2">
|
||||
<h4 class="mb-2 text-sm font-medium text-n-slate-12">
|
||||
{{
|
||||
t('WHATSAPP_TEMPLATES.PARSER.BUTTON_PARAMETERS') ||
|
||||
'Button Parameters'
|
||||
@@ -702,7 +727,7 @@ onMounted(() => {
|
||||
<div
|
||||
v-for="(button, index) in processedParams.buttons"
|
||||
:key="`button-${index}`"
|
||||
class="flex items-center w-full gap-2 mb-2"
|
||||
class="flex gap-2 items-center mb-2 w-full"
|
||||
>
|
||||
<span
|
||||
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
|
||||
@@ -733,7 +758,7 @@ onMounted(() => {
|
||||
<div
|
||||
v-for="(variable, key) in legacyParams"
|
||||
:key="key"
|
||||
class="flex items-center w-full gap-2"
|
||||
class="flex gap-2 items-center w-full"
|
||||
>
|
||||
<span
|
||||
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
|
||||
@@ -748,7 +773,7 @@ onMounted(() => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex items-end justify-between w-full gap-3 h-14">
|
||||
<div class="flex gap-3 justify-between items-end w-full h-14">
|
||||
<Button
|
||||
:label="
|
||||
t(
|
||||
|
||||
+15
-29
@@ -47,7 +47,7 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getTemplatebody(template) {
|
||||
getTemplateBody(template) {
|
||||
return (
|
||||
template.components.find(component => component.type === 'BODY')
|
||||
?.text || ''
|
||||
@@ -73,20 +73,6 @@ export default {
|
||||
header.format === 'DOCUMENT')
|
||||
);
|
||||
},
|
||||
debugTemplate(template) {
|
||||
// Debug helper method - can be used in dev tools console
|
||||
return {
|
||||
name: template.name,
|
||||
status: template.status,
|
||||
hasHeader: !!this.getTemplateHeader(template),
|
||||
headerFormat: this.getTemplateHeader(template)?.format,
|
||||
hasMediaContent: this.hasMediaContent(template),
|
||||
components: template.components.map(c => ({
|
||||
type: c.type,
|
||||
format: c.format,
|
||||
})),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -94,7 +80,7 @@ export default {
|
||||
<template>
|
||||
<div class="w-full">
|
||||
<div
|
||||
class="gap-1 bg-n-alpha-black2 items-center flex mb-2.5 py-0 px-2.5 rounded-lg outline outline-1 outline-n-weak hover:outline-n-slate-6 dark:hover:outline-n-slate-6 focus-within:outline-n-brand dark:focus-within:outline-n-brand"
|
||||
class="flex gap-1 items-center px-2.5 py-0 mb-2.5 rounded-lg bg-n-alpha-black2 outline outline-1 outline-n-weak hover:outline-n-slate-6 dark:hover:outline-n-slate-6 focus-within:outline-n-brand dark:focus-within:outline-n-brand"
|
||||
>
|
||||
<fluent-icon icon="search" class="text-n-slate-12" size="16" />
|
||||
<input
|
||||
@@ -109,16 +95,16 @@ export default {
|
||||
>
|
||||
<div v-for="(template, i) in filteredTemplateMessages" :key="template.id">
|
||||
<button
|
||||
class="rounded-lg cursor-pointer block p-2.5 text-left w-full hover:bg-n-alpha-2 dark:hover:bg-n-solid-2"
|
||||
class="block p-2.5 w-full text-left rounded-lg cursor-pointer hover:bg-n-alpha-2 dark:hover:bg-n-solid-2"
|
||||
@click="$emit('onSelect', template)"
|
||||
>
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-2.5">
|
||||
<div class="flex justify-between items-center mb-2.5">
|
||||
<p class="text-sm">
|
||||
{{ template.name }}
|
||||
</p>
|
||||
<span
|
||||
class="inline-block px-2 py-1 text-xs leading-none bg-n-slate-3 rounded-lg cursor-default text-n-slate-12"
|
||||
class="inline-block px-2 py-1 text-xs leading-none rounded-lg cursor-default bg-n-slate-3 text-n-slate-12"
|
||||
>
|
||||
{{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.LANGUAGE') }} :
|
||||
{{ template.language }}
|
||||
@@ -126,18 +112,18 @@ export default {
|
||||
</div>
|
||||
<!-- Header -->
|
||||
<div v-if="getTemplateHeader(template)" class="mb-3">
|
||||
<p class="font-medium text-xs text-n-slate-11">
|
||||
<p class="text-xs font-medium text-n-slate-11">
|
||||
{{ $t('WHATSAPP_TEMPLATES.PICKER.HEADER') || 'HEADER' }}
|
||||
</p>
|
||||
<div
|
||||
v-if="getTemplateHeader(template).format === 'TEXT'"
|
||||
class="label-body text-sm"
|
||||
class="text-sm label-body"
|
||||
>
|
||||
{{ getTemplateHeader(template).text }}
|
||||
</div>
|
||||
<div
|
||||
v-else-if="hasMediaContent(template)"
|
||||
class="text-sm text-n-slate-11 italic"
|
||||
class="text-sm italic text-n-slate-11"
|
||||
>
|
||||
{{
|
||||
$t('WHATSAPP_TEMPLATES.PICKER.MEDIA_CONTENT', {
|
||||
@@ -149,32 +135,32 @@ export default {
|
||||
|
||||
<!-- Body -->
|
||||
<div>
|
||||
<p class="font-medium text-xs text-n-slate-11">
|
||||
<p class="text-xs font-medium text-n-slate-11">
|
||||
{{ $t('WHATSAPP_TEMPLATES.PICKER.BODY') || 'BODY' }}
|
||||
</p>
|
||||
<p class="label-body text-sm">{{ getTemplatebody(template) }}</p>
|
||||
<p class="text-sm label-body">{{ getTemplateBody(template) }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div v-if="getTemplateFooter(template)" class="mt-3">
|
||||
<p class="font-medium text-xs text-n-slate-11">
|
||||
<p class="text-xs font-medium text-n-slate-11">
|
||||
{{ $t('WHATSAPP_TEMPLATES.PICKER.FOOTER') || 'FOOTER' }}
|
||||
</p>
|
||||
<p class="label-body text-sm">
|
||||
<p class="text-sm label-body">
|
||||
{{ getTemplateFooter(template).text }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div v-if="getTemplateButtons(template)" class="mt-3">
|
||||
<p class="font-medium text-xs text-n-slate-11">
|
||||
<p class="text-xs font-medium text-n-slate-11">
|
||||
{{ $t('WHATSAPP_TEMPLATES.PICKER.BUTTONS') || 'BUTTONS' }}
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-1 mt-1">
|
||||
<span
|
||||
v-for="button in getTemplateButtons(template).buttons"
|
||||
:key="button.text"
|
||||
class="px-2 py-1 text-xs bg-n-slate-3 rounded text-n-slate-12"
|
||||
class="px-2 py-1 text-xs rounded bg-n-slate-3 text-n-slate-12"
|
||||
>
|
||||
{{ button.text }}
|
||||
</span>
|
||||
@@ -182,7 +168,7 @@ export default {
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<p class="font-medium text-xs text-n-slate-11">
|
||||
<p class="text-xs font-medium text-n-slate-11">
|
||||
{{ $t('WHATSAPP_TEMPLATES.PICKER.CATEGORY') || 'CATEGORY' }}
|
||||
</p>
|
||||
<p class="text-sm">{{ template.category }}</p>
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
"PICKER": {
|
||||
"SEARCH_PLACEHOLDER": "Search Templates",
|
||||
"NO_TEMPLATES_FOUND": "No templates found for",
|
||||
"HEADER": "Header",
|
||||
"BODY": "Body",
|
||||
"FOOTER": "Footer",
|
||||
"BUTTONS": "Buttons",
|
||||
"CATEGORY": "Category",
|
||||
"MEDIA_CONTENT": "Media Content",
|
||||
"LABELS": {
|
||||
"LANGUAGE": "Language",
|
||||
"TEMPLATE_BODY": "Template Body",
|
||||
|
||||
Reference in New Issue
Block a user