diff --git a/views/chat.ejs b/views/chat.ejs index 6b736b0..9a919f9 100644 --- a/views/chat.ejs +++ b/views/chat.ejs @@ -7,13 +7,14 @@ - <%= title %> | <%= process.env.OWNER_NAME %>'s' Blog + <%= title %> | <%= process.env.OWNER_NAME %>'s Blog - + @@ -29,7 +30,6 @@ margin: 0; padding: 0; overflow: hidden; - /* Prevent page scroll */ background-color: #121212; color: white; font-family: Arial, sans-serif; @@ -39,13 +39,6 @@ background-color: #121212 !important; } - textarea::placeholder { - color: #007bff; - /* Blue color to match the button */ - opacity: 0; - /* Ensures the placeholder text is fully opaque */ - } - .chat-container { display: flex; flex-direction: column; @@ -62,13 +55,11 @@ flex-grow: 1; background-color: #1e1e1e; overflow: hidden; - /* Ensures no overflow beyond screen */ } .messages { flex-grow: 1; overflow-y: auto; - /* Enable scrolling */ padding: 20px; background-color: #2e2e2e; border-radius: 5px; @@ -128,84 +119,12 @@ background-color: #555; } - .alert { - margin-top: 10px; - } - - /* Buttons side-by-side with sticky behavior */ .input-area { background-color: #1e1e1e; padding: 10px 20px; z-index: 10; flex-shrink: 0; color: white; - /* Prevents shrinking */ - } - - .alert { - margin-top: 10px; - text-align: center; - /* Center the text content */ - display: flex; - /* Make sure the alert is a flex container */ - justify-content: center; - /* Center flex items horizontally */ - align-items: center; - /* Center flex items vertically (if needed) */ - } - - /* WebKit-based browsers (Chrome, Safari, Edge) */ - .messages::-webkit-scrollbar { - width: 8px; - /* Make the scrollbar thin */ - } - - .messages::-webkit-scrollbar-track { - background: #2e2e2e; - /* Background color for the scrollbar track */ - } - - .messages::-webkit-scrollbar-thumb { - background-color: #007bff; - /* Blue color for the scrollbar */ - border-radius: 10px; - /* Rounded corners for the scrollbar thumb */ - border: 2px solid #2e2e2e; - /* Adds space around the thumb */ - } - - /* Firefox */ - .messages { - scrollbar-width: thin; - /* Make the scrollbar thin in Firefox */ - scrollbar-color: #007bff #2e2e2e; - /* Blue thumb with dark track */ - } - - - .input-area .btn-primary, - .input-area .btn-secondary { - width: 49%; - } - - .btn-primary { - background-color: #007bff; - border-color: #007bff; - } - - .btn-primary:hover { - background-color: #0056b3; - border-color: #0056b3; - } - - .btn-secondary { - background-color: #6c757d; - border-color: #6c757d; - } - - .btn-secondary:hover { - background-color: #5a6268; - border-color: #545b62; } .footer { @@ -214,16 +133,35 @@ padding: 10px; background-color: #121212; } - - - - - - - - - + .copy-button { + background-color: #444; + /* Button background color */ + color: white; + /* Button text color */ + border: none; + /* Remove border */ + cursor: pointer; + /* Pointer cursor for interaction */ + padding: 5px 10px; + /* Adjusted padding for smaller size */ + margin-top: 5px; + /* Space at the top */ + display: inline-block; + /* Keep the button in line */ + font-size: 14px; + /* Slightly smaller font size for compactness */ + width: 147px; + /* Prevent the button from stretching */ + text-align: left; + /* Align the text left */ + } + + .copy-button:hover { + background-color: #555; + /* Darker shade on hover */ + } + @@ -277,7 +215,6 @@ - @@ -367,6 +304,11 @@ addCopyButton(block); // Add copy button to code blocks } }); + + // Add "Copy Full Response" button after each assistant response + if (sender === 'assistant') { + addCopyFullResponseButton(messages, messageElement); + } } // Adds a copy button to a code block @@ -378,6 +320,16 @@ block.parentNode.appendChild(button); } + // Adds "Copy Full Response" button below the assistant response + function addCopyFullResponseButton(messagesContainer, messageElement) { + const copyFullResponseButton = document.createElement('button'); + copyFullResponseButton.classList.add('copy-button'); + copyFullResponseButton.textContent = 'Copy Full Response'; + copyFullResponseButton.addEventListener('click', () => copyFullResponse(messageElement)); + + messagesContainer.appendChild(copyFullResponseButton); + } + // Copies code block content to the clipboard function copyToClipboard(block) { const text = block.innerText; @@ -388,6 +340,33 @@ }); } + // Copies the full response content to the clipboard in Markdown format + function copyFullResponse(messageElement) { + const markdownContent = convertToMarkdown(messageElement); + navigator.clipboard.writeText(markdownContent).then(() => { + displayAlert('success', 'Full response copied to clipboard!'); + }).catch((err) => { + displayAlert('error', 'Failed to copy response: ' + err); + }); + } + + // Converts the HTML content of the response to Markdown + function convertToMarkdown(element) { + let markdown = ''; + const nodes = element.childNodes; + + nodes.forEach(node => { + if (node.nodeName === 'P') { + markdown += `${node.innerText}\n\n`; + } else if (node.nodeName === 'PRE') { + const codeBlock = node.querySelector('code').innerText; + markdown += `\`\`\`\n${codeBlock}\n\`\`\`\n\n`; + } + }); + + return markdown; + } + // Displays an alert message function displayAlert(type, message) { const alertElement = document.getElementById(`${type}-alert`); @@ -424,27 +403,23 @@ const response = await sendResetRequest(); if (response.ok) { - // Clear the messages in the UI const messagesContainer = document.getElementById('messages'); messagesContainer.innerHTML = ''; // Clear all messages - // Optionally display a success message if (displaySuccessMessage) { displayAlert('success', 'Messages Cleared!'); } } else { - // Handle error response from the server displayAlert('error', 'Failed to reset conversation. Please try again.'); } } catch (error) { - // Handle network or other errors displayAlert('error', 'An error occurred while resetting the conversation.'); } } // Resets the chat on page load without displaying the success message document.addEventListener('DOMContentLoaded', function () { - resetChat(false); // Call without displaying success message + resetChat(false); });