From ea944072aa61ff8e81f384da91437c4ac5ae0246 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 13 Jul 2025 23:08:05 +0530 Subject: [PATCH] Implement custom display functions for all agents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Overview Replace generic `AgentUtils.displayResults()` with specialized display functions for each agent to provide optimized content formatting and presentation. ## Changes Made ### Custom Display Functions Created - **Job Posting Generator**: Professional business formatting with structured headers - **Social Ads Generator**: Engaging ad copy styling with creative glassmorphism effects - **Weather Reporter**: Clean weather data presentation with metric highlighting - **Data Analyzer**: Already had custom function with rich analysis formatting ### Agent-Specific Features #### Job Posting Generator - Professional headers with border styling and proper hierarchy - Clean business formatting for requirements and responsibilities - Justified text alignment for formal presentation - Enhanced bold text for key information #### Social Ads Generator - Creative pink/purple theme matching creative agent styling - Eye-catching call-to-action highlighting with background effects - Sparkle emoji bullets for engaging list presentation - Glassmorphism wrapper effects for modern visual appeal #### Weather Reporter - Clean blue theme for weather data presentation - Temperature and metric highlighting with background colors - Organized weather sections with proper data structure - Subtle background styling for data containers ### Removed Generic Function - Removed `AgentUtils.displayResults()` from agent-utils.js - Added explanatory comment about custom display logic - Kept shared utilities: showToast, updateWalletBalance, etc. ## Benefits - **Specialized Content Handling**: Each agent optimizes its specific data structure - **Better User Experience**: Content formatted appropriately for each use case - **Enhanced Visual Appeal**: Custom styling matches each agent's theme and purpose - **Maintainability**: Agent-specific logic contained within each agent - **Performance**: No unnecessary generic field checking ## Technical Implementation - Custom content extraction with priority field ordering - Agent-specific markdown/text formatting functions - Proper error handling and wallet balance updates - Consistent success/error messaging patterns - Type-safe content handling with fallbacks ## Testing - All agent templates render successfully - Django project passes system checks - Custom display functions handle content extraction properly - Maintained compatibility with existing agent workflows 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../job_posting_generator/detail.html | 129 ++++++++++++++++-- .../social_ads_generator/detail.html | 129 ++++++++++++++++-- static/js/agent-utils.js | 39 +----- .../templates/weather_reporter/detail.html | 129 ++++++++++++++++-- 4 files changed, 361 insertions(+), 65 deletions(-) diff --git a/job_posting_generator/templates/job_posting_generator/detail.html b/job_posting_generator/templates/job_posting_generator/detail.html index bea1fe8..155cb0a 100644 --- a/job_posting_generator/templates/job_posting_generator/detail.html +++ b/job_posting_generator/templates/job_posting_generator/detail.html @@ -295,16 +295,127 @@ } - // Display job posting results with markdown formatting + // Display job posting results with professional formatting function displayResults(result) { - AgentUtils.displayResults({ - result: result, - resultsId: 'jobResults', - contentId: 'jobContent', - defaultMessage: 'Job posting generated successfully!', - successMessage: '✅ Job posting created and payment processed!', - errorMessage: '❌ Failed to generate job posting - no charge applied' - }); + const resultsContainer = document.getElementById('jobResults'); + const contentElement = document.getElementById('jobContent'); + + if (!resultsContainer || !contentElement) { + console.error('Job results elements not found'); + return; + } + + // Update wallet balance if provided + if (result.wallet_balance !== undefined) { + updateWalletBalance(result.wallet_balance); + } + + // Handle errors + if (result.error) { + AgentUtils.showToast(`❌ ${result.error}`, 'error'); + return; + } + + // Handle failed status + if (result.status === 'failed') { + AgentUtils.showToast('❌ Failed to generate job posting - no charge applied', 'error'); + return; + } + + // Extract job posting content with priority order + let content = ''; + + if (result.job_posting_content && typeof result.job_posting_content === 'string') { + content = result.job_posting_content; + } else if (result.content && typeof result.content === 'string') { + content = result.content; + } else if (result.formatted_report && typeof result.formatted_report === 'string') { + content = result.formatted_report; + } else if (result.output_text && typeof result.output_text === 'string') { + content = result.output_text; + } else { + content = 'Job posting generated successfully!'; + } + + // Format job posting content with professional styling + const formattedContent = formatJobPostingContent(content); + + // Update content + contentElement.innerHTML = formattedContent; + + // Show results + resultsContainer.style.display = 'block'; + resultsContainer.scrollIntoView({ behavior: 'smooth' }); + + // Show success message + const successMessage = result.success ? '✅ Job posting created and payment processed!' : '✅ Job posting generated!'; + AgentUtils.showToast(successMessage, 'success'); + } + + // Professional job posting formatter + function formatJobPostingContent(content) { + if (!content || typeof content !== 'string') { + return '

No job posting content available.

'; + } + + let html = content; + + // Enhanced header formatting for job titles and company names + html = html.replace(/^# (.*$)/gm, '

$1

'); + html = html.replace(/^## (.*$)/gm, '

$1

'); + html = html.replace(/^### (.*$)/gm, '

$1

'); + + // Professional bold text formatting + html = html.replace(/\*\*(.*?)\*\*/g, '$1'); + + // Professional bullet point formatting + const lines = html.split('\n'); + let inList = false; + let processedLines = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + + if (line.startsWith('- ') || line.startsWith('• ')) { + if (!inList) { + processedLines.push(''); + inList = false; + } + processedLines.push(line); + } + } + + if (inList) { + processedLines.push(''); + } + + html = processedLines.join('\n'); + + // Convert line breaks to professional paragraphs + const paragraphs = html.split(/\n\s*\n/); + html = paragraphs + .filter(p => p.trim() !== '') + .map(p => { + const trimmed = p.trim(); + // Don't wrap headers or lists in paragraphs + if (trimmed.startsWith('') || trimmed.includes('${trimmed}

`; + }) + .join(''); + + // Add professional spacing and structure + html = `
${html}
`; + + return html; } // Track if results have been displayed to prevent duplicates diff --git a/social_ads_generator/templates/social_ads_generator/detail.html b/social_ads_generator/templates/social_ads_generator/detail.html index b7182e0..2da3cf9 100644 --- a/social_ads_generator/templates/social_ads_generator/detail.html +++ b/social_ads_generator/templates/social_ads_generator/detail.html @@ -199,16 +199,127 @@ AgentUtils.showToast('Form reset! Ready for another ad campaign.', 'success'); } - // Display social ads results with markdown parsing + // Display social ads results with engaging ad copy formatting function displayResults(result) { - AgentUtils.displayResults({ - result: result, - resultsId: 'adResults', - contentId: 'adContent', - defaultMessage: 'Social ads generated successfully!', - successMessage: '✅ Social ads created and payment processed!', - errorMessage: '❌ Failed to generate ads - no charge applied' - }); + const resultsContainer = document.getElementById('adResults'); + const contentElement = document.getElementById('adContent'); + + if (!resultsContainer || !contentElement) { + console.error('Ad results elements not found'); + return; + } + + // Update wallet balance if provided + if (result.wallet_balance !== undefined) { + updateWalletBalance(result.wallet_balance); + } + + // Handle errors + if (result.error) { + AgentUtils.showToast(`❌ ${result.error}`, 'error'); + return; + } + + // Handle failed status + if (result.status === 'failed') { + AgentUtils.showToast('❌ Failed to generate ads - no charge applied', 'error'); + return; + } + + // Extract ad copy content with priority order + let content = ''; + + if (result.ad_copy_content && typeof result.ad_copy_content === 'string') { + content = result.ad_copy_content; + } else if (result.content && typeof result.content === 'string') { + content = result.content; + } else if (result.formatted_report && typeof result.formatted_report === 'string') { + content = result.formatted_report; + } else if (result.output_text && typeof result.output_text === 'string') { + content = result.output_text; + } else { + content = 'Social ads generated successfully!'; + } + + // Format ad copy content with engaging styling + const formattedContent = formatSocialAdContent(content); + + // Update content + contentElement.innerHTML = formattedContent; + + // Show results + resultsContainer.style.display = 'block'; + resultsContainer.scrollIntoView({ behavior: 'smooth' }); + + // Show success message + const successMessage = result.success ? '✅ Social ads created and payment processed!' : '✅ Social ads generated!'; + AgentUtils.showToast(successMessage, 'success'); + } + + // Engaging social ad copy formatter + function formatSocialAdContent(content) { + if (!content || typeof content !== 'string') { + return '

No ad content available.

'; + } + + let html = content; + + // Enhanced header formatting for ad titles and platform sections + html = html.replace(/^# (.*$)/gm, '

$1

'); + html = html.replace(/^## (.*$)/gm, '

$1

'); + html = html.replace(/^### (.*$)/gm, '

$1

'); + + // Eye-catching bold text for call-to-actions and key phrases + html = html.replace(/\*\*(.*?)\*\*/g, '$1'); + + // Engaging bullet point formatting for ad features + const lines = html.split('\n'); + let inList = false; + let processedLines = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + + if (line.startsWith('- ') || line.startsWith('• ')) { + if (!inList) { + processedLines.push('
    '); + inList = true; + } + const listContent = line.substring(2).trim(); + processedLines.push(`
  • ${listContent}
  • `); + } else { + if (inList) { + processedLines.push('
'); + inList = false; + } + processedLines.push(line); + } + } + + if (inList) { + processedLines.push(''); + } + + html = processedLines.join('\n'); + + // Convert line breaks to engaging paragraphs + const paragraphs = html.split(/\n\s*\n/); + html = paragraphs + .filter(p => p.trim() !== '') + .map(p => { + const trimmed = p.trim(); + // Don't wrap headers or lists in paragraphs + if (trimmed.startsWith('') || trimmed.includes('${trimmed}

`; + }) + .join(''); + + // Add creative wrapper with glassmorphism effect + html = `
${html}
`; + + return html; } // Track polling and results to prevent duplicates diff --git a/static/js/agent-utils.js b/static/js/agent-utils.js index f532c96..2f5bbb8 100644 --- a/static/js/agent-utils.js +++ b/static/js/agent-utils.js @@ -173,44 +173,7 @@ window.AgentUtils = { }, 2000); }, - /** - * Display results with markdown parsing - * Standardized across all agents - */ - displayResults(config) { - const resultsContainer = document.getElementById(config.resultsId); - const contentContainer = document.getElementById(config.contentId); - - if (config.result.success && config.result.status === 'completed') { - // Get content from various possible fields - const content = config.result.content || - config.result.job_posting_content || - config.result.ad_copy_content || - config.result.analysis_results || - config.result.insights_summary || - config.result.report_text || - config.result.weather_data || - config.result.formatted_report || - config.result.output_text || - config.defaultMessage || - 'Content generated successfully!'; - - // Parse markdown and display as HTML - const formattedContent = this.parseMarkdown(content); - contentContainer.innerHTML = formattedContent; - - resultsContainer.style.display = 'block'; - - // Update wallet balance if provided - if (config.result.wallet_balance !== undefined) { - this.updateWalletBalance(config.result.wallet_balance); - } - - this.showToast(config.successMessage || '✅ Content generated and payment processed!', 'success'); - } else { - this.showToast(config.errorMessage || '❌ Failed to generate content - no charge applied', 'error'); - } - }, + // NOTE: displayResults() function removed - each agent now has its own custom display logic /** * Generate text for copy/download functionality diff --git a/weather_reporter/templates/weather_reporter/detail.html b/weather_reporter/templates/weather_reporter/detail.html index 264f9e7..0c926a5 100644 --- a/weather_reporter/templates/weather_reporter/detail.html +++ b/weather_reporter/templates/weather_reporter/detail.html @@ -259,16 +259,127 @@ // Simple toast notification - // Display weather results with markdown parsing + // Display weather results with clean weather data formatting function displayResults(result) { - AgentUtils.displayResults({ - result: result, - resultsId: 'weatherResults', - contentId: 'weatherContent', - defaultMessage: 'Weather report generated successfully!', - successMessage: '✅ Weather report completed and payment processed!', - errorMessage: '❌ Failed to generate weather report - no charge applied' - }); + const resultsContainer = document.getElementById('weatherResults'); + const contentElement = document.getElementById('weatherContent'); + + if (!resultsContainer || !contentElement) { + console.error('Weather results elements not found'); + return; + } + + // Update wallet balance if provided + if (result.wallet_balance !== undefined) { + updateWalletBalance(result.wallet_balance); + } + + // Handle errors + if (result.error) { + AgentUtils.showToast(`❌ ${result.error}`, 'error'); + return; + } + + // Handle failed status + if (result.status === 'failed') { + AgentUtils.showToast('❌ Failed to generate weather report - no charge applied', 'error'); + return; + } + + // Extract weather content with priority order + let content = ''; + + if (result.weather_data && typeof result.weather_data === 'string') { + content = result.weather_data; + } else if (result.formatted_report && typeof result.formatted_report === 'string') { + content = result.formatted_report; + } else if (result.content && typeof result.content === 'string') { + content = result.content; + } else if (result.output_text && typeof result.output_text === 'string') { + content = result.output_text; + } else { + content = 'Weather report generated successfully!'; + } + + // Format weather content with clean data presentation + const formattedContent = formatWeatherContent(content); + + // Update content + contentElement.innerHTML = formattedContent; + + // Show results + resultsContainer.style.display = 'block'; + resultsContainer.scrollIntoView({ behavior: 'smooth' }); + + // Show success message + const successMessage = result.success ? '✅ Weather report completed and payment processed!' : '✅ Weather report generated!'; + AgentUtils.showToast(successMessage, 'success'); + } + + // Clean weather data formatter + function formatWeatherContent(content) { + if (!content || typeof content !== 'string') { + return '

No weather data available.

'; + } + + let html = content; + + // Enhanced header formatting for weather sections + html = html.replace(/^# (.*$)/gm, '

$1

'); + html = html.replace(/^## (.*$)/gm, '

$1

'); + html = html.replace(/^### (.*$)/gm, '

$1

'); + + // Temperature and weather metric highlighting + html = html.replace(/\*\*(.*?)\*\*/g, '$1'); + + // Weather condition formatting with clean presentation + const lines = html.split('\n'); + let inList = false; + let processedLines = []; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + + if (line.startsWith('- ') || line.startsWith('• ')) { + if (!inList) { + processedLines.push('
    '); + inList = true; + } + const listContent = line.substring(2).trim(); + processedLines.push(`
  • ${listContent}
  • `); + } else { + if (inList) { + processedLines.push('
'); + inList = false; + } + processedLines.push(line); + } + } + + if (inList) { + processedLines.push(''); + } + + html = processedLines.join('\n'); + + // Convert line breaks to clean paragraphs + const paragraphs = html.split(/\n\s*\n/); + html = paragraphs + .filter(p => p.trim() !== '') + .map(p => { + const trimmed = p.trim(); + // Don't wrap headers or lists in paragraphs + if (trimmed.startsWith('') || trimmed.includes('${trimmed}

`; + }) + .join(''); + + // Add clean wrapper for weather data + html = `
${html}
`; + + return html; } // Poll for results