feat: Add media URL input support for WhatsApp templates
Add support for media URL input fields in WhatsApp templates with IMAGE, VIDEO, or DOCUMENT headers, enabling users to provide media links for template messages. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+59
-7
@@ -116,13 +116,25 @@ const generateVariables = () => {
|
||||
});
|
||||
|
||||
// Process header variables
|
||||
if (headerComponent.value?.text) {
|
||||
const headerVars = headerComponent.value.text.match(/{{([^}]+)}}/g) || [];
|
||||
headerVars.forEach(variable => {
|
||||
const key = processVariable(variable);
|
||||
if (headerComponent.value) {
|
||||
if (headerComponent.value.text) {
|
||||
// Text headers with variables
|
||||
const headerVars = headerComponent.value.text.match(/{{([^}]+)}}/g) || [];
|
||||
headerVars.forEach(variable => {
|
||||
const key = processVariable(variable);
|
||||
if (!allVariables.header) allVariables.header = {};
|
||||
allVariables.header[key] = '';
|
||||
});
|
||||
} else if (
|
||||
headerComponent.value.format &&
|
||||
['IMAGE', 'VIDEO', 'DOCUMENT'].includes(headerComponent.value.format)
|
||||
) {
|
||||
// Media headers need URL input
|
||||
if (!allVariables.header) allVariables.header = {};
|
||||
allVariables.header[key] = '';
|
||||
});
|
||||
allVariables.header.media_url = '';
|
||||
allVariables.header.media_type =
|
||||
headerComponent.value.format.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
// Process footer variables
|
||||
@@ -177,6 +189,44 @@ const validateButtonParameter = (button, index) => {
|
||||
}
|
||||
};
|
||||
|
||||
const getHeaderFieldLabel = key => {
|
||||
if (key === 'media_url') {
|
||||
const mediaType = processedParams.value.header?.media_type || 'media';
|
||||
return (
|
||||
t('WHATSAPP_TEMPLATES.PARSER.MEDIA_URL', {
|
||||
type: mediaType.toUpperCase(),
|
||||
}) || `${mediaType.toUpperCase()} URL`
|
||||
);
|
||||
}
|
||||
return key;
|
||||
};
|
||||
|
||||
const getHeaderFieldPlaceholder = key => {
|
||||
if (key === 'media_url') {
|
||||
const mediaType = processedParams.value.header?.media_type || 'media';
|
||||
switch (mediaType) {
|
||||
case 'image':
|
||||
return (
|
||||
t('WHATSAPP_TEMPLATES.PARSER.IMAGE_URL_PLACEHOLDER') ||
|
||||
'Enter image URL (https://example.com/image.jpg)'
|
||||
);
|
||||
case 'video':
|
||||
return (
|
||||
t('WHATSAPP_TEMPLATES.PARSER.VIDEO_URL_PLACEHOLDER') ||
|
||||
'Enter video URL (https://example.com/video.mp4)'
|
||||
);
|
||||
case 'document':
|
||||
return (
|
||||
t('WHATSAPP_TEMPLATES.PARSER.DOCUMENT_URL_PLACEHOLDER') ||
|
||||
'Enter document URL (https://example.com/document.pdf)'
|
||||
);
|
||||
default:
|
||||
return 'Enter media URL';
|
||||
}
|
||||
}
|
||||
return `Enter ${key} value`;
|
||||
};
|
||||
|
||||
const sendMessage = async () => {
|
||||
const isValid = await v$.value.$validate();
|
||||
if (!isValid) return;
|
||||
@@ -243,13 +293,15 @@ onMounted(() => {
|
||||
<span
|
||||
class="flex items-center h-8 text-sm min-w-6 ltr:text-left rtl:text-right text-n-slate-10"
|
||||
>
|
||||
{{ key }}
|
||||
{{ 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>
|
||||
|
||||
@@ -96,8 +96,16 @@ class Whatsapp::TemplateProcessorService
|
||||
|
||||
# Process header parameters
|
||||
if processed_params['header'].present?
|
||||
header_params = processed_params['header'].map { |_, value| build_parameter(value) }
|
||||
components << { type: 'header', parameters: header_params }
|
||||
header_params = processed_params['header'].filter_map do |key, value|
|
||||
if key == 'media_url' && processed_params['header']['media_type'].present?
|
||||
build_media_parameter(value, processed_params['header']['media_type'])
|
||||
else
|
||||
build_parameter(value)
|
||||
end
|
||||
end
|
||||
|
||||
# Only add header component if we have valid parameters
|
||||
components << { type: 'header', parameters: header_params } if header_params.present?
|
||||
end
|
||||
|
||||
# Process footer parameters (rarely used but supported)
|
||||
@@ -216,6 +224,39 @@ class Whatsapp::TemplateProcessorService
|
||||
raise ArgumentError, 'Invalid URL format'
|
||||
end
|
||||
|
||||
def build_media_parameter(url, media_type)
|
||||
return nil if url.blank?
|
||||
|
||||
sanitized_url = sanitize_parameter(url)
|
||||
validate_url(sanitized_url)
|
||||
|
||||
case media_type.downcase
|
||||
when 'image'
|
||||
{
|
||||
type: 'image',
|
||||
image: {
|
||||
link: sanitized_url
|
||||
}
|
||||
}
|
||||
when 'video'
|
||||
{
|
||||
type: 'video',
|
||||
video: {
|
||||
link: sanitized_url
|
||||
}
|
||||
}
|
||||
when 'document'
|
||||
{
|
||||
type: 'document',
|
||||
document: {
|
||||
link: sanitized_url
|
||||
}
|
||||
}
|
||||
else
|
||||
raise ArgumentError, "Unsupported media type: #{media_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def validated_body_object(template)
|
||||
# we don't care if its not approved template
|
||||
return if template['status'] != 'approved'
|
||||
|
||||
Reference in New Issue
Block a user