UNPKG

besper-frontend-site-dev-main

Version:

Professional B-esper Frontend Site - Site-wide integration toolkit for full website bot deployment

342 lines (300 loc) 8.81 kB
/** * Knowledge Panel Component * Displays information about the bot's knowledge base in the demo */ export class KnowledgePanel { constructor(apiEndpoint, botId) { this.apiEndpoint = apiEndpoint; this.botId = botId; this.knowledgeStats = null; } /** * Renders the knowledge panel HTML * @returns {string} Knowledge panel HTML */ render() { return ` <div class="knowledge-panel"> <div class="knowledge-panel-header"> <h3 class="knowledge-panel-title"> <i class="knowledge-icon">🧠</i> Knowledge Base </h3> <div class="knowledge-panel-status" id="knowledge-status"> <span class="status-indicator loading"></span> <span class="status-text">Loading...</span> </div> </div> <div class="knowledge-panel-content" id="knowledge-content"> <div class="knowledge-stats" id="knowledge-stats"> <!-- Stats will be populated dynamically --> </div> <div class="knowledge-capabilities"> <div class="besper-h4">What I can help with:</div> <ul class="capabilities-list"> <li><i class="cap-icon"></i> Answer questions about our products and services</li> <li><i class="cap-icon"></i> Provide detailed explanations and guides</li> <li><i class="cap-icon"></i> Help you find specific information quickly</li> <li><i class="cap-icon"></i> Suggest solutions to common problems</li> </ul> </div> <div class="knowledge-examples"> <div class="besper-h4">Try asking me:</div> <div class="example-questions"> <button class="example-btn" data-question="What are your main features?"> "What are your main features?" </button> <button class="example-btn" data-question="How do I get started?"> "How do I get started?" </button> <button class="example-btn" data-question="What's your pricing?"> "What's your pricing?" </button> </div> </div> </div> </div> `; } /** * Loads and displays knowledge base statistics */ async loadKnowledgeStats() { try { const statusEl = document.getElementById('knowledge-status'); const statsEl = document.getElementById('knowledge-stats'); if (statusEl) { statusEl.innerHTML = ` <span class="status-indicator loading"></span> <span class="status-text">Loading knowledge stats...</span> `; } // Simulate API call to get knowledge stats // In real implementation, this would fetch from the API await new Promise(resolve => setTimeout(resolve, 1000)); this.knowledgeStats = { documents: 150, webPages: 25, qaItems: 75, lastUpdated: new Date().toLocaleDateString(), }; if (statsEl) { statsEl.innerHTML = this.renderStats(); } if (statusEl) { statusEl.innerHTML = ` <span class="status-indicator active"></span> <span class="status-text">Knowledge base active</span> `; } } catch (error) { console.error('Error loading knowledge stats:', error); const statusEl = document.getElementById('knowledge-status'); if (statusEl) { statusEl.innerHTML = ` <span class="status-indicator error"></span> <span class="status-text">Error loading stats</span> `; } } } /** * Renders the knowledge statistics * @returns {string} Stats HTML */ renderStats() { if (!this.knowledgeStats) return ''; return ` <div class="stats-grid"> <div class="stat-item"> <div class="stat-number">${this.knowledgeStats.documents}</div> <div class="stat-label">Documents</div> </div> <div class="stat-item"> <div class="stat-number">${this.knowledgeStats.webPages}</div> <div class="stat-label">Web Pages</div> </div> <div class="stat-item"> <div class="stat-number">${this.knowledgeStats.qaItems}</div> <div class="stat-label">Q&A Items</div> </div> </div> <div class="last-updated"> Last updated: ${this.knowledgeStats.lastUpdated} </div> `; } /** * Gets the CSS styles for the knowledge panel * @returns {string} CSS styles */ getStyles() { return ` .knowledge-panel { background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 12px; padding: 1.5rem; margin-bottom: 2rem; } .knowledge-panel-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; padding-bottom: 1rem; border-bottom: 1px solid #e9ecef; } .knowledge-panel-title { margin: 0; font-size: 1.4rem; font-weight: 600; color: #2c3e50; display: flex; align-items: center; gap: 0.5rem; } .knowledge-icon { font-size: 1.5rem; } .knowledge-panel-status { display: flex; align-items: center; gap: 0.5rem; } .status-indicator { width: 10px; height: 10px; border-radius: 50%; display: inline-block; } .status-indicator.loading { background: #ffc107; animation: pulse 1.5s infinite; } .status-indicator.active { background: #28a745; } .status-indicator.error { background: #dc3545; } .status-text { font-size: 0.9rem; color: #6c757d; } .stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-bottom: 1rem; } .stat-item { text-align: center; padding: 1rem; background: white; border-radius: 8px; border: 1px solid #e9ecef; } .stat-number { font-size: 2rem; font-weight: 700; color: #007bff; margin-bottom: 0.5rem; } .stat-label { font-size: 0.9rem; color: #6c757d; font-weight: 500; } .last-updated { text-align: center; font-size: 0.85rem; color: #6c757d; font-style: italic; } .knowledge-capabilities, .knowledge-examples { margin-top: 1.5rem; } .knowledge-capabilities h4, .knowledge-examples h4 { margin: 0 0 1rem 0; font-size: 1.1rem; color: #2c3e50; } .capabilities-list { list-style: none; padding: 0; margin: 0; } .capabilities-list li { display: flex; align-items: center; gap: 0.75rem; padding: 0.5rem 0; font-size: 0.9rem; color: #495057; } .cap-icon { font-size: 1rem; } .example-questions { display: flex; flex-wrap: wrap; gap: 0.5rem; } .example-btn { background: #007bff; color: white; border: none; padding: 0.5rem 1rem; border-radius: 20px; font-size: 0.85rem; cursor: pointer; transition: all 0.3s ease; } .example-btn:hover { background: #0056b3; transform: translateY(-2px); } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } @media (max-width: 768px) { .stats-grid { grid-template-columns: 1fr; } .knowledge-panel-header { flex-direction: column; gap: 1rem; text-align: center; } } `; } /** * Sets up event listeners for the knowledge panel * @param {Function} onQuestionClick - Callback for when example question is clicked */ setupEventListeners(onQuestionClick) { // Example question buttons const exampleBtns = document.querySelectorAll('.example-btn'); exampleBtns.forEach(btn => { btn.addEventListener('click', () => { const question = btn.getAttribute('data-question'); if (onQuestionClick && question) { onQuestionClick(question); } }); }); } /** * Initializes the knowledge panel * @param {Function} onQuestionClick - Callback for when example question is clicked */ async init(onQuestionClick) { this.setupEventListeners(onQuestionClick); await this.loadKnowledgeStats(); } }