Skip to main content
Glama
ui-generation.ts6.61 kB
/** * UI Generation Helper Functions * * Utilities for generating dashboard HTML and remote DOM scripts */ /** * Generate dashboard HTML content */ export function generateDashboardHTML(options: { title: string; visualizationType: string; data: any; panels: any[]; layout: string; interactive: boolean; }): string { const { title, visualizationType, data, panels, layout, interactive } = options; // Generate HTML with embedded Chart.js or D3.js visualization const chartScript = visualizationType === "chart" ? ` <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> const ctx = document.getElementById('mainChart').getContext('2d'); const chart = new Chart(ctx, { type: '${data.chartType || "bar"}', data: ${JSON.stringify(data.chartData || { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], datasets: [{ label: 'Dataset', data: [12, 19, 3, 5, 2], backgroundColor: 'rgba(75, 192, 192, 0.2)', borderColor: 'rgba(75, 192, 192, 1)', borderWidth: 1 }] })}, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true }, tooltip: { enabled: ${interactive} } } } }); </script> ` : ""; const panelsHTML = panels.map((panel, index) => ` <div class="panel" style=" padding: 15px; margin: 10px; border: 1px solid #ddd; border-radius: 8px; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1); "> <h3>${panel.title || `Panel ${index + 1}`}</h3> <div class="panel-content"> ${panel.content || `<p>Panel content for ${panel.type || 'metric'}</p>`} ${panel.value ? `<div class="metric-value" style="font-size: 2em; font-weight: bold; color: #2196F3;">${panel.value}</div>` : ''} </div> </div> `).join(''); return ` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>${title}</title> <style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 20px; background: #f5f5f5; } .dashboard { max-width: 1200px; margin: 0 auto; } .header { background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .panels-container { display: ${layout === 'grid' ? 'grid' : 'flex'}; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; flex-wrap: ${layout === 'flex' ? 'wrap' : 'nowrap'}; } .chart-container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); height: 400px; margin-bottom: 20px; } canvas { width: 100% !important; height: 100% !important; } </style> </head> <body> <div class="dashboard"> <div class="header"> <h1>${title}</h1> <p>Interactive Dashboard - ${new Date().toLocaleString()}</p> </div> ${visualizationType === 'chart' ? ` <div class="chart-container"> <canvas id="mainChart"></canvas> </div> ` : ''} <div class="panels-container"> ${panelsHTML} </div> </div> ${chartScript} ${interactive ? ` <script> // Enable interactive features window.parent.postMessage({ type: 'ui-lifecycle-iframe-ready', payload: { ready: true } }, '*'); // Handle clicks on panels document.querySelectorAll('.panel').forEach((panel, index) => { panel.style.cursor = 'pointer'; panel.addEventListener('click', () => { window.parent.postMessage({ type: 'notify', payload: { message: 'Panel ' + (index + 1) + ' clicked' } }, '*'); }); }); </script> ` : ''} </body> </html> `; } /** * Generate remote DOM script for dynamic content */ export function generateRemoteDomScript(options: { visualizationType: string; data: any; panels: any[]; interactive: boolean; }): string { const { visualizationType, data, panels, interactive } = options; return ` // Create dashboard container const container = document.createElement('ui-container'); container.style.padding = '20px'; // Add title const title = document.createElement('ui-text'); title.textContent = 'Dynamic Dashboard'; title.style.fontSize = '24px'; title.style.fontWeight = 'bold'; title.style.marginBottom = '20px'; container.appendChild(title); // Add panels ${panels.map((panel, index) => ` const panel${index} = document.createElement('ui-panel'); panel${index}.style.padding = '15px'; panel${index}.style.margin = '10px'; panel${index}.style.border = '1px solid #ddd'; panel${index}.style.borderRadius = '8px'; const panelTitle${index} = document.createElement('ui-text'); panelTitle${index}.textContent = '${panel.title || `Panel ${index + 1}`}'; panelTitle${index}.style.fontWeight = 'bold'; panel${index}.appendChild(panelTitle${index}); ${panel.value ? ` const panelValue${index} = document.createElement('ui-text'); panelValue${index}.textContent = '${panel.value}'; panelValue${index}.style.fontSize = '2em'; panelValue${index}.style.color = '#2196F3'; panel${index}.appendChild(panelValue${index}); ` : ''} ${interactive ? ` panel${index}.style.cursor = 'pointer'; panel${index}.onclick = () => { window.parent.postMessage({ type: 'tool', payload: { toolName: 'handlePanelClick', params: { panelId: ${index} } } }, '*'); }; ` : ''} container.appendChild(panel${index}); `).join('\n')} // Append to root root.appendChild(container); // Send ready signal window.parent.postMessage({ type: 'ui-lifecycle-iframe-ready', payload: { ready: true } }, '*'); `; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/waldzellai/clearthought-onepointfive'

If you have feedback or need assistance with the MCP directory API, please join our Discord server