Spaces:
Runtime error
Runtime error
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
background-color: #eef1f5; | |
margin: 0; | |
padding: 0; | |
} | |
#chat-container { | |
max-width: 500px; | |
position: relative; | |
margin: auto; | |
padding: 20px; | |
border-radius: 30px; | |
background-color: #fafafa; | |
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); | |
} | |
#chat-history { | |
height: 530px; | |
overflow-y: auto; | |
margin-bottom: 10px; | |
padding: 10px; | |
background-color: #f9f9f9; | |
background: linear-gradient(135deg, #f0f4ff 0%, #ffd1d1 100%); | |
border-radius: 20px; | |
box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.1); | |
} | |
.message { | |
position: relative; | |
padding: 8px 12px; | |
margin: 5px 0; | |
border-radius: 20px; | |
max-width: 70%; | |
font-size: 0.85em; | |
cursor: pointer; | |
transition: background-color 0.3s; | |
} | |
.user-message { | |
background: linear-gradient(135deg, #d1ecf1 0%, #a8d8e0 100%); | |
color: #0c5460; | |
margin-left: auto; | |
border-radius: 15px 15px 0 15px; | |
} | |
.bot-message { | |
background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%); | |
color: #721c24; | |
margin-right: auto; | |
border-radius: 15px 15px 15px 0; | |
} | |
.user-icon, .bot-icon { | |
margin-right: 8px; | |
font-size: 1.1em; | |
} | |
#loading { | |
display: none; | |
margin: 10px 0; | |
text-align: center; | |
} | |
#user-input { | |
border: 1px solid #ccc; | |
border-radius: 5px; | |
resize: none; /* Prevents resizing */ | |
} | |
#user-input:focus { | |
border-color: #007bff; | |
outline: none; | |
} | |
.btn-icon { | |
background-color: #007bff; | |
color: white; | |
} | |
.btn-close { | |
position: absolute; /* Keep it absolute within the chat container */ | |
top: 10px; /* Adjust top position */ | |
right: 10px; /* Adjust left position */ | |
background-color: #dc3545; /* Red color for close button */ | |
color: white; | |
border: none; /* Remove border for a cleaner look */ | |
border-radius: 50%; /* Round shape */ | |
width: 30px; /* Set width */ | |
height: 30px; /* Set height */ | |
display: flex; /* Flexbox for centering icon */ | |
align-items: center; /* Center vertically */ | |
justify-content: center; /* Center horizontally */ | |
transition: background-color 0.3s; /* Add transition for hover effect */ | |
} | |
.btn-close:hover { | |
background-color: #c82333; /* Darker red on hover */ | |
} | |
.typing-indicator { | |
font-style: italic; | |
color: #aaa; | |
margin: 5px 0; | |
} | |
.timestamp { | |
font-size: 0.75em; | |
color: #aaa; | |
display: none; | |
margin-top: 5px; | |
} | |
</style> | |
<title>Chat Interface</title> | |
</head> | |
<body> | |
<div id="chat-container" class="rounded p-4 shadow"> | |
<input type="hidden" id="user-id" value="{{ user_id }}"> | |
<button id="close-button" class="btn btn-close" aria-label="Close chat"> | |
<i class="fas fa-arrow-left"></i> | |
</button> | |
<div id="chat-history" class="mb-3"></div> | |
<div id="loading" class="spinner-border text-primary" role="status"> | |
<span class="sr-only">Loading...</span> | |
</div> | |
<div class="input-group mb-2"> | |
<textarea id="user-input" class="form-control" rows="2" placeholder="Type your message..." aria-label="Message input"></textarea> | |
<div class="input-group-append"> | |
<button id="send-button" class="btn btn-icon" aria-label="Send message"> | |
<i class="fas fa-paper-plane"></i> | |
</button> | |
</div> | |
</div> | |
</div> | |
<script> | |
let chatHistoryArray = []; | |
document.getElementById("send-button").addEventListener("click", sendMessage); | |
document.getElementById("user-input").addEventListener("keypress", function(event) { | |
if (event.key === "Enter" && !event.shiftKey) { // Only send if Enter is pressed without Shift | |
event.preventDefault(); // Prevent default newline behavior | |
sendMessage(); | |
} | |
}); | |
document.getElementById("close-button").addEventListener("click", closeChat); | |
async function sendMessage() { | |
const input = document.getElementById("user-input"); | |
const userId = document.getElementById("user-id").value; | |
const message = input.value.trim(); | |
if (message === "") { | |
return; | |
} | |
addMessage("User", message, "user-message"); | |
chatHistoryArray.push({ userId, sender: "User", message }); | |
input.value = ""; | |
document.getElementById("loading").style.display = "block"; | |
showTypingIndicator(); | |
try { | |
const response = await fetch("/chat/", { | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json" | |
}, | |
body: JSON.stringify({ message }) | |
}); | |
if (!response.ok) { | |
throw new Error(`HTTP error! Status: ${response.status}`); | |
} | |
const data = await response.json(); | |
addMessage("Bot", data.response, "bot-message"); | |
chatHistoryArray.push({ userId, sender: "Bot", message: data.response }); | |
} catch (error) { | |
console.error('Error:', error); | |
addMessage("Bot", "Sorry, something went wrong.", "bot-message"); | |
} finally { | |
document.getElementById("loading").style.display = "none"; | |
hideTypingIndicator(); | |
} | |
} | |
async function closeChat() { | |
const userId = document.getElementById("user-id").value; | |
try { | |
await fetch("/hist/", { | |
method: "POST", | |
headers: { | |
"Content-Type": "application/json" | |
}, | |
body: JSON.stringify({ history: chatHistoryArray, userId }) | |
}); | |
} catch (error) { | |
console.error('Error sending chat history on close:', error); | |
} finally { | |
const chatContainer = document.getElementById("chat-container"); | |
window.top.location.href = 'https://redfernstech.com/chat-bot-test/'; // Or use chatContainer.remove(); to completely remove it | |
} | |
} | |
function addMessage(sender, message, className) { | |
const chatHistory = document.getElementById("chat-history"); | |
const messageElement = document.createElement("div"); | |
messageElement.className = `message ${className}`; | |
// Check if the message contains a URL | |
const linkRegex = /(https?:\/\/[^\s]+)/g; | |
const formattedMessage = message.replace(linkRegex, function(url) { | |
let linkText; | |
if (url === "https://appexchange.salesforce.com/appxListingDetail?listingId=cf4b19d4-8667-49f7-83b0-d2bc4032527b") { | |
linkText = "Visit this link to check out the Product Filter App."; | |
} else if (url === "https://appexchange.salesforce.com/appxListingDetail?listingId=e671f4fe-92fb-4760-99e5-7a5df5754cfe") { | |
linkText = "Visit this link to check out the Mass Approvals App."; | |
} else if (url === "https://appexchange.salesforce.com/appxListingDetail?listingId=3473ffd3-d530-462f-828f-d2c69f80d89d") { | |
linkText = "Visit this link to check out the Related Records App."; | |
} else { | |
linkText = url; | |
} | |
return `<a href="${url}" target="_blank">${linkText}</a>`; | |
}); | |
messageElement.innerHTML = `<span class="${sender.toLowerCase()}-icon">${sender === "User" ? '<i class="fas fa-user"></i>' : '<i class="fas fa-robot"></i>'}</span>${formattedMessage}<div class="timestamp">${new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</div>`; | |
chatHistory.appendChild(messageElement); | |
chatHistory.scrollTop = chatHistory.scrollHeight; // Scroll to bottom | |
} | |
function showTypingIndicator() { | |
const chatHistory = document.getElementById("chat-history"); | |
const typingIndicator = document.createElement("div"); | |
typingIndicator.className = "typing-indicator"; | |
typingIndicator.id = "typing-indicator"; | |
typingIndicator.innerText = "Bot is typing..."; | |
chatHistory.appendChild(typingIndicator); | |
chatHistory.scrollTop = chatHistory.scrollHeight; // Scroll to bottom | |
} | |
function hideTypingIndicator() { | |
const typingIndicator = document.getElementById("typing-indicator"); | |
if (typingIndicator) { | |
typingIndicator.remove(); | |
} | |
} | |
</script> | |
</body> | |
</html> | |