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
JavaScript
/**
* 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();
}
}