opencompletion.com/templates/base.html
Russell Ballestrini 381588d6bc mistral upgrades
modified:   README.rst
	modified:   app.py
	modified:   templates/base.html
	modified:   templates/chat.html
2025-02-08 16:03:22 -05:00

426 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Chatroom{% endblock %}</title>
<!-- Include highlight.js library for syntax highlighting -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
<!-- Include a highlight.js theme (replace 'default' with your preferred theme) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/default.min.css">
<!-- Include socket.io for real-time bidirectional event-based communication -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script>
<!-- Include marked.js for markdown parsing -->
<script
src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.2/marked.min.js"
integrity="sha512-rfX4p3RNnxdwLT3wWP1K0NR3ztTobn+sISlT9WhxDDK00zNYbQ6MCHA5OHm0hqKAzEMXYCgFrp8iY/ER5MkXqA=="
crossorigin="anonymous"
referrerpolicy="no-referrer">
</script>
<!-- Include DOMPurify to sanitize HTML and prevent XSS attacks -->
<script src="https://cdn.jsdelivr.net/npm/dompurify@2/dist/purify.min.js"></script>
<script>
// Connect to the server using socket.io
const socket = io.connect(window.location.protocol + "//" + document.domain + ":" + location.port);
</script>
<!-- Link to the favicon -->
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
<style>
/* Basic styling for the chat application */
html, body {
height: 100%;
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background-color: #f7f7f7;
display: grid;
place-items: center;
overflow: hidden; /* Prevent scrolling of the main viewport */
}
/* Styling for the chat container */
#chat-container {
display: grid;
grid-template-rows: 1fr auto;
width: 100%;
height: 90vh;
background-color: #ffffff;
border-radius: 5px;
padding: 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
box-sizing: border-box;
}
/* Styling for the chat area */
#chat {
overflow-y: auto;
border: 1px solid #e1e1e1;
border-radius: 5px;
padding-left: 10px;
margin-bottom: 10px;
width: 100%; /* Allow chat window to fill available space */
}
/* Styling for the message input area */
#message, .message-edit {
width: 100%;
border: 1px solid #e1e1e1;
border-radius: 5px;
padding: 5px;
display: block;
}
/* Styling for the message div holding html/markdown content */
.message-content {
width: 100%;
}
/* Styling for individual message wrappers */
.message-wrapper {
display: grid;
grid-template-columns: auto 1fr;
align-items: start;
gap: 4px;
margin-bottom: 32px;
}
/* Styling for the delete and edit buttons next to messages */
.message-wrapper button {
margin-right: 4px;
margin-bottom: 4px;
}
/* Styling for the button container within each message */
.button-container {
display: grid;
grid-auto-rows: min-content; /* Ensure each button takes up only as much space as it needs */
gap: 4px; /* Vertical space between buttons */
}
/* Styling for paragraphs, used for messages */
p {
margin: 0;
margin-bottom: 12px;
}
/* Styling for the main container that holds the rooms list and chat */
.main-container {
display: grid;
grid-template-columns: 15% 70% 15%;
width: 100%;
height: 90vh;
}
/* Styling for the rooms list */
#rooms-list {
border-right: 1px solid #e1e1e1;
overflow-y: auto;
}
/* Styling for the unordered list in the rooms list */
#rooms-list ul, #rooms-list-modal-content ul {
list-style: none; /* Removes default list styling */
padding: 0; /* Resets default padding */
margin: 0; /* Resets default margin */
}
/* Styling for list items in the rooms list */
#rooms-list li {
margin-bottom: 10px; /* Adds space between items */
padding: 5px; /* Adds padding inside each item */
border: 1px solid #e1e1e1; /* Adds a border around each item */
border-radius: 5px; /* Optional: Rounds the corners of the border */
}
/* Styling for links in the rooms list */
#rooms-list a {
text-decoration: none; /* Optional: Removes underline from links */
color: inherit; /* Optional: Ensures link color matches the text color */
}
.hljs {
position: relative;
padding-left: 46px !important;
counter-reset: line;
}
.hljs .line-numbers-rows {
position: absolute;
top: 0;
left: 0;
width: 3em; /* Adjust the width as needed */
letter-spacing: -1px;
border-right: 1px solid #ccc; /* Optional: adds a line to separate numbers */
text-align: right;
margin-top: 14px; /* Align with the code block */
color: #999;
pointer-events: none;
}
.hljs .line-numbers-rows span {
display: block;
counter-increment: line;
}
.hljs .line-numbers-rows span::before {
content: counter(line);
display: block;
padding-right: 0.8em; /* Adjust the padding as needed */
}
.download-links {
text-align: center;
}
/* Hamburger button styling */
#hamburger-button {
display: none; /* Hidden by default */
position: fixed;
top: 20px;
left: 20px;
background-color: #333;
color: white;
border: none;
border-radius: 5px;
padding: 10px;
cursor: pointer;
z-index: 1001;
}
/* Modal styling */
#room-list-modal {
display: none; /* Hidden by default */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1002;
justify-content: center;
align-items: center;
}
#room-list-modal-content {
display: none; /* Hidden by default */
background-color: white;
padding: 20px;
border-radius: 5px;
width: 80%;
max-width: 400px;
max-height: 80vh;
overflow-y: auto; /* Make the room list scrollable */
position: relative;
}
/* Close button styling */
#close-modal-button {
display: none; /* Hidden by default */
position: fixed;
top: 10px;
right: 10px;
background-color: #333;
color: white;
border: none;
border-radius: 5px;
font-size: 20px;
cursor: pointer;
z-index: 1003; /* Ensure it is above the modal content */
padding: 5px 10px; /* Add padding for a button-like appearance */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* Add a shadow for depth */
transition: background-color 0.3s; /* Smooth transition for hover effect */
}
#close-modal-button:hover {
background-color: #555; /* Darken on hover */
}
.utility-belt {
padding: 10px;
}
/* Media query for mobile devices */
@media (max-width: 768px) {
.main-container {
grid-template-columns: 1fr; /* Single column layout */
}
#rooms-list {
display: none; /* Hide the room list on mobile */
}
#hamburger-button {
display: block; /* Show the hamburger button on mobile */
}
}
</style>
</head>
<body>
<a href="https://github.com/russellballestrini/opencompletion#interacting-with-language-models" target="_blank">🚀 docs for models & other commands, also try /help</a>
<!-- Search form -->
<div id="search-form" style="width: 90%;">
<form action="/search" method="get">
<input type="text" id="search-keywords" name="keywords" placeholder="Search for keywords..." style="width: 100%; text-align: center;" value="{{ keywords }}">
<input type="hidden" id="username" name="username" value="{{ username }}">
</form>
</div>
<!-- Hamburger button for mobile -->
<button id="hamburger-button"></button>
<!-- Modal for room list and utility belt -->
<div id="room-list-modal">
<div id="room-list-modal-content">
<button id="close-modal-button" onclick="closeModal()">×</button>
<div id="utility-belt-mobile">
<div id="model-chooser-mobile">
<label for="model-select-mobile">Choose Model:</label>
<select id="model-select-mobile">
<option value="None">None</option>
<option value="vllm/r1">vllm/r1</option>
<option value="vllm/hermes">vllm/hermes</option>
<option value="vllm/qwq">vllm/qwq</option>
<option value="ollama/qwen-coder">ollama/qwen-coder</option>
<option value="ollama/deepseek-coder">ollama/deepseek-coder</option>
<option value="mistral-tiny">mistral-tiny</option>
<option value="mistral-small">mistral-small</option>
<option value="mistral-medium">mistral-medium</option>
<option value="mistral-large">mistral-large</option>
<option value="mistral-codestral">mistral-codestral</option>
<option value="gemini-flash">gemini-flash</option>
<option value="gemini-flash-8b">gemini-flash-8b</option>
<option value="gemini-pro">gemini-pro</option>
<option value="grok-beta">grok-beta</option>
<option value="gpt-4">gpt-4</option>
<option value="gpt-4o-2024-08-06">gpt-4o-2024-08-06</option>
<option value="gpt-mini">gpt-mini</option>
<option value="gpt-o1-mini">gpt-o1-mini</option>
<option value="gpt-o1-preview">gpt-o1-preview</option>
<option value="gpt-o1">gpt-o1</option>
<option value="gpt-o3-mini">gpt-o3-mini</option>
<!--
<option value="gpt-o3-mini-medium">gpt-o3-mini-medium</option>
<option value="gpt-o3-mini-high">gpt-o3-mini-high</option>
-->
<option value="claude-haiku">claude-haiku</option>
<option value="claude-sonnet">claude-sonnet</option>
<option value="claude-opus">claude-opus</option>
</select>
</div>
<div id="voice-chooser-mobile">
<label for="voice-select-mobile">Choose Voice:</label>
<select id="voice-select-mobile">
<option value="onyx">Onyx</option>
<option value="alloy">Alloy</option>
<option value="echo">Echo</option>
<option value="fable">Fable</option>
<option value="nova">Nova</option>
<option value="shimmer">Shimmer</option>
</select>
</div>
<div id="user-lists-mobile">
<div id="active-users-list">
<h3>Active Users</h3>
<ul id="active-users-mobile">
<!-- Active users will be dynamically populated here -->
</ul>
</div>
<div id="inactive-users-list">
<h3>Inactive Users</h3>
<ul id="inactive-users-mobile">
<!-- Inactive users will be dynamically populated here -->
</ul>
</div>
</div>
</div>
<div id="rooms-list-modal-content">
<!-- Room list will be cloned here for mobile view -->
</div>
</div>
</div>
<!-- Chatroom list -->
<div class="main-container">
<div id="rooms-list">
<ul id="rooms-list-ul">
<!-- Loop through rooms and create list items for each room -->
{% for room in rooms %}
<a href="{{ url_for('chat', room_name=room.name) }}?{{ request.query_string.decode('utf-8')|safe }}">
<li data-room-id="{{ room.id }}">
<!-- Display the room title if available, otherwise the room name -->
<b>{{ room.name }}</b>
{% if room.title %}
<br />{{ room.title }}
{% endif %}
{% if room.get_active_users()|length %}
<br /> {{ room.get_active_users()|length }} users
{% endif %}
</li>
</a>
{% endfor %}
</ul>
</div>
{% block content %}{% endblock %}
</div>
<script>
// Function to perform the search
function performSearch() {
const keywords = document.getElementById("search-keywords").value;
const username = document.getElementById("username").value;
if (!keywords) {
alert("Please enter keywords to search.");
return;
}
// Navigate to the search results page with the keywords as a query parameter
window.location.href = `/search?keywords=${encodeURIComponent(keywords)}&username=${username}`;
}
// Add event listener for keyword search the "Enter" key
document.getElementById("search-keywords").addEventListener("keydown", function(event) {
if (event.key === "Enter") {
event.preventDefault();
performSearch();
}
});
// Function to open the modal
function openModal() {
const modal = document.getElementById("room-list-modal");
const modalContent = document.getElementById("room-list-modal-content");
const closeButton = document.getElementById("close-modal-button");
const roomsList = document.getElementById("rooms-list-ul").cloneNode(true);
document.getElementById("rooms-list-modal-content").innerHTML = ''; // Clear previous content
document.getElementById("rooms-list-modal-content").appendChild(roomsList);
modal.style.display = "flex";
modalContent.style.display = "block";
closeButton.style.display = "block";
}
// Function to close the modal
function closeModal() {
const modal = document.getElementById("room-list-modal");
const modalContent = document.getElementById("room-list-modal-content");
const closeButton = document.getElementById("close-modal-button");
modal.style.display = "none";
modalContent.style.display = "none";
closeButton.style.display = "none";
}
// Add event listener to the hamburger button
document.getElementById("hamburger-button").addEventListener("click", openModal);
</script>
</body>
</html>