Added a toggle button for the sidebar, implemented a responsive design (fixes #4) and made more minor improvements to the frontend
This commit is contained in:
parent
63706a3c64
commit
22ba6239c7
4 changed files with 140 additions and 58 deletions
|
@ -18,49 +18,57 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidepanel flex flex-column">
|
<div class="flex sidebar-container sidebar-hidden" id="sidebar-container">
|
||||||
<div class="max-width">Settings</div>
|
<button id="sidebar-toggle-open" class="icon-button">
|
||||||
<div class="settings flex flex-column">
|
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="M433 712V440L297 576l136 136ZM180 936q-24.75 0-42.375-17.625T120 876V276q0-24.75 17.625-42.375T180 216h600q24.75 0 42.375 17.625T840 276v600q0 24.75-17.625 42.375T780 936H180Zm393-60V276H180v600h393Z"/></svg>
|
||||||
<div class="setting flex">
|
</button>
|
||||||
<div>Assistant</div>
|
<button id="sidebar-toggle-close" class="icon-button hidden">
|
||||||
<div id="settings-label-assistant"></div>
|
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="M297 440v272l136-136-136-136ZM180 936q-24.75 0-42.375-17.625T120 876V276q0-24.75 17.625-42.375T180 216h600q24.75 0 42.375 17.625T840 276v600q0 24.75-17.625 42.375T780 936H180Zm393-60V276H180v600h393Z"/></svg>
|
||||||
|
</button>
|
||||||
|
<div class="sidebar flex flex-column">
|
||||||
|
<div class="max-width">Settings</div>
|
||||||
|
<div class="settings flex flex-column">
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>Assistant</div>
|
||||||
|
<div id="settings-label-assistant"></div>
|
||||||
|
</div>
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>max_tokens</div>
|
||||||
|
<div><input type="number" id="settings-max-tokens" min="16" value="100"></div>
|
||||||
|
</div>
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>temperature</div>
|
||||||
|
<div><input type="number" id="settings-temperature" min="0.0" max="2.0" step="0.01" value="0.8"></div>
|
||||||
|
</div>
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>top_p</div>
|
||||||
|
<div><input type="number" id="settings-top-p" min="0.0" max="1.0" step="0.01" value="0.95"></div>
|
||||||
|
</div>
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>top_k</div>
|
||||||
|
<div><input type="number" id="settings-top-k" min="0" step="1" value="40"></div>
|
||||||
|
</div>
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>repeat_penalty</div>
|
||||||
|
<div><input type="number" id="settings-repeat-penalty" min="0.0" step="0.01" value="1.1"></div>
|
||||||
|
</div>
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>presence_penalty</div>
|
||||||
|
<div><input type="number" id="settings-presence-penalty" min="-2.0" max="2.0" step="0.01" value="0"></div>
|
||||||
|
</div>
|
||||||
|
<div class="setting flex">
|
||||||
|
<div>frequency_penalty</div>
|
||||||
|
<div><input type="number" id="settings-frequency-penalty" min="-2.0" max="2.0" step="0.01" value="0"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting flex">
|
<div class="flex">
|
||||||
<div>max_tokens</div>
|
<button id="reset-settings-btn" class="icon-button">
|
||||||
<div><input type="number" id="settings-max-tokens" min="16" value="100"></div>
|
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="M480 896q-133 0-226.5-93.5T160 576q0-133 93.5-226.5T480 256q85 0 149 34.5T740 385V256h60v254H546v-60h168q-38-60-97-97t-137-37q-109 0-184.5 75.5T220 576q0 109 75.5 184.5T480 836q83 0 152-47.5T728 663h62q-29 105-115 169t-195 64Z"/></svg>
|
||||||
|
</button>
|
||||||
|
<button id="reset-history-btn" class="icon-button">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="m361 757 119-121 120 121 47-48-119-121 119-121-47-48-120 121-119-121-48 48 120 121-120 121 48 48ZM261 936q-24 0-42-18t-18-42V306h-41v-60h188v-30h264v30h188v60h-41v570q0 24-18 42t-42 18H261Z"/></svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting flex">
|
|
||||||
<div>temperature</div>
|
|
||||||
<div><input type="number" id="settings-temperature" min="0.0" max="2.0" step="0.01" value="0.8"></div>
|
|
||||||
</div>
|
|
||||||
<div class="setting flex">
|
|
||||||
<div>top_p</div>
|
|
||||||
<div><input type="number" id="settings-top-p" min="0.0" max="1.0" step="0.01" value="0.95"></div>
|
|
||||||
</div>
|
|
||||||
<div class="setting flex">
|
|
||||||
<div>top_k</div>
|
|
||||||
<div><input type="number" id="settings-top-k" min="0" step="1" value="40"></div>
|
|
||||||
</div>
|
|
||||||
<div class="setting flex">
|
|
||||||
<div>repeat_penalty</div>
|
|
||||||
<div><input type="number" id="settings-repeat-penalty" min="0.0" step="0.01" value="1.1"></div>
|
|
||||||
</div>
|
|
||||||
<div class="setting flex">
|
|
||||||
<div>presence_penalty</div>
|
|
||||||
<div><input type="number" id="settings-presence-penalty" min="-2.0" max="2.0" step="0.01" value="0"></div>
|
|
||||||
</div>
|
|
||||||
<div class="setting flex">
|
|
||||||
<div>frequency_penalty</div>
|
|
||||||
<div><input type="number" id="settings-frequency-penalty" min="-2.0" max="2.0" step="0.01" value="0"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex">
|
|
||||||
<button id="reset-settings-btn" class="icon-button">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="M480 896q-133 0-226.5-93.5T160 576q0-133 93.5-226.5T480 256q85 0 149 34.5T740 385V256h60v254H546v-60h168q-38-60-97-97t-137-37q-109 0-184.5 75.5T220 576q0 109 75.5 184.5T480 836q83 0 152-47.5T728 663h62q-29 105-115 169t-195 64Z"/></svg>
|
|
||||||
</button>
|
|
||||||
<button id="reset-history-btn" class="icon-button">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 96 960 960" width="48"><path d="m361 757 119-121 120 121 47-48-119-121 119-121-47-48-120 121-119-121-48 48 120 121-120 121 48 48ZM261 936q-24 0-42-18t-18-42V306h-41v-60h188v-30h264v30h188v60h-41v570q0 24-18 42t-42 18H261Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/ui/main.js"></script>
|
<script src="/ui/main.js"></script>
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
// Copyright (c) 2023 Julian Müller (ChaoticByte)
|
// Copyright (c) 2023 Julian Müller (ChaoticByte)
|
||||||
|
|
||||||
|
const isMobile = /Android|BlackBerry|iPhone|iPod|Opera Mini/i.test(navigator.userAgent);
|
||||||
|
|
||||||
// Fetch configuration and initialize Eucalyptus Chat Frontend
|
// Fetch configuration and initialize Eucalyptus Chat Frontend
|
||||||
|
|
||||||
fetch("/config")
|
fetch("/config")
|
||||||
|
@ -11,6 +13,9 @@ fetch("/config")
|
||||||
let conversation = [frontend_config.profile.conversation_prefix];
|
let conversation = [frontend_config.profile.conversation_prefix];
|
||||||
|
|
||||||
// Elements - Sidebar
|
// Elements - Sidebar
|
||||||
|
const sidebarOpenButton = document.getElementById("sidebar-toggle-open");
|
||||||
|
const sidebarCloseButton = document.getElementById("sidebar-toggle-close");
|
||||||
|
const sidebarContainer = document.getElementById("sidebar-container");
|
||||||
const settingsLabelAssistantNameElement = document.getElementById("settings-label-assistant");
|
const settingsLabelAssistantNameElement = document.getElementById("settings-label-assistant");
|
||||||
const settingsMaxTokensElement = document.getElementById("settings-max-tokens");
|
const settingsMaxTokensElement = document.getElementById("settings-max-tokens");
|
||||||
const settingsTemperatureElement = document.getElementById("settings-temperature");
|
const settingsTemperatureElement = document.getElementById("settings-temperature");
|
||||||
|
@ -19,15 +24,15 @@ fetch("/config")
|
||||||
const settingsRepeatPenaltyElement = document.getElementById("settings-repeat-penalty");
|
const settingsRepeatPenaltyElement = document.getElementById("settings-repeat-penalty");
|
||||||
const settingsPresencePenaltyElement = document.getElementById("settings-presence-penalty");
|
const settingsPresencePenaltyElement = document.getElementById("settings-presence-penalty");
|
||||||
const settingsFrequencyPenaltyElement = document.getElementById("settings-frequency-penalty");
|
const settingsFrequencyPenaltyElement = document.getElementById("settings-frequency-penalty");
|
||||||
const resetSettingsButtonElement = document.getElementById("reset-settings-btn");
|
const resetSettingsButton = document.getElementById("reset-settings-btn");
|
||||||
const resetHistoryButtonElement = document.getElementById("reset-history-btn");
|
const resetHistoryButton = document.getElementById("reset-history-btn");
|
||||||
|
|
||||||
settingsLabelAssistantNameElement.innerText = frontend_config.profile.name;
|
settingsLabelAssistantNameElement.innerText = frontend_config.profile.name;
|
||||||
|
|
||||||
// Elements - Main
|
// Elements - Main
|
||||||
const messageHistoryContainer = document.getElementById("messages");
|
const messageHistoryContainer = document.getElementById("messages");
|
||||||
const textInputElement = document.getElementById("text-input");
|
const textInputElement = document.getElementById("text-input");
|
||||||
const sendButtonElement = document.getElementById("send-btn");
|
const sendButton = document.getElementById("send-btn");
|
||||||
|
|
||||||
// API requests
|
// API requests
|
||||||
|
|
||||||
|
@ -116,7 +121,7 @@ fetch("/config")
|
||||||
messageRoleElem.innerText = role.name;
|
messageRoleElem.innerText = role.name;
|
||||||
let messageTextElem = document.createElement("div");
|
let messageTextElem = document.createElement("div");
|
||||||
messageTextElem.classList.add("message-text");
|
messageTextElem.classList.add("message-text");
|
||||||
messageTextElem.innerText = message;
|
messageTextElem.innerText = message.trim();
|
||||||
let messageElem = document.createElement("div");
|
let messageElem = document.createElement("div");
|
||||||
messageElem.classList.add("message");
|
messageElem.classList.add("message");
|
||||||
messageElem.classList.add(role.class);
|
messageElem.classList.add(role.class);
|
||||||
|
@ -141,9 +146,9 @@ fetch("/config")
|
||||||
settingsRepeatPenaltyElement.disabled = true;
|
settingsRepeatPenaltyElement.disabled = true;
|
||||||
settingsPresencePenaltyElement.disabled = true;
|
settingsPresencePenaltyElement.disabled = true;
|
||||||
settingsFrequencyPenaltyElement.disabled = true;
|
settingsFrequencyPenaltyElement.disabled = true;
|
||||||
resetSettingsButtonElement.disabled = true;
|
resetSettingsButton.disabled = true;
|
||||||
resetHistoryButtonElement.disabled = true;
|
resetHistoryButton.disabled = true;
|
||||||
sendButtonElement.disabled = true;
|
sendButton.disabled = true;
|
||||||
textInputElement.disabled = true;
|
textInputElement.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,12 +160,12 @@ fetch("/config")
|
||||||
settingsRepeatPenaltyElement.disabled = false;
|
settingsRepeatPenaltyElement.disabled = false;
|
||||||
settingsPresencePenaltyElement.disabled = false;
|
settingsPresencePenaltyElement.disabled = false;
|
||||||
settingsFrequencyPenaltyElement.disabled = false;
|
settingsFrequencyPenaltyElement.disabled = false;
|
||||||
resetSettingsButtonElement.disabled = false;
|
resetSettingsButton.disabled = false;
|
||||||
resetHistoryButtonElement.disabled = false;
|
resetHistoryButton.disabled = false;
|
||||||
sendButtonElement.disabled = false;
|
sendButton.disabled = false;
|
||||||
textInputElement.disabled = false;
|
textInputElement.disabled = false;
|
||||||
// focus text input
|
// focus text input
|
||||||
textInputElement.focus();
|
if (!isMobile) textInputElement.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function chat() {
|
async function chat() {
|
||||||
|
@ -187,11 +192,29 @@ fetch("/config")
|
||||||
messageHistoryContainer.innerText = "";
|
messageHistoryContainer.innerText = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sidebar
|
||||||
|
|
||||||
|
function toggleSidebar() {
|
||||||
|
if (sidebarContainer.classList.contains("sidebar-hidden")) {
|
||||||
|
sidebarCloseButton.classList.remove("hidden");
|
||||||
|
sidebarOpenButton.classList.add("hidden");
|
||||||
|
sidebarContainer.classList.remove("sidebar-hidden");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sidebarOpenButton.classList.remove("hidden");
|
||||||
|
sidebarCloseButton.classList.add("hidden");
|
||||||
|
sidebarContainer.classList.add("sidebar-hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Event Listeners
|
// Event Listeners
|
||||||
|
|
||||||
resetSettingsButtonElement.addEventListener("click", resetSettings);
|
sidebarOpenButton.addEventListener("click", toggleSidebar);
|
||||||
resetHistoryButtonElement.addEventListener("click", resetHistory);
|
sidebarCloseButton.addEventListener("click", toggleSidebar);
|
||||||
sendButtonElement.addEventListener("click", chat);
|
|
||||||
|
resetSettingsButton.addEventListener("click", resetSettings);
|
||||||
|
resetHistoryButton.addEventListener("click", resetHistory);
|
||||||
|
sendButton.addEventListener("click", chat);
|
||||||
|
|
||||||
textInputElement.addEventListener("keypress", e => {
|
textInputElement.addEventListener("keypress", e => {
|
||||||
// Send via Ctrl+Enter
|
// Send via Ctrl+Enter
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
--background2: #303030;
|
--background2: #303030;
|
||||||
--background3: #161616;
|
--background3: #161616;
|
||||||
--background4: #131313;
|
--background4: #131313;
|
||||||
|
--background5: #1a1a1a;
|
||||||
--button-bg: #3b3b3b;
|
--button-bg: #3b3b3b;
|
||||||
--button-bg2: #4f4f4f;
|
--button-bg2: #4f4f4f;
|
||||||
--icon-button-fill: #ffffff;
|
--icon-button-fill: #ffffff;
|
||||||
|
@ -27,11 +28,23 @@ input[type="number"] {
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidepanel {
|
.sidebar-container {
|
||||||
|
padding: .5rem;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--background5);
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container.sidebar-hidden > .sidebar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
margin-left: .5rem;
|
||||||
|
margin-right: .5rem;
|
||||||
|
margin-top: .4rem;
|
||||||
gap: .5rem;
|
gap: .5rem;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
padding: 1rem;
|
|
||||||
padding-left: 0;
|
|
||||||
min-width: fit-content;
|
min-width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +148,8 @@ button:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-button {
|
.icon-button {
|
||||||
|
width: fit-content;
|
||||||
|
height: fit-content;
|
||||||
padding: .2rem;
|
padding: .2rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -160,3 +175,39 @@ button:hover {
|
||||||
height: 2.2rem;
|
height: 2.2rem;
|
||||||
fill: var(--send-icon-button-fill);
|
fill: var(--send-icon-button-fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
|
||||||
|
body {
|
||||||
|
height: 100dvh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container.sidebar-hidden {
|
||||||
|
position: absolute;
|
||||||
|
width: unset;
|
||||||
|
height: unset;
|
||||||
|
left: auto;
|
||||||
|
right: 0;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-container > #sidebar-toggle-close {
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
margin-right: auto;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 117 KiB |
Reference in a new issue